{t.recent_activity}
{t.status_system}
{t.bank_gallery}
{bank.name}
{bank.cards} CARDS
{t.debt_freedom}
{t.utilization}
{title}
{desc}
import React, { useState, useEffect, useMemo } from 'react'; import { LayoutDashboard, CreditCard, Gift, BarChart3, History, Settings, Plus, ChevronLeft, Trash2, Save, ArrowUp, ArrowDown, Globe, Sun, Moon, X, Plane, Coins, Star, Building, Fuel, Info, Clock, CheckCircle2, Github, Download, RotateCcw, Eye, EyeOff, Loader2, Menu } from 'lucide-react'; // Import Firebase import { initializeApp } from 'firebase/app'; import { getAuth, signInWithCustomToken, signInAnonymously, onAuthStateChanged } from 'firebase/auth'; import { getFirestore, doc, setDoc, getDoc, collection, onSnapshot, updateDoc, deleteDoc, addDoc } from 'firebase/firestore'; // --- Konfigurasi Firebase --- const firebaseConfig = JSON.parse(__firebase_config); const app = initializeApp(firebaseConfig); const auth = getAuth(app); const db = getFirestore(app); const appId = typeof __app_id !== 'undefined' ? __app_id : 'credit-control-hub-default'; // --- Penempatan Bahasa (Localization) --- const translations = { ENG: { dashboard: "Dashboard", inventory: "Card Inventory", perks: "Card Perks", analysis: "Debt Analysis", history: "History & Logs", config: "System Config", total_credit: "Total Credit Limit", total_usage: "Total Usage", debt_balance: "Debt Balance", recent_activity: "Recent Activity", status_system: "System Status: Normal & Active", add_bank: "Add Bank", bank_gallery: "Bank Gallery", filter_perks: "Filter by Perks", debt_freedom: "Debt Freedom Score", utilization: "Utilization Analysis", freedom_desc: "Safe credit limit percentage.", available_limit: "Available Limit", quick_update: "Quick Update", rewards_table: "Rewards Summary Table", settings_updated: "Cloud Synced!", visual_effects: "Visual Effects & Glow", glow_enabled: "Glow Enabled", theme_selection: "Background Theme Selection", lang_setting: "Default Language Setting", syncing: "Saving to cloud...", light_widget_setting: "Day Mode Widget Color", light_widget_desc: "Choose background color for boxes in Day Mode.", night_widget_setting: "Night Mode Widget Color", night_widget_desc: "Choose background color for boxes in Night Mode." }, BM: { dashboard: "Papan Pemuka", inventory: "Inventori Kad", perks: "Kelebihan Kad", analysis: "Analisis Beban", history: "Sejarah & Log", config: "Konfigurasi Sistem", total_credit: "Total Had Kredit", total_usage: "Total Penggunaan", debt_balance: "Baki Hutang", recent_activity: "Aktiviti Terkini", status_system: "Status Sistem: Normal & Aktif", add_bank: "Tambah Bank", bank_gallery: "Galeri Bank", filter_perks: "Tapis mengikut Kelebihan", debt_freedom: "Skor Kebebasan Hutang", utilization: "Analisis Penggunaan", freedom_desc: "Peratusan had kredit selamat.", available_limit: "Had Tersedia", quick_update: "Kemaskini Pantas", rewards_table: "Jadual Ringkasan Ganjaran", settings_updated: "Data Disinkron!", visual_effects: "Kesan Visual & Cahaya", glow_enabled: "Cahaya Diaktifkan", theme_selection: "Pilihan Tema Latar Belakang", lang_setting: "Tetapan Bahasa Lalai", syncing: "Menyimpan ke awan...", light_widget_setting: "Warna Widget Mod Siang", light_widget_desc: "Pilih warna latar belakang kotak untuk Mod Siang.", night_widget_setting: "Warna Widget Mod Malam", night_widget_desc: "Pilih warna latar belakang kotak untuk Mod Malam." } }; const App = () => { // Autentikasi & State Pangkalan Data const [user, setUser] = useState(null); const [loading, setLoading] = useState(true); const [isSyncing, setIsSyncing] = useState(false); // State UI const [isSidebarCollapsed, setIsSidebarCollapsed] = useState(false); const [lang, setLang] = useState('ENG'); const [activeTab, setActiveTab] = useState('dashboard'); const [banks, setBanks] = useState([]); const [glowEnabled, setGlowEnabled] = useState(true); const [glowColor, setGlowColor] = useState('#22D3EE'); const [theme, setTheme] = useState('bg-slate-950'); const [lightWidgetBg, setLightWidgetBg] = useState('bg-white'); const [nightWidgetBg, setNightWidgetBg] = useState('bg-[#0B0E14]'); const [showToast, setShowToast] = useState(false); const [time, setTime] = useState(new Date()); const t = translations[lang]; // Derived UI states based on theme const isDark = theme === 'bg-slate-950' || theme === 'bg-black'; const cardBg = isDark ? nightWidgetBg : `${lightWidgetBg} shadow-sm`; const borderColor = isDark ? 'border-gray-800/50' : 'border-gray-200'; const textColor = isDark ? 'text-white' : 'text-slate-900'; const labelColor = isDark ? 'text-gray-500' : 'text-slate-500'; // Format Tarikh dan Masa const formattedTime = time.toLocaleTimeString('en-GB', { hour12: false }); const formattedDate = time.toLocaleDateString(lang === 'ENG' ? 'en-GB' : 'ms-MY', { weekday: 'long', year: 'numeric', month: 'short', day: 'numeric' }).toUpperCase(); // Autentikasi useEffect(() => { const initAuth = async () => { try { if (typeof __initial_auth_token !== 'undefined' && __initial_auth_token) { await signInWithCustomToken(auth, __initial_auth_token); } else { await signInAnonymously(auth); } } catch (err) { console.error(err); } }; initAuth(); const unsubscribe = onAuthStateChanged(auth, (u) => { setUser(u); if (!u) setLoading(false); }); return () => unsubscribe(); }, []); // Pengambilan Data useEffect(() => { if (!user) return; const settingsRef = doc(db, 'artifacts', appId, 'users', user.uid, 'settings', 'appConfig'); const unsubSettings = onSnapshot(settingsRef, (snap) => { if (snap.exists()) { const data = snap.data(); if (data.lang) setLang(data.lang); if (data.glowEnabled !== undefined) setGlowEnabled(data.glowEnabled); if (data.glowColor) setGlowColor(data.glowColor); if (data.theme) setTheme(data.theme); if (data.lightWidgetBg) setLightWidgetBg(data.lightWidgetBg); if (data.nightWidgetBg) setNightWidgetBg(data.nightWidgetBg); } setLoading(false); }); const banksRef = collection(db, 'artifacts', appId, 'users', user.uid, 'banks'); const unsubBanks = onSnapshot(banksRef, (snap) => { setBanks(snap.docs.map(doc => ({ id: doc.id, ...doc.data() }))); }); return () => { unsubSettings(); unsubBanks(); }; }, [user]); const syncSettings = async (newData) => { if (!user) return; setIsSyncing(true); try { const settingsRef = doc(db, 'artifacts', appId, 'users', user.uid, 'settings', 'appConfig'); await setDoc(settingsRef, newData, { merge: true }); triggerToast(); } catch (err) { console.error(err); } setIsSyncing(false); }; const addBank = async () => { if (!user) return; await addDoc(collection(db, 'artifacts', appId, 'users', user.uid, 'banks'), { name: 'NEW BANK', cards: 0, limit: 0, usage: 0, createdAt: new Date().toISOString() }); triggerToast(); }; const deleteBank = async (id, e) => { e.stopPropagation(); await deleteDoc(doc(db, 'artifacts', appId, 'users', user.uid, 'banks', id)); triggerToast(); }; useEffect(() => { const timer = setInterval(() => setTime(new Date()), 1000); return () => clearInterval(timer); }, []); const triggerToast = () => { setShowToast(true); setTimeout(() => setShowToast(false), 3000); }; const totalLimit = banks.reduce((sum, b) => sum + (Number(b.limit) || 0), 0); const totalUsage = banks.reduce((sum, b) => sum + (Number(b.usage) || 0), 0); const freedomScore = totalLimit > 0 ? ((totalLimit - totalUsage) / totalLimit * 100).toFixed(1) : "100.0"; if (loading) return (
{t.status_system}
{bank.cards} CARDS
{desc}