Kritik Saran

shape image

Si-TARI - Tabungan TK Shigor Montessori

Masuk Sistem

Demo Mode

Si-TARI Tabungan

Sistem Informasi Tabungan Mandiri TK Shigor

// CONFIGURATION SWITCHER FOR LIVE DEPLOYMENTS const IS_PREVIEW = false; // Set false JIKA SUDAH TERHUBUNG KE FIREBASE const firebaseConfig = { apiKey: "API_KEY_ANDA", authDomain: "PROJECT_ID.firebaseapp.com", projectId: "PROJECT_ID", storageBucket: "PROJECT_ID.appspot.com", messagingSenderId: "SENDER_ID", appId: "APP_ID" }; const APP_ID = "shigor_montessori_production"; // Global State Pool window.state = { currentMode: 'auth', // auth, admin, parent currentAuthRole: 'parent', // parent, admin activeAdminSection: 'dashboard', activeAdminDataTab: 'students', students: [], transactions: [], currentUser: null, // logged-in user profile container isFirebase: false }; let db, auth; // Dynamic System Initialization const initSystem = async () => { if (!IS_PREVIEW && firebaseConfig.apiKey !== "API_KEY_ANDA") { try { const app = initializeApp(firebaseConfig); auth = getAuth(app); db = getFirestore(app); state.isFirebase = true; document.getElementById('badge-cloud-status').className = "px-3 py-1 rounded-full text-[10px] font-bold tracking-wide border bg-emerald-50 text-emerald-700 border-emerald-200"; document.getElementById('badge-cloud-status').innerHTML = ' Cloud Database Aktif'; // Synchronize Firebase Auth changes onAuthStateChanged(auth, async (user) => { if (user && state.currentAuthRole === 'admin') { state.currentUser = { email: user.email, name: "Ustadz/Ustadzah", role: "admin" }; state.currentMode = 'admin'; await autoSetupDatabase(); startDataSync(); routeSystemView(); } }); } catch (err) { console.error("Gagal inisialisasi Firebase. Beralih ke Demo Mode.", err); setupSimulatorMode(); } } else { setupSimulatorMode(); } }; const setupSimulatorMode = () => { state.isFirebase = false; document.getElementById('badge-cloud-status').className = "px-3 py-1 rounded-full text-[10px] font-bold tracking-wide border bg-amber-50 text-amber-700 border-amber-200"; document.getElementById('badge-cloud-status').innerHTML = ' Sandbox Mode Aktif'; loadSimulatorData(); }; // AUTO SETUP DATABASE (SEEDIING INITIAL DATA IF EMPTY) const autoSetupDatabase = async () => { if (!state.isFirebase) return; try { const sRef = collection(db, 'artifacts', APP_ID, 'public', 'data', 'students'); const sSnap = await getDocs(sRef); if (sSnap.empty) { // Seed Students const dummies = [ { id: 'S-001', name: 'Ahmad Fathir Mubarak', class: 'Montessori A', parentName: 'Bunda Fatimah', parentPhone: '628123456789', pin: '123456', balance: 350000, createdAt: Date.now() }, { id: 'S-002', name: 'Syifa Nur Salsabila', class: 'Montessori B', parentName: 'Ayah Lukman', parentPhone: '628987654321', pin: '111111', balance: 150000, createdAt: Date.now() }, { id: 'S-003', name: 'Zayyan Al Fatih', class: 'Islamic Playgroup', parentName: 'Bunda Sarah', parentPhone: '62855112233', pin: '222222', balance: 0, createdAt: Date.now() } ]; for (const d of dummies) { await setDoc(doc(db, 'artifacts', APP_ID, 'public', 'data', 'students', d.id), d); } // Seed Transactions const dummyTx = [ { studentId: 'S-001', studentName: 'Ahmad Fathir Mubarak', type: 'deposit', amount: 300000, date: Date.now() - 172800000, description: 'Setoran Awal Tabungan' }, { studentId: 'S-001', studentName: 'Ahmad Fathir Mubarak', type: 'deposit', amount: 50000, date: Date.now() - 86400000, description: 'Saku Senin' }, { studentId: 'S-002', studentName: 'Syifa Nur Salsabila', type: 'deposit', amount: 200000, date: Date.now() - 86400000, description: 'Tabungan Rutin Bulanan' }, { studentId: 'S-002', studentName: 'Syifa Nur Salsabila', type: 'withdrawal', amount: 50000, date: Date.now(), description: 'Pembelian Buku Iqro' } ]; for (const t of dummyTx) { await addDoc(collection(db, 'artifacts', APP_ID, 'public', 'data', 'transactions'), t); } showToast("Database Firestore berhasil diinisialisasi secara otomatis!", "success"); } } catch (err) { console.error("Gagal mengeksekusi Auto Setup:", err); } }; // Realtime Data Sync Pool const startDataSync = () => { const studentCol = collection(db, 'artifacts', APP_ID, 'public', 'data', 'students'); const transCol = collection(db, 'artifacts', APP_ID, 'public', 'data', 'transactions'); onSnapshot(studentCol, (snapshot) => { const students = []; snapshot.forEach(doc => { students.push(doc.data()); }); state.students = students; renderSystem(); }); onSnapshot(transCol, (snapshot) => { const transactions = []; snapshot.forEach(doc => { transactions.push({ id: doc.id, ...doc.data() }); }); state.transactions = transactions.sort((a, b) => b.date - a.date); renderSystem(); }); }; // Simulator / Local Storage Management const loadSimulatorData = () => { const localStudents = JSON.parse(localStorage.getItem('shigor_db_students')); const localTx = JSON.parse(localStorage.getItem('shigor_db_tx')); if (!localStudents || !localTx) { // Initialize Dummies const dummyStudents = [ { id: 'S-001', name: 'Ahmad Fathir Mubarak', class: 'Montessori A', parentName: 'Bunda Fatimah', parentPhone: '628123456789', pin: '123456', balance: 350000, createdAt: Date.now() }, { id: 'S-002', name: 'Syifa Nur Salsabila', class: 'Montessori B', parentName: 'Ayah Lukman', parentPhone: '628987654321', pin: '111111', balance: 150000, createdAt: Date.now() }, { id: 'S-003', name: 'Zayyan Al Fatih', class: 'Islamic Playgroup', parentName: 'Bunda Sarah', parentPhone: '62855112233', pin: '222222', balance: 0, createdAt: Date.now() } ]; const dummyTransactions = [ { id: 'tx-1', studentId: 'S-001', studentName: 'Ahmad Fathir Mubarak', type: 'deposit', amount: 300000, date: Date.now() - 172800000, description: 'Setoran Awal Tabungan' }, { id: 'tx-2', studentId: 'S-001', studentName: 'Ahmad Fathir Mubarak', type: 'deposit', amount: 50000, date: Date.now() - 86400000, description: 'Saku Senin' }, { id: 'tx-3', studentId: 'S-002', studentName: 'Syifa Nur Salsabila', type: 'deposit', amount: 200000, date: Date.now() - 86400000, description: 'Tabungan Rutin Bulanan' }, { id: 'tx-4', studentId: 'S-002', studentName: 'Syifa Nur Salsabila', type: 'withdrawal', amount: 50000, date: Date.now(), description: 'Pembelian Buku Iqro' } ]; localStorage.setItem('shigor_db_students', JSON.stringify(dummyStudents)); localStorage.setItem('shigor_db_tx', JSON.stringify(dummyTransactions)); state.students = dummyStudents; state.transactions = dummyTransactions; } else { state.students = localStudents; state.transactions = localTx.sort((a,b) => b.date - a.date); } renderSystem(); }; // WRITE OPERATORS WRAPPERS window.saveStudentToDB = async (studentData) => { if (state.isFirebase) { const sRef = doc(db, 'artifacts', APP_ID, 'public', 'data', 'students', studentData.id); await setDoc(sRef, studentData); } else { state.students.push(studentData); localStorage.setItem('shigor_db_students', JSON.stringify(state.students)); renderSystem(); } }; window.saveTransactionToDB = async (txData) => { if (state.isFirebase) { const sRef = doc(db, 'artifacts', APP_ID, 'public', 'data', 'students', txData.studentId); const sSnap = await getDoc(sRef); if (sSnap.exists()) { const student = sSnap.data(); const newBalance = txData.type === 'deposit' ? (student.balance || 0) + txData.amount : (student.balance || 0) - txData.amount; await addDoc(collection(db, 'artifacts', APP_ID, 'public', 'data', 'transactions'), txData); await updateDoc(sRef, { balance: newBalance }); } } else { const sIdx = state.students.findIndex(s => s.id === txData.studentId); if (sIdx !== -1) { const newBalance = txData.type === 'deposit' ? state.students[sIdx].balance + txData.amount : state.students[sIdx].balance - txData.amount; state.students[sIdx].balance = newBalance; txData.id = "tx-" + Math.random().toString(36).substr(2, 9); state.transactions.unshift(txData); localStorage.setItem('shigor_db_students', JSON.stringify(state.students)); localStorage.setItem('shigor_db_tx', JSON.stringify(state.transactions)); renderSystem(); } } }; window.deleteStudentFromDB = async (studentId) => { if (state.isFirebase) { const sRef = doc(db, 'artifacts', APP_ID, 'public', 'data', 'students', studentId); await deleteDoc(sRef); } else { state.students = state.students.filter(s => s.id !== studentId); localStorage.setItem('shigor_db_students', JSON.stringify(state.students)); renderSystem(); } }; window.deleteTransactionFromDB = async (txId, studentId, amount, type) => { if (state.isFirebase) { const txRef = doc(db, 'artifacts', APP_ID, 'public', 'data', 'transactions', txId); const sRef = doc(db, 'artifacts', APP_ID, 'public', 'data', 'students', studentId); const sSnap = await getDoc(sRef); if (sSnap.exists()) { const student = sSnap.data(); const revertedBalance = type === 'deposit' ? (student.balance || 0) - amount : (student.balance || 0) + amount; await deleteDoc(txRef); await updateDoc(sRef, { balance: revertedBalance }); } } else { state.transactions = state.transactions.filter(t => t.id !== txId); const sIdx = state.students.findIndex(s => s.id === studentId); if (sIdx !== -1) { state.students[sIdx].balance = type === 'deposit' ? state.students[sIdx].balance - amount : state.students[sIdx].balance + amount; } localStorage.setItem('shigor_db_students', JSON.stringify(state.students)); localStorage.setItem('shigor_db_tx', JSON.stringify(state.transactions)); renderSystem(); } }; // AUTH HANDLERS COMPATIBLE WITH PREVIEW MODE window.handleAdminAuth = async (e) => { e.preventDefault(); const email = document.getElementById('admin-login-email').value.trim(); const password = document.getElementById('admin-login-password').value; if (state.isFirebase) { try { await signInWithEmailAndPassword(auth, email, password); showToast("Login Admin Berhasil", "success"); } catch (err) { showToast("Gagal masuk: " + err.message, "error"); } } else { // Mock Admin Login (Safe Simulator bypass) if (email === "admin@shigor.com" && password === "shigor123") { state.currentUser = { email, name: "Ustadz Admin", role: "admin" }; state.currentMode = 'admin'; showToast("Simulasi Admin Aktif", "success"); routeSystemView(); renderSystem(); } else { showToast("Akun simulasi salah! (Gunakan: admin@shigor.com / shigor123)", "error"); } } }; window.handleParentAuth = (e) => { e.preventDefault(); const id = document.getElementById('parent-login-id').value.trim().toUpperCase(); const pin = document.getElementById('parent-login-pin').value; const studentMatch = state.students.find(s => s.id === id && s.pin === pin); if (studentMatch) { state.currentUser = { id: studentMatch.id, name: "Wali dari " + studentMatch.name, role: "parent", details: studentMatch }; state.currentMode = 'parent'; showToast("Berhasil Masuk Portal Wali Murid", "success"); routeSystemView(); renderSystem(); } else { showToast("Kredensial salah atau Murid tidak terdaftar!", "error"); } }; window.handleLogout = async () => { if (state.isFirebase && state.currentUser?.role === 'admin') { await signOut(auth); } state.currentUser = null; state.currentMode = 'auth'; showToast("Keluar berhasil.", "success"); routeSystemView(); }; // Initialization window.addEventListener('DOMContentLoaded', () => { initSystem(); // Register dynamic 1-file Service Worker if ('serviceWorker' in navigator) { const swString = ` const CACHE_NAME = 'sitari-v1'; self.addEventListener('install', e => self.skipWaiting()); self.addEventListener('fetch', e => e.respondWith(fetch(e.request))); `; const swBlob = new Blob([swString], { type: 'application/javascript' }); const swUrl = URL.createObjectURL(swBlob); navigator.serviceWorker.register(swUrl).catch(err => console.warn("PWA SW Bypassed.")); } });

Posting Komentar

© Copyright 2024 Montessori Bengkulu

Kritik Saran

Kritik Konstruktif Energi Produktif Kami

Kirim