Selasa, 19 Agustus 2025

Latihan - Absensi 2

 












Apps Script 

// Menerima data dari form
function doPost(e) {
  var ss = SpreadsheetApp.getActiveSpreadsheet();
  var sheet = ss.getSheetByName("TAbsensiOnline");

  if (!sheet) {
    sheet = ss.insertSheet("TAbsensiOnline");
    sheet.appendRow(["Kelas", "Nis", "NamaMurid", "Tanggal", "Keterangan", "WaktuPengiriman"]);
  }

  var data = [
    e.parameter.kelas,
    e.parameter.nis,
    e.parameter.namamurid,
    e.parameter.tanggal,
    e.parameter.keterangan,
    e.parameter.waktupengiriman
  ];

  sheet.appendRow(data);

  return ContentService.createTextOutput("✅ Data berhasil disimpan!");
}

// Menampilkan halaman rekap absensi + tombol cetak
function doGet() {
  var ss = SpreadsheetApp.getActiveSpreadsheet();
  var sheet = ss.getSheetByName("TAbsensiOnline");
  var data = sheet.getDataRange().getValues();

  var html = '<html><head><title>Rekap Absensi</title><style>';
  html += 'body { font-family: sans-serif; padding: 20px; }';
  html += 'table { border-collapse: collapse; width: 100%; }';
  html += 'th, td { border: 1px solid #ccc; padding: 8px; text-align: left; }';
  html += 'th { background-color: #0077cc; color: white; }';
  html += 'button { margin-top: 20px; padding: 10px 20px; font-weight: bold; }';
  html += '</style></head><body>';
  html += '<h2>📝 Rekap Absensi SMK Percontohan Pervekt Jawa Timur</h2>';
  html += '<table><tr>';

  // Header
  data[0].forEach(function (col) {
    html += '<th>' + col + '</th>';
  });
  html += '</tr>';

  // Data
  for (var i = 1; i < data.length; i++) {
    html += '<tr>';
    data[i].forEach(function (cell) {
      html += '<td>' + (cell || '') + '</td>';
    });
    html += '</tr>';
  }

  html += '</table>';
  html += '<button onclick="window.print()">🖨️ Cetak Rekap</button>';
  html += '</body></html>';

  return HtmlService.createHtmlOutput(html)
    .setTitle("Rekap Absensi")
    .setXFrameOptionsMode(HtmlService.XFrameOptionsMode.ALLOWALL);
}

HTML Awal

<!DOCTYPE html>
<html lang="id">
<head>
  <meta charset="UTF-8">
  <title>Absensi SMK Pervekt Jawa Timurn</title>
  <style>
    body {
      font-family: sans-serif;
      max-width: 600px;
      margin: 30px auto;
      background: #f1f1f1;
      padding: 20px;
      border-radius: 10px;
    }
    input, select, textarea, button {
      width: 100%;
      padding: 10px;
      margin-top: 10px;
      border-radius: 5px;
      border: 1px solid #ccc;
    }
    button {
      background-color: #0077cc;
      color: white;
      font-weight: bold;
      margin-top: 20px;
    }
    .clock {
      background: #fff;
      padding: 10px;
      border-radius: 5px;
      margin-bottom: 20px;
      text-align: center;
      font-size: 16px;
      font-weight: bold;
    }
  </style>
</head>
<body>
  <h2>📘 Absensi Online</h2>
  <h3>SMK Percontohan Pervekt Jawa Timur</h3>

  <div class="clock">
    ⏰ Waktu Indonesia Barat (WIB) : <span id="clock-wit">Memuat waktu...</span>
  </div>

  <form id="form-absensi" method="POST" action="https://script.google.com/macros/s/AKfycbyQ8NobWDeZcDOzpbJaUHj9Sn7QQUsrKzyUZzztKl1OLhsFyLLDxO1lSlGfhdI27JSj/exec">
    <label>Kelas:</label>
    <select name="kelas" required>
      <option value="Kelas 10">Kelas 10</option>
    </select>

    <label>NIS:</label>
    <textarea name="nis" placeholder="Masukkan NIS murid" required></textarea>

    <label>Nama Murid:</label>
    <input type="text" name="namamurid" placeholder="Masukkan nama murid" required>

    <label>Tanggal:</label>
    <input type="date" name="tanggal" required>

    <label>Keterangan:</label>
    <select name="keterangan" required>
      <option value="Hadir">Hadir</option>
      <option value="Sakit">Sakit</option>
      <option value="Izin">Izin</option>
      <option value="Alpa">Alpa</option>
    </select>

    <!-- Hidden input untuk waktu pengiriman -->
    <input type="hidden" id="waktupengiriman" name="waktupengiriman">

    <button type="submit">Kirim Absensi</button>
  </form>

  <script>
    const form = document.getElementById("form-absensi");
    const clockEl = document.getElementById("clock-wit");

    function updateClockWIT() {
      const now = new Date();
      const formatter = new Intl.DateTimeFormat("id-ID", {
        timeZone: "Asia/Jayapura",
        year: "numeric",
        month: "2-digit",
        day: "2-digit",
        hour: "2-digit",
        minute: "2-digit",
        second: "2-digit",
        hour12: false
      });
      clockEl.textContent = formatter.format(now);
    }

    setInterval(updateClockWIT, 1000);
    updateClockWIT();

    form.addEventListener("submit", function () {
      const now = new Date();
      const formattedTime = new Intl.DateTimeFormat("id-ID", {
        timeZone: "Asia/Jayapura",
        year: "numeric",
        month: "2-digit",
        day: "2-digit",
        hour: "2-digit",
        minute: "2-digit",
        second: "2-digit",
        hour12: false
      }).format(now);

      document.getElementById("waktupengiriman").value = formattedTime;
    });
  </script>
</body>
</html>

PROMPT

URL Data Murid : https://docs.google.com/spreadsheets/d/e/2PACX-1vSYDuI2iERadVoehPHnsLlcxb612aSTrGhWHQziUsZplm6PGH_ypzihbMRcvsiOL5Lf9p0GXgGqbAXW/pub?output=csv

URL Data Guru : https://docs.google.com/spreadsheets/d/e/2PACX-1vT-RTmCcIYrOlxFIsaLNLmOyEodVNK3HFzyxaur_n8JEM1Gn4BJgZOmVwBE64PpuAEtX4iGW5eqiPei/pub?output=csv

URL Logo : https://freeimghost.net/images/2025/08/19/Logo-pervekt1.png
Email : indieschool80@gmail.com

URL Background : https://freeimghost.net/images/2025/08/19/sekolah1.jpg

URL Script : https://script.google.com/macros/s/AKfycbyQ8NobWDeZcDOzpbJaUHj9Sn7QQUsrKzyUZzztKl1OLhsFyLLDxO1lSlGfhdI27JSj/exec
id Script : AKfycbyQ8NobWDeZcDOzpbJaUHj9Sn7QQUsrKzyUZzztKl1OLhsFyLLDxO1lSlGfhdI27JSj

Sebuah ilustrasi digital halaman sekolah menengah atas kejuruan SMK yang ramai. Terlihat siswa-siswi SMK mengenakan seragam putih-abu khas SMK Indonesia. Beberapa siswa sedang berbicara dengan guru perempuan di dekat gerbang, beberapa siswa lainnya berjalan menuju kelas, dan beberapa lagi sedang berada di halaman sekolah (seperti membaca pengumuman, berdiskusi dengan teman, menuntun sepeda). Gedung sekolah bertuliskan "SMK Negeri Percontohan Pervekt Jawa Timur" terlihat jelas di latar belajang. Suasana pagi yang cerah dan penuh semangat, dengan pepohonan rindang di sekeliling halaman.

PROMPT
==============
Prompt Tambahan :
Pastikan ketika tombol "Kirim Absensi" diklik, maka Riwayat absensi akan terkirim secara otomatis ke google apps script

Revisi bagian di bawah ini :
Ubah tampilan absensinya ke dalam bentuk sidebar dimana sebelah kiri terdiri atas : absensi, data murid, dan data guru
Data Murid : https://docs.google.com/spreadsheets/d/e/2PACX-1vSYDuI2iERadVoehPHnsLlcxb612aSTrGhWHQziUsZplm6PGH_ypzihbMRcvsiOL5Lf9p0GXgGqbAXW/pub?output=csv
Data Guru : https://docs.google.com/spreadsheets/d/e/2PACX-1vT-RTmCcIYrOlxFIsaLNLmOyEodVNK3HFzyxaur_n8JEM1Gn4BJgZOmVwBE64PpuAEtX4iGW5eqiPei/pub?output=csv

Revisi bagian di bawah ini:
  1. untuk menu data murid, diambil dari data murid (No - kolom A, Nis - kolom B, Nisn - kolom C, Nama Murid - Kolom D)
  2. untuk menu data guru, diambil dari data guru (No - kolom A, Nama Guru - kolom B, Nip - kolom C, Jabatan - Kolom D, Nomor WA - kolom F)

Revisi bagian di bawah ini :
1. logo diganti dengan : https://freeimghost.net/images/2025/08/19/Logo-pervekt1.png
2. di bawah data guru, tambahkn foto profil guru yang sumber datanya diambil dari data guru kolom E
3. di samping kanan foto profil guru, tambahkn nama guru, nip, telepon, dan email
4. tambahkan padanan warna gradient sebagai warna pada halaman : #000066, #ff0066, #660000
5. tambahkan footer : @2025 SMK Percontohan Pervekt Jawa Timur - Hak Cipta Dilindungi

Revisi bagian di bawah ini
  1. tambahkan running text di bagian atas tajuk : Daftar Hadir - SMK Percontohan Pervekt Jawa Timur
  2. Tambahkan sebuah pop-up yang muncul ketika tombol kirim absensi diklik dimana pop-up tersebut menjelaskan bahwa daftar hadirtelah dikirim dan berikan padanan warna gradient #000066, #ff0066, #660000
  3. Tambahkn kode warna #ff0066 pada latar belakang running text tambahkan kode warna  #ff0066 pada setiap garis tepi tombol
  4. Tambahkan halaman login degan Username : admin Password : admin1, dengan warna gradient tombol login :#000066, #ff0066, #660000. Latar belakang halaman login : https://freeimghost.net/images/2025/08/19/sekolah1.jpg 

Source Code Final Absensi.html

<!DOCTYPE html>
<html lang="id">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Absensi SMK Pervekt Jawa Timur</title>
  <script src="https://cdn.tailwindcss.com"></script>
  <style>
    .gradient-bg {
      background: linear-gradient(135deg, #000066 0%, #ff0066 50%, #660000 100%);
    }
    .card-shadow {
      box-shadow: 0 10px 25px rgba(0,0,0,0.1);
    }
    .pulse-animation {
      animation: pulse 2s infinite;
    }
    @keyframes pulse {
      0%, 100% { opacity: 1; }
      50% { opacity: 0.7; }
    }
    .sidebar-item {
      transition: all 0.3s ease;
    }
    .sidebar-item:hover {
      background-color: rgba(255, 255, 255, 0.1);
      transform: translateX(5px);
    }
    .sidebar-item.active {
      background-color: rgba(255, 255, 255, 0.2);
      border-left: 4px solid #fbbf24;
    }
    @keyframes marquee {
      0% { transform: translateX(100%); }
      100% { transform: translateX(-100%); }
    }
    .animate-marquee {
      animation: marquee 20s linear infinite;
    }
    .popup-overlay {
      background-color: rgba(0, 0, 0, 0.5);
      backdrop-filter: blur(5px);
    }
    .popup-content {
      background: linear-gradient(135deg, #000066 0%, #ff0066 50%, #660000 100%);
      animation: popupSlide 0.3s ease-out;
    }
    @keyframes popupSlide {
      from {
        opacity: 0;
        transform: scale(0.8) translateY(-20px);
      }
      to {
        opacity: 1;
        transform: scale(1) translateY(0);
      }
    }
  </style>
</head>
<body class="gradient-bg min-h-screen">
  <!-- Login Page -->
  <div id="login-page" class="fixed inset-0 z-50 flex items-center justify-center" style="background-image: url('https://freeimghost.net/images/2025/08/19/sekolah1.jpg'); background-size: cover; background-position: center;">
    <div class="absolute inset-0 bg-black bg-opacity-50"></div>
    <div class="relative bg-white rounded-xl card-shadow p-8 w-full max-w-md mx-4">
      <div class="text-center mb-8">
        <img src="https://freeimghost.net/images/2025/08/19/Logo-pervekt1.png" alt="Logo SMK Pervekt" class="w-20 h-20 mx-auto mb-4 rounded-lg" onerror="this.style.display='none';">
        <h1 class="text-2xl font-bold text-gray-800">SMK Pervekt</h1>
        <p class="text-gray-600">Sistem Absensi Online</p>
      </div>
     
      <form id="login-form" class="space-y-6">
        <div>
          <label class="block text-sm font-medium text-gray-700 mb-2">Username:</label>
          <input type="text" id="username" required
                 class="w-full px-4 py-3 border-2 border-pink-500 rounded-lg focus:ring-2 focus:ring-pink-500 focus:border-transparent">
        </div>
       
        <div>
          <label class="block text-sm font-medium text-gray-700 mb-2">Password:</label>
          <input type="password" id="password" required
                 class="w-full px-4 py-3 border-2 border-pink-500 rounded-lg focus:ring-2 focus:ring-pink-500 focus:border-transparent">
        </div>
       
        <button type="submit" class="w-full py-3 px-4 rounded-lg text-white font-bold transition duration-200 transform hover:scale-105" style="background: linear-gradient(135deg, #000066 0%, #ff0066 50%, #660000 100%);">
          🔐 Masuk
        </button>
      </form>
     
      <div id="login-error" class="hidden mt-4 p-3 bg-red-100 border border-red-400 text-red-700 rounded-lg text-sm text-center">
        Username atau password salah!
      </div>
    </div>
  </div>

  <!-- Running Text -->
  <div class="bg-pink-500 text-white py-2 overflow-hidden">
    <div class="whitespace-nowrap animate-marquee">
      <span class="text-lg font-bold">🎓 Daftar Hadir - SMK Percontohan Pervekt Jawa Timur 🎓 Sistem Absensi Online Terpadu 🎓 Selamat Datang di Portal Akademik 🎓</span>
    </div>
  </div>

  <div id="main-app" class="flex h-screen hidden">
    <!-- Sidebar -->
    <div class="w-64 bg-gray-800 text-white flex flex-col">
      <!-- Header -->
      <div class="p-6 border-b border-gray-700">
        <div class="flex items-center mb-3">
          <img src="https://freeimghost.net/images/2025/08/19/Logo-pervekt1.png" alt="Logo SMK Pervekt" class="w-12 h-12 mr-3 rounded-lg" onerror="this.style.display='none';">
          <div>
            <h1 class="text-xl font-bold">SMK Pervekt</h1>
            <p class="text-sm text-gray-300">Jawa Timur</p>
          </div>
        </div>
      </div>

      <!-- Navigation -->
      <nav class="flex-1 p-4">
        <ul class="space-y-2">
          <li>
            <button onclick="showSection('absensi')" class="sidebar-item active w-full text-left px-4 py-3 rounded-lg flex items-center" id="nav-absensi">
              <span class="mr-3">✏️</span>
              <span>Absensi</span>
            </button>
          </li>
          <li>
            <button onclick="showSection('data-murid')" class="sidebar-item w-full text-left px-4 py-3 rounded-lg flex items-center" id="nav-data-murid">
              <span class="mr-3">👨‍🎓</span>
              <span>Data Murid</span>
            </button>
          </li>
          <li>
            <button onclick="showSection('data-guru')" class="sidebar-item w-full text-left px-4 py-3 rounded-lg flex items-center" id="nav-data-guru">
              <span class="mr-3">👨‍🏫</span>
              <span>Data Guru</span>
            </button>
          </li>
        </ul>
      </nav>

      <!-- Footer -->
      <div class="p-4 border-t border-gray-700">
        <div class="bg-green-600 text-green-100 px-3 py-2 rounded text-sm text-center">
          🚀 Sistem Aktif
        </div>
      </div>
    </div>

    <!-- Main Content -->
    <div class="flex-1 overflow-auto">
      <!-- Absensi Section -->
      <div id="section-absensi" class="p-8">
        <div class="max-w-6xl mx-auto">
          <div class="mb-8">
            <h2 class="text-3xl font-bold text-white mb-2">✏️ Form Absensi</h2>
            <p class="text-blue-100">Sistem absensi online SMK Percontohan Pervekt Jawa Timur</p>
          </div>

          <div class="grid lg:grid-cols-2 gap-8">
            <!-- Form Absensi -->
            <div class="bg-white rounded-xl card-shadow p-6">
              <h3 class="text-2xl font-bold text-gray-800 mb-6">📝 Input Absensi</h3>

              <!-- Clock -->
              <div class="bg-blue-50 border-l-4 border-blue-500 p-4 mb-6 rounded">
                <div class="flex items-center">
                  <span class="text-blue-600 mr-2"></span>
                  <div>
                    <p class="text-sm text-blue-600 font-medium">Waktu Indonesia Timur (WIT)</p>
                    <p id="clock-wit" class="text-lg font-bold text-blue-800 pulse-animation">Memuat waktu...</p>
                  </div>
                </div>
              </div>

              <form id="form-absensi" class="space-y-4">
                <div>
                  <label class="block text-sm font-medium text-gray-700 mb-2">Kelas:</label>
                  <select name="kelas" required class="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent">
                    <option value="Kelas 10">Kelas 10</option>
                    <option value="Kelas 11">Kelas 11</option>
                    <option value="Kelas 12">Kelas 12</option>
                  </select>
                </div>

                <div>
                  <label class="block text-sm font-medium text-gray-700 mb-2">NIS:</label>
                  <input type="text" name="nis" placeholder="Masukkan NIS murid" required
                         class="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent">
                </div>

                <div>
                  <label class="block text-sm font-medium text-gray-700 mb-2">Nama Murid:</label>
                  <input type="text" name="namamurid" placeholder="Masukkan nama murid" required
                         class="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent">
                </div>

                <div>
                  <label class="block text-sm font-medium text-gray-700 mb-2">Tanggal:</label>
                  <input type="date" name="tanggal" required
                         class="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent">
                </div>

                <div>
                  <label class="block text-sm font-medium text-gray-700 mb-2">Keterangan:</label>
                  <select name="keterangan" required class="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent">
                    <option value="Hadir">✅ Hadir</option>
                    <option value="Sakit">🤒 Sakit</option>
                    <option value="Izin">📝 Izin</option>
                    <option value="Alpa">❌ Alpa</option>
                  </select>
                </div>

                <button type="submit" class="w-full bg-blue-600 hover:bg-blue-700 text-white font-bold py-3 px-4 rounded-lg border-2 border-pink-500 transition duration-200 transform hover:scale-105">
                  📤 Kirim Absensi
                </button>
              </form>

              <!-- Success Message -->
              <div id="success-message" class="hidden mt-4"></div>
            </div>

            <!-- Riwayat Absensi -->
            <div class="bg-white rounded-xl card-shadow p-6">
              <div class="flex justify-between items-center mb-6">
                <h3 class="text-2xl font-bold text-gray-800">📊 Riwayat Absensi</h3>
                <button id="clear-data" class="bg-red-500 hover:bg-red-600 text-white px-4 py-2 rounded-lg border-2 border-pink-500 text-sm font-medium transition duration-200">
                  🗑️ Hapus Semua
                </button>
              </div>

              <div id="attendance-list" class="space-y-3 max-h-96 overflow-y-auto">
                <div class="text-center text-gray-500 py-8">
                  <p class="text-lg">📝 Belum ada data absensi</p>
                  <p class="text-sm">Isi form untuk mulai mencatat absensi</p>
                </div>
              </div>

              <!-- Statistics -->
              <div id="stats" class="hidden mt-6 grid grid-cols-2 gap-4">
                <div class="bg-green-50 p-4 rounded-lg text-center">
                  <div class="text-2xl font-bold text-green-600" id="hadir-count">0</div>
                  <div class="text-sm text-green-700">Hadir</div>
                </div>
                <div class="bg-red-50 p-4 rounded-lg text-center">
                  <div class="text-2xl font-bold text-red-600" id="absent-count">0</div>
                  <div class="text-sm text-red-700">Tidak Hadir</div>
                </div>
              </div>
            </div>
          </div>
        </div>
      </div>

      <!-- Data Murid Section -->
      <div id="section-data-murid" class="p-8 hidden">
        <div class="max-w-6xl mx-auto">
          <div class="mb-8">
            <h2 class="text-3xl font-bold text-white mb-2">👨‍🎓 Data Murid</h2>
            <p class="text-blue-100">Daftar lengkap murid SMK Percontohan Pervekt Jawa Timur</p>
          </div>

          <div class="bg-white rounded-xl card-shadow p-6">
            <div class="flex justify-between items-center mb-6">
              <h3 class="text-2xl font-bold text-gray-800">📋 Daftar Murid</h3>
              <div class="flex items-center space-x-4">
                <input type="text" id="search-murid" placeholder="Cari nama atau NIS..."
                       class="px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent">
                <button onclick="loadDataMurid()" class="bg-blue-600 hover:bg-blue-700 text-white px-4 py-2 rounded-lg border-2 border-pink-500 font-medium">
                  🔄 Refresh
                </button>
              </div>
            </div>

            <div id="loading-murid" class="text-center py-8">
              <div class="inline-block animate-spin rounded-full h-8 w-8 border-b-2 border-blue-600"></div>
              <p class="mt-2 text-gray-600">Memuat data murid...</p>
            </div>

            <div id="murid-table" class="hidden overflow-x-auto">
              <table class="w-full table-auto">
                <thead>
                  <tr class="bg-gray-50">
                    <th class="px-4 py-3 text-left text-sm font-medium text-gray-700">No</th>
                    <th class="px-4 py-3 text-left text-sm font-medium text-gray-700">NIS</th>
                    <th class="px-4 py-3 text-left text-sm font-medium text-gray-700">NISN</th>
                    <th class="px-4 py-3 text-left text-sm font-medium text-gray-700">Nama Murid</th>
                  </tr>
                </thead>
                <tbody id="murid-tbody" class="divide-y divide-gray-200">
                </tbody>
              </table>
            </div>

            <div id="murid-stats" class="hidden mt-6 grid grid-cols-3 gap-4">
              <div class="bg-blue-50 p-4 rounded-lg text-center">
                <div class="text-2xl font-bold text-blue-600" id="total-murid">0</div>
                <div class="text-sm text-blue-700">Total Murid</div>
              </div>
              <div class="bg-green-50 p-4 rounded-lg text-center">
                <div class="text-2xl font-bold text-green-600" id="kelas-10">0</div>
                <div class="text-sm text-green-700">Dengan NIS</div>
              </div>
              <div class="bg-purple-50 p-4 rounded-lg text-center">
                <div class="text-2xl font-bold text-purple-600" id="kelas-11-12">0</div>
                <div class="text-sm text-purple-700">Dengan NISN</div>
              </div>
            </div>
          </div>
        </div>
      </div>

      <!-- Data Guru Section -->
      <div id="section-data-guru" class="p-8 hidden">
        <div class="max-w-6xl mx-auto">
          <div class="mb-8">
            <h2 class="text-3xl font-bold text-white mb-2">👨‍🏫 Data Guru</h2>
            <p class="text-blue-100">Daftar lengkap guru SMK Percontohan Pervekt Jawa Timur</p>
          </div>

          <div class="bg-white rounded-xl card-shadow p-6">
            <div class="flex justify-between items-center mb-6">
              <h3 class="text-2xl font-bold text-gray-800">📋 Daftar Guru</h3>
              <div class="flex items-center space-x-4">
                <input type="text" id="search-guru" placeholder="Cari nama, NIP, atau jabatan..."
                       class="px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent">
                <button onclick="loadDataGuru()" class="bg-blue-600 hover:bg-blue-700 text-white px-4 py-2 rounded-lg border-2 border-pink-500 font-medium">
                  🔄 Refresh
                </button>
              </div>
            </div>

            <div id="loading-guru" class="text-center py-8">
              <div class="inline-block animate-spin rounded-full h-8 w-8 border-b-2 border-blue-600"></div>
              <p class="mt-2 text-gray-600">Memuat data guru...</p>
            </div>

            <div id="guru-table" class="hidden overflow-x-auto">
              <table class="w-full table-auto">
                <thead>
                  <tr class="bg-gray-50">
                    <th class="px-4 py-3 text-left text-sm font-medium text-gray-700">No</th>
                    <th class="px-4 py-3 text-left text-sm font-medium text-gray-700">Nama Guru</th>
                    <th class="px-4 py-3 text-left text-sm font-medium text-gray-700">NIP</th>
                    <th class="px-4 py-3 text-left text-sm font-medium text-gray-700">Jabatan</th>
                    <th class="px-4 py-3 text-left text-sm font-medium text-gray-700">Nomor WA</th>
                  </tr>
                </thead>
                <tbody id="guru-tbody" class="divide-y divide-gray-200">
                </tbody>
              </table>
            </div>

            <div id="guru-stats" class="hidden mt-6 grid grid-cols-2 gap-4">
              <div class="bg-blue-50 p-4 rounded-lg text-center">
                <div class="text-2xl font-bold text-blue-600" id="total-guru">0</div>
                <div class="text-sm text-blue-700">Total Guru</div>
              </div>
              <div class="bg-green-50 p-4 rounded-lg text-center">
                <div class="text-2xl font-bold text-green-600" id="mata-pelajaran">0</div>
                <div class="text-sm text-green-700">Dengan NIP</div>
              </div>
            </div>

            <!-- Teacher Profile Cards -->
            <div id="guru-profiles" class="hidden mt-8">
              <h4 class="text-xl font-bold text-gray-800 mb-6">👥 Profil Guru</h4>
              <div id="guru-profile-grid" class="grid md:grid-cols-2 lg:grid-cols-3 gap-6">
                <!-- Profile cards will be inserted here -->
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>

  <!-- Success Popup -->
  <div id="success-popup" class="fixed inset-0 z-50 flex items-center justify-center popup-overlay hidden">
    <div class="popup-content rounded-xl p-8 max-w-md mx-4 text-center text-white">
      <div class="mb-6">
        <div class="w-20 h-20 bg-white bg-opacity-20 rounded-full flex items-center justify-center mx-auto mb-4">
          <span class="text-4xl"></span>
        </div>
        <h3 class="text-2xl font-bold mb-2">Berhasil!</h3>
        <p class="text-lg">Daftar hadir telah dikirim</p>
      </div>
      <button onclick="closeSuccessPopup()" class="bg-white bg-opacity-20 hover:bg-opacity-30 text-white px-6 py-2 rounded-lg font-medium transition duration-200">
        Tutup
      </button>
    </div>
  </div>

  <!-- Footer -->
  <footer class="bg-gray-800 text-white py-4 text-center">
    <p class="text-sm">© 2025 SMK Percontohan Pervekt Jawa Timur - Hak Cipta Dilindungi</p>
  </footer>

  <script>
    // Global variables
    let muridData = [];
    let guruData = [];
    const clockEl = document.getElementById("clock-wit");
    const form = document.getElementById("form-absensi");
    const successMessage = document.getElementById("success-message");
    const attendanceList = document.getElementById("attendance-list");
    const clearDataBtn = document.getElementById("clear-data");
    const statsEl = document.getElementById("stats");
    const hadirCountEl = document.getElementById("hadir-count");
    const absentCountEl = document.getElementById("absent-count");

    // Set today's date as default
    document.querySelector('input[name="tanggal"]').value = new Date().toISOString().split('T')[0];

    // Update clock for WIT (UTC+9)
    function updateClockWIT() {
      const now = new Date();
      const witTime = new Date(now.getTime() + (9 * 60 * 60 * 1000));
      const formatter = new Intl.DateTimeFormat("id-ID", {
        year: "numeric",
        month: "2-digit",
        day: "2-digit",
        hour: "2-digit",
        minute: "2-digit",
        second: "2-digit",
        hour12: false
      });
      clockEl.textContent = formatter.format(witTime);
    }

    setInterval(updateClockWIT, 1000);
    updateClockWIT();

    // Navigation functions
    function showSection(sectionName) {
      // Hide all sections
      document.querySelectorAll('[id^="section-"]').forEach(section => {
        section.classList.add('hidden');
      });
     
      // Remove active class from all nav items
      document.querySelectorAll('.sidebar-item').forEach(item => {
        item.classList.remove('active');
      });
     
      // Show selected section
      document.getElementById(`section-${sectionName}`).classList.remove('hidden');
      document.getElementById(`nav-${sectionName}`).classList.add('active');
     
      // Load data if needed
      if (sectionName === 'data-murid' && muridData.length === 0) {
        loadDataMurid();
      } else if (sectionName === 'data-guru' && guruData.length === 0) {
        loadDataGuru();
      }
    }

    // Load data murid from Google Sheets
    async function loadDataMurid() {
      const loadingEl = document.getElementById('loading-murid');
      const tableEl = document.getElementById('murid-table');
      const statsEl = document.getElementById('murid-stats');
     
      loadingEl.classList.remove('hidden');
      tableEl.classList.add('hidden');
      statsEl.classList.add('hidden');
     
      try {
        const response = await fetch('https://docs.google.com/spreadsheets/d/e/2PACX-1vSYDuI2iERadVoehPHnsLlcxb612aSTrGhWHQziUsZplm6PGH_ypzihbMRcvsiOL5Lf9p0GXgGqbAXW/pub?output=csv');
        const csvText = await response.text();
       
        // Parse CSV
        const lines = csvText.split('\n');
        const headers = lines[0].split(',');
        muridData = [];
       
        for (let i = 1; i < lines.length; i++) {
          if (lines[i].trim()) {
            const values = lines[i].split(',');
            muridData.push({
              no: values[0]?.trim() || '',
              nis: values[1]?.trim() || '',
              nisn: values[2]?.trim() || '',
              nama: values[3]?.trim() || ''
            });
          }
        }
       
        displayMuridData(muridData);
        updateMuridStats(muridData);
       
      } catch (error) {
        console.error('Error loading murid data:', error);
        loadingEl.innerHTML = `
          <div class="text-center py-8 text-red-600">
            <p>❌ Gagal memuat data murid</p>
            <p class="text-sm">Periksa koneksi internet Anda</p>
          </div>
        `;
      }
    }

    function displayMuridData(data) {
      const tbody = document.getElementById('murid-tbody');
      const loadingEl = document.getElementById('loading-murid');
      const tableEl = document.getElementById('murid-table');
     
      tbody.innerHTML = data.map((murid, index) => `
        <tr class="hover:bg-gray-50">
          <td class="px-4 py-3 text-sm text-gray-900">${murid.no}</td>
          <td class="px-4 py-3 text-sm font-medium text-gray-900">${murid.nis}</td>
          <td class="px-4 py-3 text-sm text-gray-900">${murid.nisn}</td>
          <td class="px-4 py-3 text-sm text-gray-900">${murid.nama}</td>
        </tr>
      `).join('');
     
      loadingEl.classList.add('hidden');
      tableEl.classList.remove('hidden');
    }

    function updateMuridStats(data) {
      const totalMurid = data.length;
      const withNIS = data.filter(m => m.nis && m.nis.trim() !== '').length;
      const withNISN = data.filter(m => m.nisn && m.nisn.trim() !== '').length;
     
      document.getElementById('total-murid').textContent = totalMurid;
      document.getElementById('kelas-10').textContent = withNIS;
      document.getElementById('kelas-11-12').textContent = withNISN;
      document.getElementById('murid-stats').classList.remove('hidden');
    }

    // Load data guru from Google Sheets
    async function loadDataGuru() {
      const loadingEl = document.getElementById('loading-guru');
      const tableEl = document.getElementById('guru-table');
      const statsEl = document.getElementById('guru-stats');
     
      loadingEl.classList.remove('hidden');
      tableEl.classList.add('hidden');
      statsEl.classList.add('hidden');
     
      try {
        const response = await fetch('https://docs.google.com/spreadsheets/d/e/2PACX-1vT-RTmCcIYrOlxFIsaLNLmOyEodVNK3HFzyxaur_n8JEM1Gn4BJgZOmVwBE64PpuAEtX4iGW5eqiPei/pub?output=csv');
        const csvText = await response.text();
       
        // Parse CSV
        const lines = csvText.split('\n');
        const headers = lines[0].split(',');
        guruData = [];
       
        for (let i = 1; i < lines.length; i++) {
          if (lines[i].trim()) {
            const values = lines[i].split(',');
            guruData.push({
              no: values[0]?.trim() || '',
              nama: values[1]?.trim() || '',
              nip: values[2]?.trim() || '',
              jabatan: values[3]?.trim() || '',
              foto: values[4]?.trim() || '',
              nomorWA: values[5]?.trim() || '',
              email: values[6]?.trim() || ''
            });
          }
        }
       
        displayGuruData(guruData);
        updateGuruStats(guruData);
        displayGuruProfiles(guruData);
       
      } catch (error) {
        console.error('Error loading guru data:', error);
        loadingEl.innerHTML = `
          <div class="text-center py-8 text-red-600">
            <p>❌ Gagal memuat data guru</p>
            <p class="text-sm">Periksa koneksi internet Anda</p>
          </div>
        `;
      }
    }

    function displayGuruData(data) {
      const tbody = document.getElementById('guru-tbody');
      const loadingEl = document.getElementById('loading-guru');
      const tableEl = document.getElementById('guru-table');
     
      tbody.innerHTML = data.map((guru, index) => `
        <tr class="hover:bg-gray-50">
          <td class="px-4 py-3 text-sm text-gray-900">${guru.no}</td>
          <td class="px-4 py-3 text-sm font-medium text-gray-900">${guru.nama}</td>
          <td class="px-4 py-3 text-sm text-gray-900">${guru.nip}</td>
          <td class="px-4 py-3 text-sm text-gray-900">${guru.jabatan}</td>
          <td class="px-4 py-3 text-sm text-blue-600">
            ${guru.nomorWA ? `<a href="https://wa.me/${guru.nomorWA.replace(/\D/g, '')}" target="_blank" class="hover:underline">📱 ${guru.nomorWA}</a>` : '-'}
          </td>
        </tr>
      `).join('');
     
      loadingEl.classList.add('hidden');
      tableEl.classList.remove('hidden');
    }

    function updateGuruStats(data) {
      const totalGuru = data.length;
      const withNIP = data.filter(g => g.nip && g.nip.trim() !== '').length;
     
      document.getElementById('total-guru').textContent = totalGuru;
      document.getElementById('mata-pelajaran').textContent = withNIP;
      document.getElementById('guru-stats').classList.remove('hidden');
    }

    function displayGuruProfiles(data) {
      const profileGrid = document.getElementById('guru-profile-grid');
      const profilesSection = document.getElementById('guru-profiles');
     
      profileGrid.innerHTML = data.map((guru, index) => `
        <div class="bg-white rounded-xl card-shadow p-6 hover:shadow-lg transition-shadow duration-300">
          <div class="flex items-start space-x-4">
            <div class="flex-shrink-0">
              <img src="${guru.foto || 'https://via.placeholder.com/80x80/e5e7eb/6b7280?text=👤'}"
                   alt="Foto ${guru.nama}"
                   class="w-20 h-20 rounded-full object-cover border-2 border-gray-200"
                   onerror="this.src='https://via.placeholder.com/80x80/e5e7eb/6b7280?text=👤';">
            </div>
            <div class="flex-1 min-w-0">
              <h5 class="text-lg font-bold text-gray-900 mb-2">${guru.nama}</h5>
              <div class="space-y-1 text-sm text-gray-600">
                <p><span class="font-medium">NIP:</span> ${guru.nip || '-'}</p>
                <p><span class="font-medium">Jabatan:</span> ${guru.jabatan || '-'}</p>
                <p><span class="font-medium">Telepon:</span>
                  ${guru.nomorWA ? `<a href="https://wa.me/${guru.nomorWA.replace(/\D/g, '')}" target="_blank" class="text-blue-600 hover:underline">📱 ${guru.nomorWA}</a>` : '-'}
                </p>
                <p><span class="font-medium">Email:</span>
                  ${guru.email ? `<a href="mailto:${guru.email}" class="text-blue-600 hover:underline">📧 ${guru.email}</a>` : '-'}
                </p>
              </div>
            </div>
          </div>
        </div>
      `).join('');
     
      profilesSection.classList.remove('hidden');
    }

    // Search functionality
    document.getElementById('search-murid').addEventListener('input', function(e) {
      const searchTerm = e.target.value.toLowerCase();
      const filteredData = muridData.filter(murid =>
        murid.nama.toLowerCase().includes(searchTerm) ||
        murid.nis.toLowerCase().includes(searchTerm)
      );
      displayMuridData(filteredData);
    });

    document.getElementById('search-guru').addEventListener('input', function(e) {
      const searchTerm = e.target.value.toLowerCase();
      const filteredData = guruData.filter(guru =>
        guru.nama.toLowerCase().includes(searchTerm) ||
        guru.nip.toLowerCase().includes(searchTerm) ||
        guru.jabatan.toLowerCase().includes(searchTerm)
      );
      displayGuruData(filteredData);
    });

    // Attendance functions (same as before)
    function loadAttendanceData() {
      const data = JSON.parse(localStorage.getItem('attendanceData') || '[]');
      displayAttendanceData(data);
      updateStats(data);
    }

    function displayAttendanceData(data) {
      if (data.length === 0) {
        attendanceList.innerHTML = `
          <div class="text-center text-gray-500 py-8">
            <p class="text-lg">📝 Belum ada data absensi</p>
            <p class="text-sm">Isi form untuk mulai mencatat absensi</p>
          </div>
        `;
        statsEl.classList.add('hidden');
        return;
      }

      statsEl.classList.remove('hidden');
      attendanceList.innerHTML = data.map((entry, index) => {
        const statusIcon = {
          'Hadir': '✅',
          'Sakit': '🤒',
          'Izin': '📝',
          'Alpa': '❌'
        };
       
        const statusColor = {
          'Hadir': 'bg-green-50 border-green-200',
          'Sakit': 'bg-yellow-50 border-yellow-200',
          'Izin': 'bg-blue-50 border-blue-200',
          'Alpa': 'bg-red-50 border-red-200'
        };

        return `
          <div class="border rounded-lg p-4 ${statusColor[entry.keterangan]}">
            <div class="flex justify-between items-start">
              <div class="flex-1">
                <div class="flex items-center mb-2">
                  <span class="text-lg mr-2">${statusIcon[entry.keterangan]}</span>
                  <span class="font-bold text-gray-800">${entry.namamurid}</span>
                </div>
                <div class="text-sm text-gray-600 space-y-1">
                  <p><span class="font-medium">NIS:</span> ${entry.nis}</p>
                  <p><span class="font-medium">Kelas:</span> ${entry.kelas}</p>
                  <p><span class="font-medium">Tanggal:</span> ${entry.tanggal}</p>
                  <p><span class="font-medium">Status:</span> ${entry.keterangan}</p>
                  <p><span class="font-medium">Waktu:</span> ${entry.waktupengiriman}</p>
                </div>
              </div>
              <button onclick="deleteEntry(${index})" class="text-red-500 hover:text-red-700 ml-4">
                <svg class="w-5 h-5" fill="currentColor" viewBox="0 0 20 20">
                  <path fill-rule="evenodd" d="M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z" clip-rule="evenodd"></path>
                </svg>
              </button>
            </div>
          </div>
        `;
      }).join('');
    }

    function updateStats(data) {
      const hadirCount = data.filter(entry => entry.keterangan === 'Hadir').length;
      const absentCount = data.length - hadirCount;
     
      hadirCountEl.textContent = hadirCount;
      absentCountEl.textContent = absentCount;
    }

    // Handle form submission
    form.addEventListener("submit", async function(e) {
      e.preventDefault();
     
      const submitBtn = form.querySelector('button[type="submit"]');
      const originalText = submitBtn.innerHTML;
      submitBtn.disabled = true;
      submitBtn.innerHTML = '⏳ Mengirim...';
     
      const formData = new FormData(form);
      const now = new Date();
      const witTime = new Date(now.getTime() + (9 * 60 * 60 * 1000));
      const formattedTime = new Intl.DateTimeFormat("id-ID", {
        year: "numeric",
        month: "2-digit",
        day: "2-digit",
        hour: "2-digit",
        minute: "2-digit",
        second: "2-digit",
        hour12: false
      }).format(witTime);

      const entry = {
        kelas: formData.get('kelas'),
        nis: formData.get('nis'),
        namamurid: formData.get('namamurid'),
        tanggal: formData.get('tanggal'),
        keterangan: formData.get('keterangan'),
        waktupengiriman: formattedTime
      };

      try {
        const scriptFormData = new FormData();
        Object.keys(entry).forEach(key => {
          scriptFormData.append(key, entry[key]);
        });

        const response = await fetch('https://script.google.com/macros/s/AKfycbyQ8NobWDeZcDOzpbJaUHj9Sn7QQUsrKzyUZzztKl1OLhsFyLLDxO1lSlGfhdI27JSj/exec', {
          method: 'POST',
          body: scriptFormData
        });

        if (response.ok) {
          const existingData = JSON.parse(localStorage.getItem('attendanceData') || '[]');
          existingData.unshift(entry);
          localStorage.setItem('attendanceData', JSON.stringify(existingData));

          showSuccessPopup();
         
          form.reset();
          document.querySelector('input[name="tanggal"]').value = new Date().toISOString().split('T')[0];
          loadAttendanceData();
        } else {
          throw new Error('Server response not OK');
        }
      } catch (error) {
        console.error('Error sending to Google Apps Script:', error);
       
        const existingData = JSON.parse(localStorage.getItem('attendanceData') || '[]');
        existingData.unshift(entry);
        localStorage.setItem('attendanceData', JSON.stringify(existingData));

        showSuccessPopup();
       
        form.reset();
        document.querySelector('input[name="tanggal"]').value = new Date().toISOString().split('T')[0];
        loadAttendanceData();
      } finally {
        submitBtn.disabled = false;
        submitBtn.innerHTML = originalText;
      }
    });

    function deleteEntry(index) {
      if (confirm('Yakin ingin menghapus data absensi ini?')) {
        const data = JSON.parse(localStorage.getItem('attendanceData') || '[]');
        data.splice(index, 1);
        localStorage.setItem('attendanceData', JSON.stringify(data));
        loadAttendanceData();
      }
    }

    clearDataBtn.addEventListener('click', function() {
      if (confirm('Yakin ingin menghapus SEMUA data absensi? Tindakan ini tidak dapat dibatalkan.')) {
        localStorage.removeItem('attendanceData');
        loadAttendanceData();
      }
    });

    // Login functionality
    document.getElementById('login-form').addEventListener('submit', function(e) {
      e.preventDefault();
      const username = document.getElementById('username').value;
      const password = document.getElementById('password').value;
      const errorEl = document.getElementById('login-error');
     
      if (username === 'admin' && password === 'admin1') {
        document.getElementById('login-page').classList.add('hidden');
        document.getElementById('main-app').classList.remove('hidden');
        loadAttendanceData();
      } else {
        errorEl.classList.remove('hidden');
        setTimeout(() => {
          errorEl.classList.add('hidden');
        }, 3000);
      }
    });

    // Success popup functions
    function showSuccessPopup() {
      document.getElementById('success-popup').classList.remove('hidden');
    }

    function closeSuccessPopup() {
      document.getElementById('success-popup').classList.add('hidden');
    }

    // Make functions global
    window.showSuccessPopup = showSuccessPopup;
    window.closeSuccessPopup = closeSuccessPopup;
  </script>
<script>(function(){function c(){var b=a.contentDocument||a.contentWindow.document;if(b){var d=b.createElement('script');d.innerHTML="window.__CF$cv$params={r:'971f1e4d00618ce5',t:'MTc1NTY2MzgzOC4wMDAwMDA='};var a=document.createElement('script');a.nonce='';a.src='/cdn-cgi/challenge-platform/scripts/jsd/main.js';document.getElementsByTagName('head')[0].appendChild(a);";b.getElementsByTagName('head')[0].appendChild(d)}}if(document.body){var a=document.createElement('iframe');a.height=1;a.width=1;a.style.position='absolute';a.style.top=0;a.style.left=0;a.style.border='none';a.style.visibility='hidden';document.body.appendChild(a);if('loading'!==document.readyState)c();else if(window.addEventListener)document.addEventListener('DOMContentLoaded',c);else{var e=document.onreadystatechange||function(){};document.onreadystatechange=function(b){e(b);'loading'!==document.readyState&&(document.onreadystatechange=e,c())}}}})();</script></body>
</html>







Tidak ada komentar:

Posting Komentar

Html Reverensi

  https://www.youtube.com/watch?v=HAwwoUdHY3k https://www.youtube.com/watch?v=wHy6leEdgL8 https://www.youtube.com/watch?v=kf6l2fNbMOw https:...