import { useState, useEffect, useRef } from "react"; // ─── THEME ─────────────────────────────────────────────────────────────────── const T = { bg: "#0A0E1A", surface: "#111827", card: "#1A2235", border: "#1E2D45", gold: "#F0B429", goldLight: "#F7D070", goldDark: "#C98D00", green: "#10B981", red: "#EF4444", blue: "#3B82F6", purple: "#8B5CF6", cyan: "#06B6D4", text: "#F1F5F9", muted: "#64748B", sub: "#94A3B8", }; // ─── MOCK DATA ──────────────────────────────────────────────────────────────── const mockUser = { name: "Alex Tumwine", username: "alex_t", phone: "0701234567", avatar: "AT", cuBalance: 42500, ugxBalance: 8500, notifications: 3, }; const mockTransactions = [ { id: 1, type: "deposit", label: "Wallet Deposit", amount: 50000, cu: 42500, date: "Today, 10:32 AM", status: "completed" }, { id: 2, type: "queue", label: "Queue Commit", amount: -20000, cu: -20000, date: "Yesterday", status: "pending" }, { id: 3, type: "sacco", label: "SACCO Savings", amount: -20000, cu: -20000, date: "Mon, Apr 21", status: "completed" }, { id: 4, type: "reward", label: "Blogger Reward", amount: 5000, cu: 5000, date: "Sun, Apr 20", status: "completed" }, ]; const mockQueue = [ { id: 1, username: "james_k", committed: 85000, position: 1, progress: 92 }, { id: 2, username: "sarah_m", committed: 50000, position: 2, progress: 65 }, { id: 3, username: "alex_t", committed: 20000, position: 3, progress: 30, isMe: true }, { id: 4, username: "grace_n", committed: 100000, position: 4, progress: 10 }, ]; const mockBusinesses = [ { id: 1, name: "Kampala Bakers Ltd", category: "Food & Beverage", status: "verified", loan: 500000, repaid: 320000 }, { id: 2, name: "TechHub Uganda", category: "Technology", status: "pending", loan: 0, repaid: 0 }, ]; const mockBloggers = [ { id: 1, name: "Sarah Mukasa", platform: "Instagram", followers: "12.4K", posts: 8, rewards: 35000, status: "active" }, { id: 2, name: "David Ojo", platform: "TikTok", followers: "45K", posts: 15, rewards: 82000, status: "active" }, { id: 3, name: "Faith Apio", platform: "Twitter/X", followers: "8.2K", posts: 5, rewards: 18000, status: "review" }, ]; const mockAds = [ { id: 1, business: "Kampala Bakers", type: "image", expires: "23h 14m", views: 1240 }, { id: 2, business: "TechHub UG", type: "video", expires: "8h 45m", views: 3870 }, ]; const mockSacco = { joined: true, savings: 80000, loanEligible: 240000, activeLoan: 100000, loanRepaid: 40000, weeklyTarget: 20000, streak: 4, }; // ─── UTILS ─────────────────────────────────────────────────────────────────── const fmtCU = (n) => n?.toLocaleString() + " CU"; const fmtUGX = (n) => "UGX " + n?.toLocaleString(); const fmtNum = (n) => n?.toLocaleString(); // ─── STYLES ────────────────────────────────────────────────────────────────── const gbl = ` @import url('https://fonts.googleapis.com/css2?family=Sora:wght@300;400;500;600;700;800&family=Space+Mono:wght@400;700&display=swap'); *{box-sizing:border-box;margin:0;padding:0;} body{background:${T.bg};color:${T.text};font-family:'Sora',sans-serif;overflow:hidden;} ::-webkit-scrollbar{width:4px;} ::-webkit-scrollbar-track{background:${T.surface};} ::-webkit-scrollbar-thumb{background:${T.border};border-radius:2px;} .mono{font-family:'Space Mono',monospace;} @keyframes slideUp{from{transform:translateY(100%);opacity:0;}to{transform:translateY(0);opacity:1;}} @keyframes fadeIn{from{opacity:0;transform:translateY(8px);}to{opacity:1;transform:translateY(0);}} @keyframes pulse{0%,100%{opacity:1;}50%{opacity:.5;}} @keyframes shimmer{0%{background-position:-200% 0;}100%{background-position:200% 0;}} @keyframes ringPop{0%{transform:scale(1);}50%{transform:scale(1.2);}100%{transform:scale(1);}} @keyframes spin{from{transform:rotate(0deg);}to{transform:rotate(360deg);}}; .slide-up{animation:slideUp .35s cubic-bezier(.22,1,.36,1) forwards;} .fade-in{animation:fadeIn .3s ease forwards;} .ring-pop{animation:ringPop .4s ease;} `; // ─── COMPONENTS ────────────────────────────────────────────────────────────── function Badge({ color = T.gold, children, small }) { return ( {children} ); } function Card({ children, style, onClick, glow }) { return (
{children}
); } function ProgressBar({ value, color = T.gold, height = 6 }) { return (
); } function Avatar({ initials, size = 38, color = T.gold }) { return (
{initials}
); } function Divider({ style }) { return
; } function Btn({ children, onClick, variant = "primary", small, full, disabled, style }) { const base = { border: "none", borderRadius: 12, fontFamily: "Sora, sans-serif", fontWeight: 600, cursor: disabled ? "not-allowed" : "pointer", transition: "all .2s", display: "flex", alignItems: "center", justifyContent: "center", gap: 6, opacity: disabled ? .5 : 1, padding: small ? "8px 16px" : "12px 20px", fontSize: small ? 12 : 14, width: full ? "100%" : "auto", ...style, }; const variants = { primary: { background: `linear-gradient(135deg, ${T.gold}, ${T.goldDark})`, color: "#0A0E1A" }, ghost: { background: "transparent", color: T.sub, border: `1px solid ${T.border}` }, danger: { background: T.red + "22", color: T.red, border: `1px solid ${T.red}44` }, success: { background: T.green + "22", color: T.green, border: `1px solid ${T.green}44` }, blue: { background: T.blue + "22", color: T.blue, border: `1px solid ${T.blue}44` }, }; return ; } function Input({ label, placeholder, type = "text", value, onChange, icon }) { return (
{label &&
{label}
}
{icon && {icon}} onChange(e.target.value)} placeholder={placeholder} style={{ width: "100%", background: T.surface, border: `1px solid ${T.border}`, borderRadius: 12, padding: icon ? "12px 14px 12px 40px" : "12px 14px", color: T.text, fontSize: 14, fontFamily: "Sora, sans-serif", outline: "none", transition: "border .2s", }} />
); } // ─── AUTH SCREENS ───────────────────────────────────────────────────────────── function LoginScreen({ onLogin }) { const [tab, setTab] = useState("login"); const [form, setForm] = useState({ identifier: "", password: "", username: "", phone: "", confirm: "" }); const [checking, setChecking] = useState(false); const [usernameOk, setUsernameOk] = useState(null); const [loading, setLoading] = useState(false); const checkUsername = (val) => { setForm(f => ({ ...f, username: val })); if (val.length > 2) { setChecking(true); setTimeout(() => { setUsernameOk(!["admin", "awish", "capitallock"].includes(val.toLowerCase())); setChecking(false); }, 600); } else setUsernameOk(null); }; const handleSubmit = () => { setLoading(true); setTimeout(() => { setLoading(false); onLogin(); }, 1200); }; return (
{/* Logo */}
🔒
CAPITAL LOCK
BY AWISH
{/* Tabs */}
{["login", "register"].map(t => ( ))}
{tab === "login" ? (
setForm(f => ({ ...f, identifier: v }))} icon="👤" /> setForm(f => ({ ...f, password: v }))} icon="🔑" /> {loading ? "Signing in…" : "Sign In →"}
) : (
setForm(f => ({ ...f, fullname: v }))} icon="🧑" />
USERNAME
@ checkUsername(e.target.value)} placeholder="choose a unique username" style={{ width: "100%", background: T.surface, border: `1px solid ${usernameOk === false ? T.red : usernameOk ? T.green : T.border}`, borderRadius: 12, padding: "12px 14px 12px 36px", color: T.text, fontSize: 14, fontFamily: "Sora", outline: "none", }} /> {checking && } {!checking && usernameOk === true && } {!checking && usernameOk === false && }
{usernameOk === false &&
Username already taken
}
setForm(f => ({ ...f, phone: v }))} icon="📱" /> setForm(f => ({ ...f, password: v }))} icon="🔑" /> setForm(f => ({ ...f, confirm: v }))} icon="🔏" /> {loading ? "Creating account…" : "Create Account →"}
)}
); } // ─── NOTIFICATIONS SHEET ────────────────────────────────────────────────────── function NotifSheet({ onClose }) { const notifs = [ { icon: "💰", title: "Queue Progress", body: "Your queue position moved to #3", time: "2 min ago" }, { icon: "🏦", title: "SACCO Reminder", body: "Weekly savings due in 2 days", time: "1 hr ago" }, { icon: "🎉", title: "Blogger Reward", body: "You earned 5,000 CU for your post!", time: "Yesterday" }, ]; return ( {notifs.map((n, i) => (
{n.icon}
{n.title}
{n.body}
{n.time}
))}
); } // ─── BOTTOM SHEET WRAPPER ──────────────────────────────────────────────────── function Sheet({ children, title, onClose }) { return (
e.stopPropagation()} style={{ background: T.surface, borderRadius: "24px 24px 0 0", width: "100%", maxHeight: "88vh", overflow: "hidden", display: "flex", flexDirection: "column", border: `1px solid ${T.border}`, borderBottom: "none", }}> {/* Handle */}
{/* Header */}
{title}
{children}
); } // ─── WALLET SHEET ───────────────────────────────────────────────────────────── function WalletSheet({ onClose }) { const [tab, setTab] = useState("overview"); const [depositAmount, setDepositAmount] = useState(""); const [step, setStep] = useState(1); const calcCU = (ugx) => Math.floor(ugx * 0.85); const calcFee = (ugx) => Math.floor(ugx * 0.15); const handleDeposit = () => { if (step === 1) setStep(2); else { setStep(1); setDepositAmount(""); setTab("overview"); } }; return ( {/* Tabs */}
{["overview", "deposit", "history"].map(t => ( ))}
{tab === "overview" && (
{/* Balances */}
CU BALANCE
{fmtNum(mockUser.cuBalance)}
Capital Units
UGX BALANCE
{fmtNum(mockUser.ugxBalance)}
Ugandan Shilling
{/* CU Explain */}
⚡ HOW CU WORKS
When you deposit UGX, 15% goes to the Reserve Fund and the remaining 85% becomes CU — your in-app currency used across all services.
setTab("deposit")}>+ Deposit Funds
)} {tab === "deposit" && (
{step === 1 && ( <> {depositAmount >= 10000 && (
Deposit Amount {fmtUGX(+depositAmount)}
Reserve Fund (15%) -{fmtUGX(calcFee(+depositAmount))}
You Receive (CU) {fmtNum(calcCU(+depositAmount))} CU
)}
PAYMENT METHOD
{["Mobile Money (MTN)", "Mobile Money (Airtel)", "Bank Transfer"].map((m, i) => (
{i === 0 &&
}
{m} ))}
Continue → )} {step === 2 && (
📱
Confirm on your phone
A payment prompt has been sent to 0701234567.
Enter your Mobile Money PIN to confirm.
{fmtUGX(+depositAmount)}
≈ {fmtNum(calcCU(+depositAmount))} CU after conversion
✓ Payment Confirmed
)}
)} {tab === "history" && (
{mockTransactions.map(tx => (
0 ? T.green : T.red) + "22", display: "flex", alignItems: "center", justifyContent: "center", fontSize: 18, }}> {tx.type === "deposit" ? "⬇️" : tx.type === "reward" ? "🎁" : "⬆️"}
{tx.label}
{tx.date}
0 ? T.green : T.red, fontSize: 13 }}> {tx.amount > 0 ? "+" : ""}{fmtNum(tx.cu)} CU
{tx.status}
))}
)} ); } // ─── QUEUE SHEET ────────────────────────────────────────────────────────────── function QueueSheet({ onClose }) { const [committing, setCommitting] = useState(false); const [amount, setAmount] = useState(""); return (
⚙️ HOW THE QUEUE WORKS
Commit your CU to the FIFO queue. Your funds grow through new deposits, business loan repayments, and reserve support. Fully transparent — track your position live.
{/* My Position */}
MY QUEUE POSITION
#3
COMMITTED
20,000 CU
Progress: 30% Estimated: ~18 days
{/* Queue List */}
LIVE QUEUE
{mockQueue.map(q => (
#{q.position}
@{q.username}{q.isMe ? " (you)" : ""}
{fmtNum(q.committed)} CU
))}
COMMIT MORE CU
setCommitting(true)} disabled={amount < 10000}> Lock CU into Queue
); } // ─── SACCO SHEET ────────────────────────────────────────────────────────────── function SaccoSheet({ onClose }) { const [tab, setTab] = useState("dashboard"); const [loanAmt, setLoanAmt] = useState(""); return (
{["dashboard", "save", "loans"].map(t => ( ))}
{tab === "dashboard" && (
TOTAL SAVINGS
{fmtUGX(mockSacco.savings)}
LOAN ELIGIBLE
{fmtUGX(mockSacco.loanEligible)}
🔥 Savings Streak {mockSacco.streak} weeks
Keep saving weekly to increase your loan eligibility!
{mockSacco.activeLoan > 0 && (
Active Loan {fmtUGX(mockSacco.activeLoan)}
Repaid: {fmtUGX(mockSacco.loanRepaid)} Remaining: {fmtUGX(mockSacco.activeLoan - mockSacco.loanRepaid)}
)}
)} {tab === "save" && (
WEEKLY TARGET
{fmtUGX(mockSacco.weeklyTarget)}
{ }} icon="💰" /> Save This Week
SAVINGS HISTORY
{[1, 2, 3, 4].map(w => (
Week {w}
Apr {28 - w * 7}, 2025
+{fmtUGX(20000)}
saved
))}
)} {tab === "loans" && (
YOUR LOAN LIMIT
{fmtUGX(mockSacco.loanEligible)}
Based on 3× your total savings
{loanAmt >= 50000 && (
LOAN SUMMARY
{[ ["Principal", fmtUGX(+loanAmt)], ["Interest (15%/month)", fmtUGX(Math.floor(+loanAmt * 0.15))], ["Total Repayable", fmtUGX(Math.floor(+loanAmt * 1.15))], ].map(([l, v]) => (
{l} {v}
))}
)} mockSacco.loanEligible}>Apply for Loan
)}
); } // ─── BUSINESS SHEET ─────────────────────────────────────────────────────────── function BusinessSheet({ onClose }) { const [tab, setTab] = useState("list"); const [step, setStep] = useState(1); return (
{["list", "register", "funding"].map(t => ( ))}
{tab === "list" && (
{mockBusinesses.map(b => (
{b.name}
{b.category}
{b.status}
{b.loan > 0 && ( <>
Loan: {fmtUGX(b.loan)} Repaid: {fmtUGX(b.repaid)}
)}
))} setTab("register")}> + Register a Business
)} {tab === "register" && (
VERIFICATION FEE
UGX 50,000
One-time fee to verify your business
{ }} icon="🏢" /> { }} icon="📂" /> { }} icon="📱" /> { }} icon="📍" />
UPLOAD DOCUMENTS
📎
Tap to upload business documents
Pay Fee & Register →
)} {tab === "funding" && (
Kampala Bakers Ltd
Verified Business
CURRENT FUNDING STATUS
{fmtUGX(500000)}
64% repaid (UGX 320,000)
{ }} icon="💼" /> { }} icon="📋" /> { }} icon="📅" /> Apply for Business Funding
)}
); } // ─── BLOGGER SHEET ──────────────────────────────────────────────────────────── function BloggerSheet({ onClose }) { const [tab, setTab] = useState("bloggers"); return (
{["bloggers", "apply", "ads"].map(t => ( ))}
{tab === "bloggers" && (
💡 HOW TO EARN
Apply as a blogger, post about CAPITAL LOCK on your socials, submit post links, and earn CU rewards based on your engagement!
{mockBloggers.map(b => (
x[0]).join("")} color={T.purple} />
{b.name}
{b.platform} • {b.followers}
{b.status}
{b.posts}
Posts
{fmtNum(b.rewards)} CU
Rewards
))}
)} {tab === "apply" && (
{ }} icon="📲" /> { }} icon="🔗" /> { }} icon="👥" /> { }} icon="📝" />
SCREENSHOT OF POST
📸
Upload screenshot as proof
Submit for Review →
)} {tab === "ads" && (
📢 ACTIVE ADS FEED
{mockAds.map(ad => (
{ad.type === "video" ? "🎬" : "🖼️"}
{ad.business}
👁️ {fmtNum(ad.views)} views
⏱️ {ad.expires}
))}
POST YOUR AD
AD FEE
UGX 10,000
Ad visible for 24 hours
📤
Upload image or video
Post Ad (10,000 UGX)
)}
); } // ─── ADMIN PANEL ────────────────────────────────────────────────────────────── function AdminPanel({ onExit }) { const [section, setSection] = useState("dashboard"); const stats = [ { label: "Total Users", value: "1,247", icon: "👥", color: T.blue }, { label: "Total CU in System", value: "8.4M", icon: "💎", color: T.gold }, { label: "Reserve Fund", value: "UGX 2.1M", icon: "🏛️", color: T.green }, { label: "Active Queue", value: "89 users", icon: "🔄", color: T.purple }, { label: "Verified Businesses", value: "23", icon: "🏢", color: T.cyan }, { label: "Active Bloggers", value: "41", icon: "📣", color: T.red }, ]; const sections = ["dashboard", "users", "businesses", "bloggers", "queue", "transactions", "settings"]; return (
{/* Sidebar */}
🔒
CAPITAL LOCK
Admin Panel
{sections.map(s => ( ))}
← Exit Admin
{/* Content */}
{section === "dashboard" && ( <>
Admin Dashboard
AWISH Capital Lock — System Overview
{stats.map(s => (
{s.icon}
{s.value}
{s.label}
))}
📈 Reserve Fund Flow
{[["Total Deposited", "UGX 12.4M", T.blue], ["Reserve (15%)", "UGX 1.86M", T.gold], ["In Queue", "UGX 8.4M", T.purple], ["Business Loans", "UGX 2.1M", T.cyan]].map(([l, v, c]) => (
{v}
{l}
))}
)} {section === "users" && ( <>
User Management
{[ { name: "Alex Tumwine", username: "alex_t", phone: "0701234567", cu: 42500, status: "active" }, { name: "Sarah Mukasa", username: "sarah_m", phone: "0782345678", cu: 128000, status: "active" }, { name: "James Kato", username: "james_k", phone: "0753456789", cu: 320000, status: "active" }, { name: "Grace Nakato", username: "grace_n", phone: "0714567890", cu: 85000, status: "suspended" }, ].map((u, i) => ( x[0]).join("")} />
{u.name}
@{u.username} • {u.phone}
{fmtNum(u.cu)} CU
{u.status}
View Suspend
))} )} {section === "businesses" && ( <>
Business Management
{[...mockBusinesses, { id: 3, name: "Nakawa Market Vendors", category: "Retail", status: "pending", loan: 0, repaid: 0 }].map(b => (
{b.name}
{b.category}
{b.status} {b.status === "pending" && ✓ Verify} Details
{b.loan > 0 && (
Loan: {fmtUGX(b.loan)} | Repaid: {fmtUGX(b.repaid)}
)}
))} )} {section === "bloggers" && ( <>
Blogger Management
{mockBloggers.map(b => (
x[0]).join("")} color={T.purple} size={34} />
{b.name}
{b.platform} • {b.followers} followers • {b.posts} posts
{b.status} {b.status === "review" && Approve} Reward CU
))} )} {section === "queue" && ( <>
Queue Management
{mockQueue.map(q => (
#{q.position}
@{q.username}
Progress: {q.progress}%
{fmtNum(q.committed)} CU
))} )} {section === "transactions" && ( <>
All Transactions
{[ ...mockTransactions, { id: 5, type: "deposit", label: "Deposit – james_k", amount: 100000, cu: 85000, date: "Yesterday", status: "completed" }, { id: 6, type: "loan", label: "Business Loan – Kampala Bakers", amount: 500000, cu: 500000, date: "Apr 20", status: "completed" }, ].map(tx => (
0 ? T.green : T.red) + "22", display: "flex", alignItems: "center", justifyContent: "center", fontSize: 16, }}> {tx.type === "deposit" ? "⬇️" : tx.type === "loan" ? "🏦" : tx.type === "reward" ? "🎁" : "⬆️"}
{tx.label}
{tx.date}
0 ? T.green : T.red, fontWeight: 700 }}> {tx.amount > 0 ? "+" : ""}{fmtUGX(Math.abs(tx.amount))}
{tx.status}
))} )} {section === "settings" && ( <>
System Settings
⚙️ Economy Parameters
{[ ["Reserve Fund Rate", "15%"], ["CU Conversion Rate", "85% of deposit"], ["Minimum Deposit", "UGX 10,000"], ["SACCO Weekly Minimum", "UGX 20,000"], ["Business Verification Fee", "UGX 50,000"], ["Loan Interest Rate", "15% / month"], ["Ad Fee (24h)", "UGX 10,000"], ].map(([k, v]) => (
{k} {v}
))}
🔑 Admin Accounts
Super Admin
admin@capitallock.ug
SUPER
)}
); } // ─── MAIN APP ───────────────────────────────────────────────────────────────── export default function App() { const [route, setRoute] = useState("login"); // login | app | admin | install const [activeSheet, setActiveSheet] = useState(null); const [notifOpen, setNotifOpen] = useState(false); const [notifRing, setNotifRing] = useState(false); const [url, setUrl] = useState("/index"); // Simulate URL routing useEffect(() => { if (url === "/supperaccount/login") setRoute("admin"); else if (url === "/supperaccount/install") setRoute("install"); else if (url === "/index") setRoute("login"); }, [url]); const openSheet = (name) => setActiveSheet(name); const closeSheet = () => setActiveSheet(null); const ringNotif = () => { setNotifRing(true); setTimeout(() => setNotifRing(false), 400); setNotifOpen(true); }; if (route === "install") return setRoute("admin")} />; if (route === "admin") return setRoute("app")} />; if (route === "login") return setRoute("app")} />; const tabs = [ { id: "queue", icon: "🔄", label: "Queue" }, { id: "sacco", icon: "🏦", label: "SACCO" }, { id: "wallet", icon: "💼", label: "Wallet", big: true }, { id: "business", icon: "🏢", label: "Business" }, { id: "blogger", icon: "📣", label: "Blogger" }, ]; return (
{/* TOP BAR */}
{/* Balance */}
ACTIVE BALANCE
{fmtNum(mockUser.cuBalance)} CU
{/* Right: notif + profile */}
{/* Admin shortcut */} {/* Bell */}
{mockUser.notifications}
{/* HOME CONTENT */}
{/* Welcome */}
Good morning,
{mockUser.name} 👋
{/* Quick Stats */}
openSheet("queue")} style={{ cursor: "pointer" }}>
QUEUE POSITION
#3
30% funded
openSheet("sacco")} style={{ cursor: "pointer" }}>
SACCO SAVINGS
UGX 80K
🔥 4-week streak
{/* Ads Feed */}
📢 ADS FEED
{mockAds.map(ad => (
{ad.type === "video" ? "🎬" : "🖼️"}
{ad.business}
⏱️ {ad.expires}
))}
{/* Recent Transactions */}
🕐 RECENT ACTIVITY
{mockTransactions.slice(0, 3).map(tx => (
0 ? T.green : T.red) + "22", display: "flex", alignItems: "center", justifyContent: "center", fontSize: 16, }}> {tx.type === "deposit" ? "⬇️" : tx.type === "reward" ? "🎁" : "⬆️"}
{tx.label}
{tx.date}
0 ? T.green : T.red, fontSize: 13 }}> {tx.cu > 0 ? "+" : ""}{fmtNum(tx.cu)} CU
))}
{/* BOTTOM NAV */}
{tabs.map(t => ( t.big ? ( ) : ( ) ))}
{/* SHEETS */} {notifOpen && setNotifOpen(false)} />} {activeSheet === "wallet" && } {activeSheet === "queue" && } {activeSheet === "sacco" && } {activeSheet === "business" && } {activeSheet === "blogger" && }
); } // ─── INSTALL SCREEN ─────────────────────────────────────────────────────────── function InstallScreen({ onDone }) { const [step, setStep] = useState(1); const [form, setForm] = useState({ dbHost: "localhost", dbPort: "3306", dbName: "", dbUser: "", dbPass: "", adminName: "", adminEmail: "", adminPass: "" }); const [installing, setInstalling] = useState(false); const runInstall = () => { setInstalling(true); setTimeout(() => { setInstalling(false); onDone(); }, 2500); }; return (
🔒
CAPITAL LOCK
Installation Wizard
{/* Steps */}
{[1, 2, 3].map(s => (
{s < step ? "✓" : s}
{s < 3 &&
}
))}
{step === 1 && (
🗄️ Database Configuration
setForm(f => ({ ...f, dbHost: v }))} placeholder="localhost" /> setForm(f => ({ ...f, dbPort: v }))} placeholder="3306" /> setForm(f => ({ ...f, dbName: v }))} placeholder="capitallock_db" /> setForm(f => ({ ...f, dbUser: v }))} placeholder="root" /> setForm(f => ({ ...f, dbPass: v }))} placeholder="••••••••" /> setStep(2)}>Next: Admin Account →
)} {step === 2 && (
👤 Admin Account Setup
setForm(f => ({ ...f, adminName: v }))} placeholder="Super Administrator" /> setForm(f => ({ ...f, adminEmail: v }))} placeholder="admin@capitallock.ug" /> setForm(f => ({ ...f, adminPass: v }))} placeholder="Create a strong password" />
setStep(1)}>← Back setStep(3)}>Next: Review & Install →
)} {step === 3 && (
✅ Review & Install
{[ ["Database Host", form.dbHost || "localhost"], ["Database Port", form.dbPort || "3306"], ["Database", form.dbName || "(not set)"], ["Admin Name", form.adminName || "(not set)"], ["Admin Email", form.adminEmail || "(not set)"], ].map(([k, v]) => (
{k} {v}
))}
{installing ? (
⚙️
Installing Capital Lock…
) : (
setStep(2)}>← Back 🚀 Install Now
)}
)}
); }