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 (
Initializing Control Hub
); return (
{showToast && (
{t.settings_updated}
)} {/* Sidebar */} {/* Kandungan Utama */}
{formattedTime}
{formattedDate}
{activeTab === 'dashboard' && (

{t.recent_activity}

{t.status_system}

)} {activeTab === 'inventory' && (

{t.bank_gallery}

{banks.map(bank => (
deleteBank(bank.id, e)}>

{bank.name}

{bank.cards} CARDS

))}
)} {activeTab === 'analysis' && (

{t.debt_freedom}

{freedomScore}%
RM {(totalLimit - totalUsage).toLocaleString()} {t.available_limit}

{t.utilization}

{banks.length === 0 ?
No Data Recorded
: banks.map(bank => (
{bank.name}{(bank.limit > 0 ? (bank.usage / bank.limit * 100).toFixed(1) : 0)}%
0 ? (bank.usage / bank.limit * 100) : 0)}%`, backgroundColor: glowColor }} />
))}
)} {activeTab === 'config' && (
{/* Kesan Visual */}
{t.glow_enabled}
{['#22D3EE', '#F43F5E', '#F97316', '#EAB308', '#8B5CF6', '#10B981', '#EC4899', '#3B82F6'].map(c =>
syncSettings({ glowColor: c })} className={`w-8 h-8 rounded-full cursor-pointer transition-all ${glowColor === c ? 'ring-2 ring-cyan-500 ring-offset-2' : ''} ${!isDark && 'ring-offset-white'}`} style={{ backgroundColor: c }} />)}
{/* Warna Widget Mod Siang */}
{[ { id: 'bg-white', label: 'White' }, { id: 'bg-slate-50', label: 'Slate 50' }, { id: 'bg-blue-50', label: 'Blue 50' }, { id: 'bg-orange-50', label: 'Orange 50' }, { id: 'bg-emerald-50', label: 'Emerald 50' }, { id: 'bg-rose-50', label: 'Rose 50' }, { id: 'bg-amber-50', label: 'Amber 50' }, { id: 'bg-violet-50', label: 'Violet 50' }, { id: 'bg-cyan-50', label: 'Cyan 50' }, { id: 'bg-gray-50', label: 'Gray 50' } ].map(color => (
syncSettings({ lightWidgetBg: color.id })} className={`h-16 rounded-xl cursor-pointer border-2 transition-all flex items-center justify-center ${lightWidgetBg === color.id ? 'border-cyan-500 scale-95 shadow-lg' : 'border-gray-200'} ${color.id}`} > {color.label}
))}
{/* Warna Widget Mod Malam */}
{[ { id: 'bg-[#0B0E14]', label: 'Default Dark' }, { id: 'bg-slate-900', label: 'Slate 900' }, { id: 'bg-zinc-950', label: 'Zinc 950' }, { id: 'bg-neutral-900', label: 'Neutral 900' }, { id: 'bg-stone-950', label: 'Stone 950' }, { id: 'bg-[#020617]', label: 'Deep Blue' }, { id: 'bg-[#0a0a0a]', label: 'True Black' }, { id: 'bg-[#1a1a2e]', label: 'Midnight' }, { id: 'bg-[#121212]', label: 'Material Dark' }, { id: 'bg-[#1c1c1c]', label: 'Onyx' } ].map(color => (
syncSettings({ nightWidgetBg: color.id })} className={`h-16 rounded-xl cursor-pointer border-2 transition-all flex items-center justify-center ${nightWidgetBg === color.id ? 'border-cyan-500 scale-95 shadow-lg' : 'border-gray-800'} ${color.id}`} > {color.label}
))}
{/* Pilihan Latar Belakang */}
{['bg-white', 'bg-slate-50', 'bg-slate-950', 'bg-black'].map(bg =>
syncSettings({ theme: bg })} className={`h-16 rounded-xl cursor-pointer border-2 transition-all ${theme === bg ? 'border-cyan-500 scale-95' : isDark ? 'border-gray-800' : 'border-slate-200'} ${bg}`} />)}
)} {['history', 'perks'].includes(activeTab) &&
Tiada data direkodkan di awan.
}