Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- <!DOCTYPE html>
- <html lang="id">
- <head>
- <base target="_top">
- <meta charset="utf-8">
- <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
- <title>Online Attendance Records System</title>
- <!-- Google Fonts & Bootstrap -->
- <link href="https://fonts.googleapis.com/css2?family=Plus+Jakarta+Sans:wght@400;500;600;700;800&display=swap" rel="stylesheet">
- <link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet">
- <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
- <style>
- :root {
- --sea-deep: #002b5b;
- --sea-main: #0052d4;
- --sea-light: #00d2ff;
- --bg-body: #f8fafc;
- --card-border: rgba(255, 255, 255, 0.8);
- --shadow-sm: 0 2px 4px rgba(0,0,0,0.02);
- --shadow-md: 0 10px 25px -5px rgba(0,0,0,0.05);
- --glass: rgba(255, 255, 255, 0.9);
- }
- body {
- background-color: var(--bg-body);
- font-family: 'Plus Jakarta Sans', sans-serif;
- color: #1e293b;
- padding-bottom: 120px;
- }
- /* --- Professional Header --- */
- .header-enterprise {
- background: linear-gradient(135deg, var(--sea-deep) 0%, var(--sea-main) 50%, var(--sea-light) 100%);
- padding: 40px 0 80px;
- color: white;
- border-bottom-left-radius: 50px;
- border-bottom-right-radius: 50px;
- position: relative;
- box-shadow: 0 10px 30px rgba(0, 82, 212, 0.2);
- }
- .header-content {
- display: flex;
- align-items: center;
- justify-content: space-between;
- gap: 20px;
- }
- .logo-placeholder {
- width: 70px;
- height: 70px;
- background: rgba(255,255,255,0.15);
- backdrop-filter: blur(10px);
- border-radius: 15px;
- display: flex;
- align-items: center;
- justify-content: center;
- border: 1px solid rgba(255,255,255,0.2);
- }
- .logo-placeholder img { width: 50px; height: auto; }
- .brand-title h2 {
- font-weight: 800;
- letter-spacing: -1px;
- margin: 0;
- text-shadow: 0 2px 4px rgba(0,0,0,0.1);
- }
- /* --- Selector Styling --- */
- .class-selector-wrapper {
- max-width: 500px;
- margin: -40px auto 0;
- position: relative;
- z-index: 10;
- padding: 0 20px;
- }
- .custom-select-card {
- background: var(--glass);
- backdrop-filter: blur(15px);
- padding: 20px;
- border-radius: 24px;
- box-shadow: var(--shadow-md);
- border: 1px solid var(--card-border);
- }
- .form-select-custom {
- border-radius: 12px;
- border: 2px solid #e2e8f0;
- padding: 12px 20px;
- font-weight: 600;
- transition: all 0.3s;
- }
- .form-select-custom:focus {
- border-color: var(--sea-main);
- box-shadow: 0 0 0 4px rgba(0, 82, 212, 0.1);
- }
- /* --- List Section --- */
- .stats-bar {
- display: flex;
- justify-content: space-between;
- align-items: center;
- margin-bottom: 15px;
- padding: 0 10px;
- }
- .badge-stats {
- background: white;
- color: var(--sea-deep);
- padding: 8px 16px;
- border-radius: 12px;
- font-weight: 700;
- font-size: 0.9rem;
- box-shadow: var(--shadow-sm);
- border: 1px solid #e2e8f0;
- }
- .student-card {
- background: white;
- border-radius: 20px;
- padding: 15px 20px;
- margin-bottom: 12px;
- border: 1px solid #f1f5f9;
- transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
- display: flex;
- align-items: center;
- justify-content: space-between;
- gap: 15px;
- }
- .student-card:hover {
- transform: translateY(-3px);
- box-shadow: 0 12px 20px -5px rgba(0,0,0,0.05);
- border-color: var(--sea-light);
- }
- .student-identity {
- display: flex;
- align-items: center;
- gap: 15px;
- }
- .student-id-circle {
- width: 38px;
- height: 38px;
- background: #f1f5f9;
- color: var(--sea-deep);
- display: flex;
- align-items: center;
- justify-content: center;
- border-radius: 12px;
- font-weight: 800;
- font-size: 0.85rem;
- }
- .student-name {
- font-weight: 700;
- color: #334155;
- font-size: 1.05rem;
- }
- /* --- Radio Button Groups --- */
- .presence-btn-group {
- display: grid;
- grid-template-columns: repeat(6, 1fr);
- gap: 6px;
- background: #f8fafc;
- padding: 5px;
- border-radius: 14px;
- }
- .btn-check + .btn-pills {
- width: 42px;
- height: 42px;
- display: flex;
- align-items: center;
- justify-content: center;
- border-radius: 10px;
- font-weight: 700;
- font-size: 0.8rem;
- border: none;
- background: transparent;
- color: #94a3b8;
- transition: all 0.2s;
- cursor: pointer;
- }
- /* Active States Colors */
- .btn-check:checked + .btn-pills.h { background: #10b981; color: white; box-shadow: 0 4px 10px rgba(16, 185, 129, 0.3); }
- .btn-check:checked + .btn-pills.a { background: #ef4444; color: white; box-shadow: 0 4px 10px rgba(239, 68, 68, 0.3); }
- .btn-check:checked + .btn-pills.i { background: #3b82f6; color: white; box-shadow: 0 4px 10px rgba(59, 130, 246, 0.3); }
- .btn-check:checked + .btn-pills.s { background: #f59e0b; color: white; box-shadow: 0 4px 10px rgba(245, 158, 11, 0.3); }
- .btn-check:checked + .btn-pills.t { background: #64748b; color: white; box-shadow: 0 4px 10px rgba(100, 116, 139, 0.3); }
- .btn-check:checked + .btn-pills.b { background: #1e293b; color: white; box-shadow: 0 4px 10px rgba(30, 41, 59, 0.3); }
- /* --- Floating Footer --- */
- .fab-container {
- position: fixed;
- bottom: 30px;
- left: 50%;
- transform: translateX(-50%);
- width: 100%;
- max-width: 400px;
- padding: 0 25px;
- z-index: 100;
- }
- .btn-submit-modern {
- background: linear-gradient(135deg, var(--sea-deep) 0%, var(--sea-main) 100%);
- border: none;
- color: white;
- width: 100%;
- padding: 16px;
- border-radius: 20px;
- font-weight: 700;
- font-size: 1.1rem;
- box-shadow: 0 15px 30px rgba(0, 82, 212, 0.3);
- display: flex;
- align-items: center;
- justify-content: center;
- gap: 12px;
- transition: all 0.3s;
- }
- .btn-submit-modern:hover {
- transform: translateY(-5px);
- box-shadow: 0 20px 40px rgba(0, 82, 212, 0.4);
- }
- @media (max-width: 768px) {
- .header-enterprise { padding: 30px 0 60px; border-bottom-left-radius: 30px; border-bottom-right-radius: 30px; }
- .logo-placeholder { width: 50px; height: 50px; }
- .logo-placeholder img { width: 35px; }
- .brand-title h2 { font-size: 1.3rem; }
- .student-card { flex-direction: column; align-items: flex-start; }
- .presence-btn-group { width: 100%; }
- .btn-check + .btn-pills { width: 100%; }
- }
- </style>
- </head>
- <body>
- <!-- Professional Header -->
- <header class="header-enterprise">
- <div class="container">
- <div class="header-content">
- <!-- Logo Kiri -->
- <div class="logo-placeholder">
- <img src="https://cdn-icons-png.flaticon.com/512/2830/2830305.png" alt="Logo Left">
- </div>
- <div class="brand-title text-center">
- <p class="mb-1 text-uppercase fw-bold opacity-75" style="font-size: 0.75rem; letter-spacing: 2px;">Smart Education System</p>
- <h2>PRESENSI ONLINE</h2>
- <div class="mt-2 opacity-75 small">
- <i class="far fa-calendar-check me-1"></i> <span id="tanggalHariIni"></span>
- </div>
- </div>
- <!-- Logo Kanan -->
- <div class="logo-placeholder">
- <img src="https://cdn-icons-png.flaticon.com/512/5968/5968260.png" alt="Logo Right">
- </div>
- </div>
- </div>
- </header>
- <!-- Class Selector Box -->
- <section class="class-selector-wrapper">
- <div class="custom-select-card">
- <label class="form-label fw-bold text-muted mb-2 ps-1" style="font-size: 0.8rem;">PILIH UNIT/KELAS :</label>
- <select id="selectKelas" class="form-select form-select-custom" onchange="loadSiswaKelas(this.value)">
- <option value="" selected disabled>-- Pilih Kelas --</option>
- <option value="" disabled>Menghubungkan ke server...</option>
- </select>
- </div>
- </section>
- <!-- Main List Container -->
- <main class="container mt-5" style="max-width: 800px;">
- <!-- Loading State -->
- <div id="loading-spinner" class="text-center py-5">
- <div class="spinner-border text-primary mb-3" role="status" style="width: 3rem; height: 3rem;"></div>
- <p class="text-muted fw-bold">Sinkronisasi Database...</p>
- </div>
- <!-- Form Area -->
- <div id="formArea" style="display:none;">
- <div class="stats-bar">
- <h6 class="m-0 fw-800 text-uppercase" id="labelKelasTerpilih" style="color: var(--sea-deep); letter-spacing: 0.5px;"></h6>
- <div class="badge-stats" id="countBadge">
- <i class="fas fa-users me-2 text-primary"></i> Jumlah Siswa: <span id="jumlahSiswa">0</span>
- </div>
- </div>
- <div id="listSiswa">
- <!-- Cards injected here -->
- </div>
- </div>
- </main>
- <!-- Floating Action Button -->
- <div class="fab-container" id="submitArea" style="display:none;">
- <button type="button" class="btn btn-submit-modern" onclick="konfirmasiKirim()">
- <i class="fas fa-cloud-upload-alt"></i> SIMPAN PRESENSI
- </button>
- </div>
- <script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script>
- <script>
- // Set Tanggal
- document.getElementById('tanggalHariIni').innerText = new Date().toLocaleDateString('id-ID', {
- weekday: 'long', year: 'numeric', month: 'long', day: 'numeric'
- });
- // 1. Ambil Daftar Kelas
- google.script.run.withSuccessHandler(initKelas).getDaftarKelas();
- function initKelas(data) {
- var select = document.getElementById('selectKelas');
- select.innerHTML = '<option value="" selected disabled>-- Pilih Kelas --</option>';
- data.kelas.forEach(function(cls) {
- var option = document.createElement("option");
- option.text = cls; option.value = cls;
- select.add(option);
- });
- document.getElementById('loading-spinner').style.display = 'none';
- }
- // 2. Load Siswa
- function loadSiswaKelas(namaKelas) {
- if(!namaKelas) return;
- document.getElementById('loading-spinner').style.display = 'block';
- document.getElementById('formArea').style.display = 'none';
- document.getElementById('submitArea').style.display = 'none';
- google.script.run.withSuccessHandler(renderSiswa).getDaftarSiswa(namaKelas);
- }
- function renderSiswa(siswaList) {
- var container = document.getElementById('listSiswa');
- var namaKelas = document.getElementById('selectKelas').value;
- document.getElementById('labelKelasTerpilih').innerText = 'Daftar ' + namaKelas;
- document.getElementById('jumlahSiswa').innerText = siswaList.length;
- var html = '';
- if (!siswaList || siswaList.length === 0) {
- html = `<div class="text-center py-5"><img src="https://cdn-icons-png.flaticon.com/512/7486/7486744.png" style="width:80px; opacity:0.3" class="mb-3"><p class="text-muted">Data siswa tidak ditemukan pada sheet ${namaKelas}.</p></div>`;
- } else {
- siswaList.forEach(function(nama, index) {
- html += `
- <div class="student-card">
- <div class="student-identity">
- <div class="student-id-circle">${index + 1}</div>
- <div class="student-name">${nama}</div>
- </div>
- <div class="presence-btn-group" role="group">
- <input type="radio" class="btn-check" name="siswa${index}" id="h_${index}" value="H" checked>
- <label class="btn-pills h" for="h_${index}" title="Hadir">H</label>
- <input type="radio" class="btn-check" name="siswa${index}" id="a_${index}" value="A">
- <label class="btn-pills a" for="a_${index}" title="Alpha">A</label>
- <input type="radio" class="btn-check" name="siswa${index}" id="i_${index}" value="I">
- <label class="btn-pills i" for="i_${index}" title="Izin">I</label>
- <input type="radio" class="btn-check" name="siswa${index}" id="s_${index}" value="S">
- <label class="btn-pills s" for="s_${index}" title="Sakit">S</label>
- <input type="radio" class="btn-check" name="siswa${index}" id="t_${index}" value="T">
- <label class="btn-pills t" for="t_${index}" title="Terlambat">T</label>
- <input type="radio" class="btn-check" name="siswa${index}" id="b_${index}" value="B">
- <label class="btn-pills b" for="b_${index}" title="Bolos">B</label>
- </div>
- </div>`;
- });
- }
- container.innerHTML = html;
- document.getElementById('loading-spinner').style.display = 'none';
- document.getElementById('formArea').style.display = 'block';
- if(siswaList.length > 0) document.getElementById('submitArea').style.display = 'block';
- }
- function konfirmasiKirim() {
- Swal.fire({
- title: 'Simpan Kehadiran?',
- text: "Data akan dicatat ke sistem pusat.",
- icon: 'question',
- showCancelButton: true,
- confirmButtonColor: '#0052d4',
- cancelButtonColor: '#94a3b8',
- confirmButtonText: 'Ya, Simpan!',
- cancelButtonText: 'Batal',
- customClass: { popup: 'rounded-4' }
- }).then((result) => {
- if (result.isConfirmed) kirimData();
- })
- }
- function kirimData() {
- Swal.fire({
- title: 'Memproses...',
- html: 'Mohon tunggu sebentar',
- allowOutsideClick: false,
- didOpen: () => Swal.showLoading()
- });
- var cards = document.getElementsByClassName('student-card');
- var dataKehadiran = [];
- var namaKelas = document.getElementById('selectKelas').value;
- for (var i = 0; i < cards.length; i++) {
- var checkedRadio = document.querySelector(`input[name="siswa${i}"]:checked`);
- dataKehadiran.push(checkedRadio ? checkedRadio.value : 'A');
- }
- google.script.run.withSuccessHandler(function(resp) {
- Swal.fire({
- icon: 'success',
- title: 'Berhasil!',
- text: resp,
- timer: 2000,
- showConfirmButton: false
- });
- }).simpanPresensi(dataKehadiran, namaKelas);
- }
- </script>
- </body>
- </html>
Add Comment
Please, Sign In to add comment