//
//
// Lalu ganti loginDenganAkun() local dengan loginSupabase(), dan ganti
// localStorage absensi/siswa dengan fungsi di bawah ini.
(function () {
function getConfig() {
return window.SUPABASE_CONFIG || {};
}
function isConfigured() {
const c = getConfig();
return c.url && c.anonKey &&
!String(c.url).includes("GANTI-DENGAN") &&
!String(c.anonKey).includes("GANTI-DENGAN");
}
function usernameToEmail(username) {
const domain = window.SUPABASE_EMAIL_DOMAIN || "absensi.smpn2saketi";
return String(username).trim().toLowerCase() + "@" + domain;
}
function createClient() {
if (!isConfigured()) return null;
if (!window.supabase) return null;
return window.supabase.createClient(getConfig().url, getConfig().anonKey);
}
async function loginSupabase(username, password) {
const client = createClient();
if (!client) throw new Error("Supabase belum dikonfigurasi di config.js");
const email = usernameToEmail(username);
const { data, error } = await client.auth.signInWithPassword({ email, password });
if (error) throw error;
const { data: profile, error: perr } = await client
.from("profiles")
.select("id, username, nama, peran, aktif")
.eq("id", data.user.id)
.single();
if (perr) throw perr;
if (!profile.aktif) throw new Error("Akun ini nonaktif. Hubungi Master.");
return { user: data.user, profile };
}
async function loadSiswa(client) {
const { data, error } = await client.from("siswa").select("*").eq("aktif", true).order("rombel").order("nama");
if (error) throw error;
return data.map(s => ({ id: s.id, nama: s.nama, rombel: s.rombel, jk: s.jk }));
}
async function loadAbsensi(client) {
const { data, error } = await client.from("absensi").select("siswa_id, tanggal, status, siswa:siswa_id(rombel)");
if (error) throw error;
const out = {};
data.forEach(r => {
const rombel = r.siswa ? r.siswa.rombel : "";
out[r.tanggal + "|" + rombel + "|" + r.siswa_id] = r.status;
});
return out;
}
async function saveAbsensi(client, siswaId, tanggal, status, diinputOleh) {
const { error } = await client.from("absensi").upsert(
{ siswa_id: siswaId, tanggal, status, diinput_oleh: diinputOleh },
{ onConflict: "siswa_id,tanggal" }
);
if (error) throw error;
}
async function saveReview(client, siswaId, bulan, sudah, catatan, diupdateOleh) {
const { error } = await client.from("review_privat").upsert(
{ siswa_id: siswaId, bulan, sudah_dikonfirmasi: sudah, catatan, diupdate_oleh: diupdateOleh },
{ onConflict: "siswa_id,bulan" }
);
if (error) throw error;
}
async function saveAlert(client, siswaId, bulan, status, catatan, diupdateOleh) {
const { error } = await client.from("tindak_lanjut_alert").upsert(
{ siswa_id: siswaId, bulan, status, catatan, diupdate_oleh: diupdateOleh },
{ onConflict: "siswa_id,bulan" }
);
if (error) throw error;
}
window.AbsensiSupabase = {
isConfigured, usernameToEmail, createClient,
loginSupabase, loadSiswa, loadAbsensi,
saveAbsensi, saveReview, saveAlert
};
})();
Absensi Shalat Dhuhr
SMPN 2 Saketi - Prototipe program sekolah, jam sekolah, hanya Dhuhr
Login
Isi username dan password saja. Webapp yang akan menentukan siapa yang login, Master atau Admin Putra atau Admin Putri, berdasarkan akun itu. Tidak ada lagi tombol pilih peran di halaman ini.
Akun demo, hanya untuk ngetes prototipe, jangan dipakai untuk akun asli:
Master: username master, password master123
Admin Putra: username admin_putra, password putra123
Admin Putri: username admin_putri, password putri123
Setelah login, peran dan menunya otomatis mengikuti akun itu.
2 jenis user di versi online nanti:
1. Master: akses penuh, bisa bikin user baru, dipakai kepala sekolah atau staff IT. 2. Admin: Admin Putra dan Admin Putri, bertugas input kehadiran siswa sesuai kelompoknya.
Batas privasi tetap berlaku: data Berhalangan dan Review Privat putri tidak tampil di akun Admin Putra. Untuk Master, daftar review putri tetap dibuka lewat gerbang privasi di menu Rekap, dan sebaiknya tindak lanjut privatnya tetap dipegang guru perempuan atau UKS.
Peringatan keamanan: password demo di atas hanya untuk prototipe lokal. Versi online wajib menyimpan password dalam bentuk hash, bukan teks asli, dan wajib pakai HTTPS.
Data di sini masih data contoh, bukan nama siswa asli. Data tersimpan lokal di browser ini, belum online ke server.
Absensi Shalat Dhuhr
SMPN 2 Saketi - Dhuhr saja
Prototipe v3, bukan data asli.
Nama contoh: Contoh Putra 1, Contoh Putri A, dan seterusnya. Data hanya tersimpan di browser ini (localStorage). Versi online nanti memindahkan data ini ke database server dengan login kata sandi.
Grafik Batang: Komposisi status bulan ini
Grafik Batang: Persentase Hadir per rombel
Grafik Tren Harian: Batang dan Garis
Hijau: Hadir per hari.Merah muda: Berhalangan per hari (putri saja).
Alert: Tidak Hadir, perlu tindak lanjut
Alert ini bukan hukuman otomatis. Tujuannya supaya admin bisa langsung memanggil siswa yang bersangkutan untuk penanganan awal, misal tanya alasan, ingatkan, atau teruskan ke wali kelas dan orang tua kalau polanya berulang. Kriteria alert: tidak hadir pada tanggal yang dipilih di atas, atau tidak hadir 3 kali atau lebih dalam bulan yang dipilih.
Review Privat (ringkasan, tanpa nama di dashboard)
Tanda review artinya perlu konfirmasi privat, bukan vonis bohong dan bukan diagnosis. Daftar nama hanya ada di bagian Review Privat di menu Rekap.
Klik status untuk menyimpan otomatis di browser ini.
Nama (contoh)
Kelompok
Status Dhuhr
Export hanya tersedia dalam 2 jenis file: PDF dan XLSX. Tidak ada lagi CSV di prototipe ini.
Episode Berhalangan dihitung dari hari berurutan. Senin sampai Rabu dihitung 1 episode, bukan 3 episode.
Nama (contoh)
Rombel
Hadir
Tidak Hadir
Izin
Sakit
Hari Berhalangan
Episode
Tanda (Putri)
Review Privat, gerbang privasi.
Hanya untuk tindak lanjut privat putri. Kriteria: episode 2 kali atau lebih dalam sebulan, atau total lebih dari 10 hari dalam sebulan, atau ada episode lebih dari 8 hari berturut-turut. Ini pemicu konfirmasi privat, bukan bukti bohong. Untuk Master, bagian ini tetap dibuka lewat tombol di bawah, dan tindak lanjutnya sebaiknya dipegang guru perempuan atau UKS.
Akun Admin Putra tidak menampilkan data Berhalangan dan Review Privat putri. Bagian itu hanya ada di akun Admin Putri dan Master lewat gerbang privasi.
Kelola User - Hanya Master
Di prototipe ini, daftar user disimpan lokal di browser. Di versi online, tambah user harus membuat akun dengan kata sandi terenkripsi, dan setiap perubahan user dicatat di log audit. Jangan simpan kata sandi asli di file ini.
Di versi online, password di sini harus langsung di-hash di server, tidak disimpan sebagai teks asli. Di prototipe ini password disimpan lokal hanya untuk simulasi login.
Nama
Peran
Status
Aksi
Data Siswa - CRUD, Hanya Master
Master bisa tambah, lihat, ubah, dan hapus data siswa contoh di sini. Perubahan langsung terlihat di menu Input dan Rekap. Di prototipe ini datanya masih contoh, bukan data siswa asli dari file Excel sekolah, dan hanya tersimpan lokal di browser. Di versi online, CRUD ini tersambung ke database siswa sekolah.
Nama (contoh)
Rombel
Kelompok
Aksi
Prototipe lokal v4. Untuk online sungguhan, perlu: database server, login kata sandi, hosting HTTPS, dan backup. Prototipe ini mensimulasikan peran dan user secara lokal.