Tutorial

Aplikasi Kelulusan Online

10 April 2026
Hendi
293 Views
Bagikan:

Panduan Pembuatan Aplikasi Pengumuman Kelulusan Online

Sistem ini menggunakan Google Sheets sebagai database dan Google Apps Script (GAS) sebagai server dan antarmuka web.

Langkah 1: Persiapan Google Sheets (Database)

  1. Buka Google Sheets dan buat spreadsheet baru dengan nama "Data Kelulusan 2026" (atau sesuai keinginan).

  2. Buat 3 Sheet (Tab) di bagian bawah dengan nama yang harus persis seperti berikut:

    • Siswa

    • Admin

    • Pengaturan

  3. Isi Header (Baris 1) pada masing-masing Sheet:

    • Sheet Siswa:

      • A1: NISN (akan digunakan sebagai username siswa)

      • B1: Password

      • C1: Nama Lengkap

      • D1: Kelas

      • E1: Status Kelulusan (Isi dengan: LULUS / TIDAK LULUS)

      • F1: Nilai Rata-rata

      • (Silakan isi data sampel di baris 2, 3, dst)

    • Sheet Admin:

      • A1: Username

      • B1: Password

      • (Isi baris 2 dengan data login admin, misalnya A2: admin, B2: admin123)

    • Sheet Pengaturan:

      • A1: Pengaturan

      • B1: Nilai

      • A2: Tanggal Kelulusan

      • B2: 2026-05-15T10:00 (Format: YYYY-MM-DDTHH:MM, akan bisa diubah via aplikasi)

Langkah 2: Memasukkan Kode Google Apps Script

  1. Pada Google Sheets yang sama, klik menu Ekstensi > Apps Script.

  2. Akan terbuka tab baru. Hapus semua kode bawaan yang ada di Code.gs.

  3. Copy dan paste kode di bawah ini ke dalam file Code.gs:

File 1: Code.gs

function doGet(e) {
  return HtmlService.createHtmlOutputFromFile('Index')
      .setTitle('Aplikasi Pengumuman Kelulusan')
      .addMetaTag('viewport', 'width=device-width, initial-scale=1')
      .setXFrameOptionsMode(HtmlService.XFrameOptionsMode.ALLOWALL);
}

// Fungsi mengambil data dari sheet
function getSheetData(sheetName) {
  const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(sheetName);
  if(!sheet) return null;
  return sheet.getDataRange().getDisplayValues();
}

// Fungsi Login
function prosesLogin(username, password) {
  // Cek Admin
  const adminData = getSheetData('Admin');
  if(adminData) {
    for(let i = 1; i < adminData.length; i++) {
      if(adminData[i][0] === username && adminData[i][1] === password) {
        return { success: true, role: 'admin', username: username };
      }
    }
  }
  
  // Cek Siswa
  const siswaData = getSheetData('Siswa');
  if(siswaData) {
    for(let i = 1; i < siswaData.length; i++) {
      if(siswaData[i][0] === username && siswaData[i][1] === password) {
        return {
          success: true,
          role: 'siswa',
          nisn: siswaData[i][0],
          nama: siswaData[i][2],
          kelas: siswaData[i][3],
          status: siswaData[i][4],
          nilai: siswaData[i][5]
        };
      }
    }
  }
  
  return { success: false, message: 'Username atau password salah!' };
}

// Mengambil Tanggal Kelulusan
function getPengaturan() {
  const data = getSheetData('Pengaturan');
  if(data && data.length > 1) {
     return { tanggal: data[1][1] }; // Mengambil sel B2
  }
  return { tanggal: '' };
}

// Simpan Tanggal Kelulusan
function savePengaturan(tanggal) {
  const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Pengaturan');
  sheet.getRange(2, 2).setValue(tanggal);
  return { success: true, message: 'Tanggal berhasil diupdate!' };
}

// Ambil Semua Data Siswa (Untuk Admin)
function getAllSiswa() {
  const data = getSheetData('Siswa');
  let result = [];
  let statistik = { total: 0, lulus: 0, tidakLulus: 0 };
  
  if(data) {
    for(let i = 1; i < data.length; i++) {
      let status = data[i][4].toUpperCase();
      result.push({
        nisn: data[i][0],
        password: data[i][1],
        nama: data[i][2],
        kelas: data[i][3],
        status: status,
        nilai: data[i][5],
        row: i + 1
      });
      
      statistik.total++;
      if(status === 'LULUS') statistik.lulus++;
      else if(status === 'TIDAK LULUS') statistik.tidakLulus++;
    }
  }
  return { data: result, stats: statistik };
}

// Update Data Siswa (Oleh Admin)
function updateSiswa(row, nisn, password, nama, kelas, status, nilai) {
  try {
    const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Siswa');
    sheet.getRange(row, 1, 1, 6).setValues([[nisn, password, nama, kelas, status, nilai]]);
    return { success: true, message: 'Data siswa berhasil diperbarui!' };
  } catch (error) {
    return { success: false, message: error.toString() };
  }
}

  1. Simpan file Code.gs dengan menekan ikon Disket (Save).

  2. Di sebelah kiri (di bawah Code.gs), klik ikon [ + ] (Tambahkan file) > Pilih HTML.

  3. Beri nama file: Index (harus Index dengan I besar, tanpa .html karena ekstensi ditambahkan otomatis).

  4. Copy dan paste seluruh kode di bawah ini ke dalam file Index.html:

File 2: Index.html

<!DOCTYPE html>
<html lang="id">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Sistem Kelulusan Online</title>
    <script src="[https://cdn.tailwindcss.com](https://cdn.tailwindcss.com)"></script>
    <script src="[https://cdn.jsdelivr.net/npm/sweetalert2@11](https://cdn.jsdelivr.net/npm/sweetalert2@11)"></script>
    <style>
        .hidden { display: none !important; }
        .spinner { border: 4px solid rgba(0,0,0,0.1); width: 36px; height: 36px; border-radius: 50%; border-left-color: #3b82f6; animation: spin 1s linear infinite; }
        @keyframes spin { 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); } }
    </style>
</head>
<body class="bg-gray-100 font-sans text-gray-800">

    <!-- Loading Overlay -->
    <div id="loading" class="fixed inset-0 bg-white bg-opacity-80 z-50 flex flex-col justify-center items-center hidden">
        <div class="spinner"></div>
        <p class="mt-4 text-gray-600 font-medium">Memproses data...</p>
    </div>

    <!-- VIEW: LOGIN -->
    <div id="view-login" class="min-h-screen flex items-center justify-center p-4">
        <div class="bg-white p-8 rounded-xl shadow-lg w-full max-w-md">
            <div class="text-center mb-8">
                <h1 class="text-2xl font-bold text-blue-600">Pengumuman Kelulusan</h1>
                <p class="text-gray-500 mt-2">Silakan login untuk melanjutkan</p>
            </div>
            <form id="loginForm" onsubmit="handleLogin(event)">
                <div class="mb-4">
                    <label class="block text-gray-700 text-sm font-bold mb-2">Username / NISN</label>
                    <input type="text" id="username" required class="w-full px-4 py-2 border rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500">
                </div>
                <div class="mb-6">
                    <label class="block text-gray-700 text-sm font-bold mb-2">Password</label>
                    <input type="password" id="password" required class="w-full px-4 py-2 border rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500">
                </div>
                <button type="submit" class="w-full bg-blue-600 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded-lg transition duration-200">
                    Masuk
                </button>
            </form>
        </div>
    </div>

    <!-- MAIN APP CONTAINER (After Login) -->
    <div id="view-app" class="hidden min-h-screen flex flex-col md:flex-row">
        
        <!-- SIDEBAR -->
        <aside class="bg-blue-800 w-full md:w-64 text-white p-6 flex flex-col">
            <h2 class="text-xl font-bold mb-6 border-b border-blue-600 pb-4">Menu Panel</h2>
            <nav class="flex-1 space-y-2" id="nav-menu">
                <!-- Dinamis diisi lewat JS -->
            </nav>
            <button onclick="logout()" class="mt-auto bg-red-500 hover:bg-red-600 px-4 py-2 rounded text-sm font-bold w-full text-left transition">
                Logout
            </button>
        </aside>

        <!-- CONTENT AREA -->
        <main class="flex-1 p-6 md:p-8 bg-gray-100 overflow-y-auto w-full">
            
            <!-- ADMIN VIEWS -->
            <div id="admin-dashboard" class="hidden">
                <h2 class="text-3xl font-bold text-gray-800 mb-6">Dashboard Admin</h2>
                <div class="grid grid-cols-1 md:grid-cols-3 gap-6 mb-8">
                    <div class="bg-white p-6 rounded-lg shadow-sm border-l-4 border-blue-500">
                        <h3 class="text-gray-500 text-sm">Total Siswa</h3>
                        <p class="text-3xl font-bold text-gray-800" id="stat-total">0</p>
                    </div>
                    <div class="bg-white p-6 rounded-lg shadow-sm border-l-4 border-green-500">
                        <h3 class="text-gray-500 text-sm">Lulus</h3>
                        <p class="text-3xl font-bold text-green-600" id="stat-lulus">0</p>
                    </div>
                    <div class="bg-white p-6 rounded-lg shadow-sm border-l-4 border-red-500">
                        <h3 class="text-gray-500 text-sm">Tidak Lulus</h3>
                        <p class="text-3xl font-bold text-red-600" id="stat-tidak">0</p>
                    </div>
                </div>
            </div>

            <div id="admin-datasiswa" class="hidden">
                <h2 class="text-3xl font-bold text-gray-800 mb-6">Data Siswa</h2>
                <div class="bg-white rounded-lg shadow-sm overflow-x-auto">
                    <table class="w-full text-left border-collapse">
                        <thead>
                            <tr class="bg-gray-50 border-b">
                                <th class="p-4 text-sm font-semibold text-gray-600">NISN</th>
                                <th class="p-4 text-sm font-semibold text-gray-600">Nama Lengkap</th>
                                <th class="p-4 text-sm font-semibold text-gray-600">Kelas</th>
                                <th class="p-4 text-sm font-semibold text-gray-600">Status</th>
                                <th class="p-4 text-sm font-semibold text-gray-600">Aksi</th>
                            </tr>
                        </thead>
                        <tbody id="table-siswa">
                            <!-- Data injected here -->
                        </tbody>
                    </table>
                </div>
            </div>

            <div id="admin-pengaturan" class="hidden">
                <h2 class="text-3xl font-bold text-gray-800 mb-6">Pengaturan Sistem</h2>
                <div class="bg-white p-6 rounded-lg shadow-sm max-w-md">
                    <label class="block text-gray-700 text-sm font-bold mb-2">Tanggal & Waktu Kelulusan Dibuka</label>
                    <input type="datetime-local" id="input-tanggal" class="w-full px-4 py-2 border rounded-lg mb-4 focus:ring-2 focus:ring-blue-500">
                    <button onclick="simpanPengaturan()" class="bg-blue-600 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded-lg">
                        Simpan Pengaturan
                    </button>
                </div>
            </div>

            <!-- SISWA VIEWS -->
            <div id="siswa-dashboard" class="hidden text-center mt-10">
                <h2 class="text-3xl font-bold text-gray-800 mb-2">Hitung Mundur Pengumuman</h2>
                <p class="text-gray-600 mb-8">Waktu tersisa sebelum pengumuman kelulusan dapat diakses.</p>
                
                <div class="flex justify-center gap-4 text-white">
                    <div class="bg-blue-600 p-4 rounded-lg w-24">
                        <span id="cd-hari" class="text-4xl font-bold">00</span>
                        <div class="text-xs mt-1">Hari</div>
                    </div>
                    <div class="bg-blue-600 p-4 rounded-lg w-24">
                        <span id="cd-jam" class="text-4xl font-bold">00</span>
                        <div class="text-xs mt-1">Jam</div>
                    </div>
                    <div class="bg-blue-600 p-4 rounded-lg w-24">
                        <span id="cd-menit" class="text-4xl font-bold">00</span>
                        <div class="text-xs mt-1">Menit</div>
                    </div>
                    <div class="bg-blue-600 p-4 rounded-lg w-24">
                        <span id="cd-detik" class="text-4xl font-bold">00</span>
                        <div class="text-xs mt-1">Detik</div>
                    </div>
                </div>
                
                <div id="countdown-msg" class="mt-8 text-lg font-bold text-green-600 hidden">
                    Waktu pengumuman telah tiba! Silakan cek menu Kelulusan.
                </div>
            </div>

            <div id="siswa-kelulusan" class="hidden">
                <h2 class="text-3xl font-bold text-gray-800 mb-6">Hasil Kelulusan</h2>
                <div id="hasil-terkunci" class="bg-yellow-100 border-l-4 border-yellow-500 text-yellow-700 p-4 rounded">
                    Pengumuman belum dibuka. Silakan kembali lagi setelah waktu hitung mundur selesai.
                </div>
                
                <div id="hasil-buka" class="hidden bg-white p-8 rounded-lg shadow-sm max-w-2xl mx-auto border-t-8">
                    <div class="text-center mb-8">
                        <h3 class="text-2xl font-bold" id="res-status-title">STATUS</h3>
                        <p class="text-gray-500 mt-2">Tahun Ajaran 2025/2026</p>
                    </div>
                    <table class="w-full text-left text-lg">
                        <tr class="border-b"><th class="py-3 text-gray-600">NISN</th><td class="font-semibold" id="res-nisn"></td></tr>
                        <tr class="border-b"><th class="py-3 text-gray-600">Nama Lengkap</th><td class="font-semibold" id="res-nama"></td></tr>
                        <tr class="border-b"><th class="py-3 text-gray-600">Kelas</th><td class="font-semibold" id="res-kelas"></td></tr>
                        <tr class="border-b"><th class="py-3 text-gray-600">Nilai Rata-rata</th><td class="font-semibold" id="res-nilai"></td></tr>
                        <tr><th class="py-4 text-gray-600">Status Akhir</th><td class="font-bold text-xl" id="res-status"></td></tr>
                    </table>
                </div>
            </div>

        </main>
    </div>

    <!-- MODAL EDIT SISWA -->
    <div id="modal-edit" class="fixed inset-0 bg-black bg-opacity-50 flex justify-center items-center z-40 hidden">
        <div class="bg-white p-6 rounded-lg shadow-lg w-full max-w-lg">
            <h3 class="text-xl font-bold mb-4">Edit Data Siswa</h3>
            <input type="hidden" id="edit-row">
            <div class="grid grid-cols-2 gap-4 mb-4">
                <div>
                    <label class="block text-sm font-bold mb-1">NISN</label>
                    <input type="text" id="edit-nisn" class="w-full border p-2 rounded">
                </div>
                <div>
                    <label class="block text-sm font-bold mb-1">Password</label>
                    <input type="text" id="edit-pass" class="w-full border p-2 rounded">
                </div>
                <div class="col-span-2">
                    <label class="block text-sm font-bold mb-1">Nama Lengkap</label>
                    <input type="text" id="edit-nama" class="w-full border p-2 rounded">
                </div>
                <div>
                    <label class="block text-sm font-bold mb-1">Kelas</label>
                    <input type="text" id="edit-kelas" class="w-full border p-2 rounded">
                </div>
                <div>
                    <label class="block text-sm font-bold mb-1">Nilai Rata-rata</label>
                    <input type="number" step="0.01" id="edit-nilai" class="w-full border p-2 rounded">
                </div>
                <div class="col-span-2">
                    <label class="block text-sm font-bold mb-1">Status Kelulusan</label>
                    <select id="edit-status" class="w-full border p-2 rounded">
                        <option value="LULUS">LULUS</option>
                        <option value="TIDAK LULUS">TIDAK LULUS</option>
                    </select>
                </div>
            </div>
            <div class="flex justify-end gap-2">
                <button onclick="closeModal()" class="bg-gray-400 hover:bg-gray-500 text-white px-4 py-2 rounded">Batal</button>
                <button onclick="simpanEditSiswa()" class="bg-blue-600 hover:bg-blue-700 text-white px-4 py-2 rounded">Simpan Data</button>
            </div>
        </div>
    </div>

    <!-- SCRIPTS -->
    <script>
        let userData = null;
        let targetDate = null;
        let timerInterval = null;

        function showLoading() { document.getElementById('loading').classList.remove('hidden'); }
        function hideLoading() { document.getElementById('loading').classList.add('hidden'); }

        // --- SISTEM LOGIN ---
        function handleLogin(e) {
            e.preventDefault();
            showLoading();
            const u = document.getElementById('username').value;
            const p = document.getElementById('password').value;

            google.script.run.withSuccessHandler(res => {
                if(res.success) {
                    userData = res;
                    setupUI();
                } else {
                    hideLoading();
                    Swal.fire('Gagal!', res.message, 'error');
                }
            }).prosesLogin(u, p);
        }

        function logout() {
            userData = null;
            clearInterval(timerInterval);
            document.getElementById('view-app').classList.add('hidden');
            document.getElementById('view-login').classList.remove('hidden');
            document.getElementById('loginForm').reset();
        }

        // --- SETUP ANTARMUKA ---
        function setupUI() {
            document.getElementById('view-login').classList.add('hidden');
            document.getElementById('view-app').classList.remove('hidden');
            const nav = document.getElementById('nav-menu');
            nav.innerHTML = '';

            if(userData.role === 'admin') {
                nav.innerHTML = `
                    <button onclick="switchTab('admin-dashboard')" class="block w-full text-left px-4 py-2 hover:bg-blue-700 rounded transition">Halaman Utama</button>
                    <button onclick="switchTab('admin-datasiswa')" class="block w-full text-left px-4 py-2 hover:bg-blue-700 rounded transition">Data Siswa</button>
                    <button onclick="switchTab('admin-pengaturan')" class="block w-full text-left px-4 py-2 hover:bg-blue-700 rounded transition">Pengaturan</button>
                `;
                switchTab('admin-dashboard');
                loadAdminData();
            } else {
                nav.innerHTML = `
                    <button onclick="switchTab('siswa-dashboard')" class="block w-full text-left px-4 py-2 hover:bg-blue-700 rounded transition">Dashboard</button>
                    <button onclick="switchTab('siswa-kelulusan')" class="block w-full text-left px-4 py-2 hover:bg-blue-700 rounded transition">Cek Kelulusan</button>
                `;
                switchTab('siswa-dashboard');
                loadSiswaData();
            }
        }

        function switchTab(tabId) {
            const views = ['admin-dashboard', 'admin-datasiswa', 'admin-pengaturan', 'siswa-dashboard', 'siswa-kelulusan'];
            views.forEach(id => {
                const el = document.getElementById(id);
                if(el) el.classList.add('hidden');
            });
            document.getElementById(tabId).classList.remove('hidden');
        }

        // --- FUNGSI ADMIN ---
        function loadAdminData() {
            // Load Settings
            google.script.run.withSuccessHandler(res => {
                document.getElementById('input-tanggal').value = res.tanggal;
            }).getPengaturan();

            // Load Siswa & Stats
            google.script.run.withSuccessHandler(res => {
                document.getElementById('stat-total').innerText = res.stats.total;
                document.getElementById('stat-lulus').innerText = res.stats.lulus;
                document.getElementById('stat-tidak').innerText = res.stats.tidakLulus;

                let trs = '';
                res.data.forEach(s => {
                    let badge = s.status === 'LULUS' ? 'bg-green-100 text-green-800' : 'bg-red-100 text-red-800';
                    trs += `<tr class="border-b hover:bg-gray-50">
                        <td class="p-4">${s.nisn}</td>
                        <td class="p-4">${s.nama}</td>
                        <td class="p-4">${s.kelas}</td>
                        <td class="p-4"><span class="px-2 py-1 rounded text-xs font-bold ${badge}">${s.status}</span></td>
                        <td class="p-4">
                            <button onclick='bukaEdit(${JSON.stringify(s)})' class="text-blue-600 hover:text-blue-800 text-sm font-bold">Edit</button>
                        </td>
                    </tr>`;
                });
                document.getElementById('table-siswa').innerHTML = trs;
                hideLoading();
            }).getAllSiswa();
        }

        function simpanPengaturan() {
            showLoading();
            const val = document.getElementById('input-tanggal').value;
            google.script.run.withSuccessHandler(res => {
                hideLoading();
                Swal.fire('Sukses!', res.message, 'success');
            }).savePengaturan(val);
        }

        function bukaEdit(data) {
            document.getElementById('edit-row').value = data.row;
            document.getElementById('edit-nisn').value = data.nisn;
            document.getElementById('edit-pass').value = data.password;
            document.getElementById('edit-nama').value = data.nama;
            document.getElementById('edit-kelas').value = data.kelas;
            document.getElementById('edit-nilai').value = data.nilai;
            document.getElementById('edit-status').value = data.status;
            document.getElementById('modal-edit').classList.remove('hidden');
        }

        function closeModal() {
            document.getElementById('modal-edit').classList.add('hidden');
        }

        function simpanEditSiswa() {
            showLoading();
            const row = document.getElementById('edit-row').value;
            const nisn = document.getElementById('edit-nisn').value;
            const pass = document.getElementById('edit-pass').value;
            const nama = document.getElementById('edit-nama').value;
            const kelas = document.getElementById('edit-kelas').value;
            const status = document.getElementById('edit-status').value;
            const nilai = document.getElementById('edit-nilai').value;

            google.script.run.withSuccessHandler(res => {
                closeModal();
                if(res.success) {
                    Swal.fire('Sukses!', res.message, 'success');
                    loadAdminData(); // Reload table
                } else {
                    hideLoading();
                    Swal.fire('Error', res.message, 'error');
                }
            }).updateSiswa(row, nisn, pass, nama, kelas, status, nilai);
        }

        // --- FUNGSI SISWA ---
        function loadSiswaData() {
            google.script.run.withSuccessHandler(res => {
                if(res.tanggal) {
                    targetDate = new Date(res.tanggal).getTime();
                    mulaiHitungMundur();
                } else {
                    targetDate = new Date().getTime() - 1000; // Force open jika belum diset
                    mulaiHitungMundur();
                }
                hideLoading();
            }).getPengaturan();
        }

        function mulaiHitungMundur() {
            if(timerInterval) clearInterval(timerInterval);
            
            timerInterval = setInterval(() => {
                const now = new Date().getTime();
                const distance = targetDate - now;

                if (distance < 0) {
                    clearInterval(timerInterval);
                    bukaHasilSiswa();
                    return;
                }

                document.getElementById('cd-hari').innerText = String(Math.floor(distance / (1000 * 60 * 60 * 24))).padStart(2, '0');
                document.getElementById('cd-jam').innerText = String(Math.floor((distance % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60))).padStart(2, '0');
                document.getElementById('cd-menit').innerText = String(Math.floor((distance % (1000 * 60 * 60)) / (1000 * 60))).padStart(2, '0');
                document.getElementById('cd-detik').innerText = String(Math.floor((distance % (1000 * 60)) / 1000)).padStart(2, '0');
            }, 1000);
        }

        function bukaHasilSiswa() {
            // Dashboard Msg
            document.getElementById('cd-hari').innerText = "00";
            document.getElementById('cd-jam').innerText = "00";
            document.getElementById('cd-menit').innerText = "00";
            document.getElementById('cd-detik').innerText = "00";
            document.getElementById('countdown-msg').classList.remove('hidden');

            // Cek Kelulusan View
            document.getElementById('hasil-terkunci').classList.add('hidden');
            const boxHasil = document.getElementById('hasil-buka');
            boxHasil.classList.remove('hidden');

            document.getElementById('res-nisn').innerText = userData.nisn;
            document.getElementById('res-nama').innerText = userData.nama;
            document.getElementById('res-kelas').innerText = userData.kelas;
            document.getElementById('res-nilai').innerText = userData.nilai;
            
            const isLulus = userData.status.toUpperCase() === 'LULUS';
            const statEl = document.getElementById('res-status');
            statEl.innerText = userData.status;
            
            if(isLulus) {
                boxHasil.classList.add('border-green-500');
                statEl.classList.add('text-green-600');
                document.getElementById('res-status-title').innerText = "SELAMAT! ANDA DINYATAKAN LULUS";
                document.getElementById('res-status-title').classList.add('text-green-600');
            } else {
                boxHasil.classList.add('border-red-500');
                statEl.classList.add('text-red-600');
                document.getElementById('res-status-title').innerText = "MOHON MAAF, ANDA BELUM LULUS";
                document.getElementById('res-status-title').classList.add('text-red-600');
            }
        }
    </script>
</body>
</html>

Langkah 3: Publish Menjadi Web App

  1. Setelah kedua file (Code.gs dan Index.html) disimpan, klik tombol biru Terapkan (Deploy) di sudut kanan atas > Pilih Deployment baru.

  2. Klik ikon roda gigi (Pilih jenis) > Pilih Aplikasi Web (Web app).

  3. Isi kolom sebagai berikut:

    • Deskripsi: Pengumuman Kelulusan Versi 1

    • Jalankan sebagai: Saya (email_anda@gmail.com)

    • Yang memiliki akses: Siapa saja (Penting agar siswa bisa membuka link tanpa login akun Google)

  4. Klik Terapkan.

  5. Jika muncul jendela "Otorisasi Diperlukan":

    • Klik Beri otorisasi (Review permissions).

    • Pilih akun email Google Anda.

    • Klik tombol Advanced (Lanjutan) di kiri bawah.

    • Klik Buka Project Tidak Aman (Go to Project unsafe).

    • Klik Izinkan (Allow).

  6. Anda akan mendapatkan URL Web App (link panjang berakhiran .../exec).

  7. Selesai! Bagikan link tersebut kepada siswa atau sematkan di website sekolah.

Fitur dan Petunjuk Penggunaan

  • Akses Admin: Buka URL Web App, masukkan username dan password yang ada di Sheet Admin.

  • Menu Admin:

    • Melihat rekap data (total, yang lulus, dan yang tidak lulus).

    • Melihat tabel siswa dan melakukan Edit Data (Mengubah nilai, nama, status kelulusan, dan sandi).

    • Mengatur Tanggal Kelulusan (siswa tidak bisa melihat hasil sebelum jam/tanggal tersebut lewat).

  • Akses Siswa: Buka URL Web App, masukkan NISN sebagai username dan password sesuai yang diatur di Sheet Siswa.

  • Menu Siswa:

    • Melihat timer hitung mundur pengumuman di Dashboard.

    • Melihat data kelulusan (Hanya terbuka jika timer hitung mundur telah mencapai angka 0).

Suka artikel ini?

Bagikan kepada teman-teman Anda.

Artikel Terkait

Paling Banyak Dilihat

Rekomendasi

Nama Produk

Rp 0 Beli