import React, { useState, useEffect } from "react"; import { createRoot } from "react-dom/client"; import { LayoutDashboard, Users, ShieldCheck, CarFront, Gavel, ClipboardCheck, CreditCard, ChartNoAxesCombined, Settings, Search, Bell, Plus, ChevronRight, Menu, X, CheckCircle2, Database, RefreshCw, Sparkles, LogOut } from "lucide-react"; import "./styles.css"; // API & Database Client import { fetchCars, saveCar, deleteCar, getSystemHealth } from "./api"; import { supabase } from "./supabaseClient"; // Components import LoginPage from "./components/LoginPage"; import ThreeGridCarForm from "./components/ThreeGridCarForm"; import CarInventoryTable from "./components/CarInventoryTable"; import InspectionsDashboard from "./components/InspectionsDashboard"; import ComingSoon from "./components/ComingSoon"; function App() { const [currentUser, setCurrentUser] = useState(() => { try { return JSON.parse(localStorage.getItem("carboli_auth_user") || "null"); } catch { return null; } }); const [page, setPage] = useState("cars"); const [mobileOpen, setMobileOpen] = useState(false); const [cars, setCars] = useState([]); const [loading, setLoading] = useState(true); const [dbStatus, setDbStatus] = useState("Connecting to Backend..."); const [schemaNeeded, setSchemaNeeded] = useState(false); const [search, setSearch] = useState(""); const [toast, setToast] = useState(""); const handleLogout = async () => { try { if (supabase) await supabase.auth.signOut(); } catch (e) { // ignore } localStorage.removeItem("carboli_auth_user"); setCurrentUser(null); notify("Signed out from CarBoli Desk."); }; // Car Management View Mode: 'inventory' (List / Grid View) vs 'create' (3-Grid Workspace) const [carViewMode, setCarViewMode] = useState("inventory"); const [selectedCar, setSelectedCar] = useState(null); const notify = (message) => { setToast(message); window.setTimeout(() => setToast(""), 3500); }; const navigate = (next) => { setPage(next); setMobileOpen(false); }; // Load cars and system health from backend / Supabase const loadData = async () => { setLoading(true); try { const [fetchedCars, health] = await Promise.all([ fetchCars().catch(() => []), getSystemHealth().catch(() => null) ]); setCars(fetchedCars || []); if (health?.supabaseConnected) { if (health.tablesReady === false) { setDbStatus("Supabase (Run Schema)"); setSchemaNeeded(true); } else { setDbStatus("Supabase Connected"); setSchemaNeeded(false); } } else if (health) { setDbStatus("Backend Connected"); setSchemaNeeded(false); } else { setDbStatus("Connecting to Backend..."); setSchemaNeeded(false); } } catch (err) { console.warn("Could not fetch cars from database:", err.message); setCars([]); } finally { setLoading(false); } }; useEffect(() => { loadData(); }, []); const handleOpenCarStudio = (car) => { setSelectedCar(car || null); setCarViewMode("create"); if (car) { notify(`Loaded ${car.make} ${car.model} in 3-Grid Studio`); } }; const handleAddNewCar = async (newCarData) => { try { const payload = selectedCar?.id ? { ...newCarData, id: selectedCar.id } : newCarData; console.log("Saving vehicle payload to API / Supabase:", payload); const saved = await saveCar(payload); setCars(prev => { const idx = prev.findIndex(c => c.id === saved.id || (saved.reg && c.reg === saved.reg)); if (idx !== -1) { const updated = [...prev]; updated[idx] = saved; return updated; } return [saved, ...prev]; }); const verb = saved.status === 'Draft' ? 'saved as Draft' : 'published to Live Auction'; notify(`✓ Vehicle ${saved.make} ${saved.model} ${verb} in Supabase!`); setSelectedCar(null); setCarViewMode("inventory"); return saved; } catch (err) { console.error("Save error in API:", err); // Fallback setCars(prev => [newCarData, ...prev]); notify(`Notice: ${err.message}. Saved locally.`); setSelectedCar(null); setCarViewMode("inventory"); return newCarData; } }; const handleDeleteCar = async (id) => { try { await deleteCar(id); setCars(prev => prev.filter(c => c.id !== id)); notify("Vehicle removed from database."); } catch (err) { setCars(prev => prev.filter(c => c.id !== id)); notify("Vehicle removed locally."); } }; const navItems = [ { id: "dashboard", label: "Dashboard", icon: LayoutDashboard }, { id: "cars", label: "Car Management", icon: CarFront, count: String(cars.length), highlight: true }, { id: "users", label: "User Management", icon: Users }, { id: "kyc", label: "KYC Verification", icon: ShieldCheck }, { id: "auctions", label: "Live Auctions", icon: Gavel }, { id: "inspection", label: "Inspections", icon: ClipboardCheck }, { id: "payments", label: "Payments & Settlements", icon: CreditCard }, { id: "reports", label: "Reports & Analytics", icon: ChartNoAxesCombined }, { id: "settings", label: "Settings", icon: Settings } ]; const currentLabel = navItems.find((item) => item.id === page)?.label || "Car Management"; if (!currentUser) { return ( <> {toast && (
{toast}
)} ); } return (
{/* Sidebar Navigation */} {/* Main Content Area */}
{/* Topbar */}
Workspace {currentLabel}
{dbStatus}
{currentUser?.name?.slice(0, 2).toUpperCase() || 'CB'}
{/* Page Switcher */} {page === "cars" ? (
{schemaNeeded && (
Supabase Connected — Database Setup Required The cars table is not created yet. Please execute the provided supabase_schema.sql in your Supabase SQL Editor.
)} {/* Render 3-Grid Form Studio or Inventory Table */} {carViewMode === "create" ? ( setCarViewMode("inventory")} /> ) : ( )}
) : page === "inspection" ? (
{ handleOpenCarStudio(car); setPage("cars"); }} notify={notify} />
) : ( /* ALL OTHER PAGES RENDER SLEEK COMING SOON SCREENS (As requested by user!) */ i.id === page)?.icon} onGoToCars={() => { setPage("cars"); setCarViewMode("create"); }} /> )}
{/* Floating Toast Notification */} {toast && (
{toast}
)}
); } function NavButton({ item, active, onClick }) { const Icon = item.icon; return ( ); } createRoot(document.getElementById("root")).render();