import { useState, useEffect } from "react"; // ── CONFIG ──────────────────────────────────────────────────── const API_BASE = "https://yoursite.com"; const DEMO_USERS = [ { id:1, username:"superadmin", password:"Admin@1234", full_name:"Sheperd Admin", role:"superadmin", email:"admin@sheperd.co.uk" }, { id:2, username:"admin", password:"Admin@1234", full_name:"License Admin", role:"admin", email:"admin2@sheperd.co.uk" }, { id:3, username:"viewer", password:"Admin@1234", full_name:"Report Viewer", role:"viewer", email:"viewer@sheperd.co.uk" }, ]; const PRODUCTS = ["BI Pro","DataViz","EduTrack","CRM Suite","Analytics Plus"]; const MOCK_LICENSES = [ { id:1, license_key:"A1B2-C3D4-E5F6-G7H8", client_name:"Acme Corp", email:"admin@acme.com", product:"BI Pro", issued_date:"2025-01-01", expiry_date:"2026-12-01", is_active:1, max_activations:5, current_activations:3 }, { id:2, license_key:"X9Y8-Z7W6-V5U4-T3S2", client_name:"Gulf Tech LLC", email:"it@gulftech.sa", product:"DataViz", issued_date:"2025-03-15", expiry_date:"2025-12-31", is_active:1, max_activations:2, current_activations:2 }, { id:3, license_key:"P1Q2-R3S4-T5U6-V7W8", client_name:"Kerala Schools", email:"admin@keralaschools.in", product:"EduTrack", issued_date:"2024-06-01", expiry_date:"2025-06-01", is_active:0, max_activations:10,current_activations:0 }, { id:4, license_key:"M1N2-O3P4-Q5R6-S7T8", client_name:"NRI Helpdesk", email:"support@nrihelpdesk.com", product:"BI Pro", issued_date:"2025-07-01", expiry_date:"2026-07-01", is_active:1, max_activations:3, current_activations:1 }, { id:5, license_key:"D4E5-F6G7-H8I9-J0K1", client_name:"TechStart Ltd", email:"cto@techstart.io", product:"CRM Suite", issued_date:"2025-09-01", expiry_date:"2026-09-01", is_active:1, max_activations:1, current_activations:1 }, ]; const genKey = () => { const s=()=>Math.random().toString(36).substring(2,6).toUpperCase(); return `${s()}-${s()}-${s()}-${s()}`; }; const isExpired = d => new Date(d) < new Date(); const daysLeft = d => Math.max(0, Math.ceil((new Date(d)-new Date())/86400000)); const roleColor = r => ({superadmin:{bg:"#312e81",color:"#a5b4fc"},admin:{bg:"#052e16",color:"#4ade80"},viewer:{bg:"#422006",color:"#fb923c"}}[r]||{bg:"#1e293b",color:"#94a3b8"}); const roleIcon = r => ({superadmin:"👑",admin:"🛡️",viewer:"👁️"}[r]||"👤"); const can = (user, perm) => { const perms = { superadmin:["all"], admin:["license.view","license.create","license.edit","license.delete","license.toggle","report.export"], viewer:["license.view","report.export"] }; const p = perms[user?.role]||[]; return p.includes("all") || p.includes(perm); }; // ── STATUS BADGE ───────────────────────────────────────────── function Badge({active, expiry}) { if (!active) return Inactive; if (isExpired(expiry)) return Expired; return Active; } // ── TOAST ──────────────────────────────────────────────────── function Toast({toast}) { if (!toast) return null; const styles = {success:{bg:"#052e16",color:"#4ade80",border:"1px solid #166534"},error:{bg:"#450a0a",color:"#f87171",border:"1px solid #7f1d1d"},info:{bg:"#0c1445",color:"#818cf8",border:"1px solid #312e81"}}; const s = styles[toast.type]||styles.info; return
{toast.msg}
; } // ════════════════════════════════════════════════════════════ export default function App() { const [user, setUser] = useState(null); const [page, setPage] = useState("dashboard"); const [licenses, setLicenses] = useState(MOCK_LICENSES); const [selected, setSelected] = useState(null); const [toast, setToast] = useState(null); // login const [creds, setCreds] = useState({username:"",password:""}); const [showPass, setShowPass] = useState(false); const [loginErr, setLoginErr] = useState(""); const [loginLoad, setLoginLoad] = useState(false); // forgot const [forgotEmail, setForgotEmail] = useState(""); const [forgotMsg, setForgotMsg] = useState({err:"",suc:""}); // list filters const [search, setSearch] = useState(""); const [fProd, setFProd] = useState("All"); const [fStatus, setFStatus] = useState("All"); // new license form const [form, setForm] = useState({client_name:"",email:"",product:"BI Pro",expiry_date:"",max_activations:1,license_key:genKey()}); const [formErr, setFormErr] = useState(""); // sidebar collapse on small const [sideOpen, setSideOpen] = useState(true); const showToast = (msg, type="success") => { setToast({msg,type}); setTimeout(()=>setToast(null),3200); }; // ── LOGIN ── const doLogin = async () => { setLoginErr(""); if (!creds.username||!creds.password) { setLoginErr("Please enter username and password."); return; } setLoginLoad(true); await new Promise(r=>setTimeout(r,1000)); const found = DEMO_USERS.find(u=>u.username===creds.username&&u.password===creds.password); setLoginLoad(false); if (!found) { setLoginErr("Invalid username or password."); return; } setUser(found); setPage("dashboard"); }; const doLogout = () => { setUser(null); setCreds({username:"",password:""}); setPage("dashboard"); showToast("Logged out successfully.","info"); }; // ── FORGOT ── const doForgot = async () => { setForgotMsg({err:"",suc:""}); if (!forgotEmail) { setForgotMsg({err:"Enter your email address.",suc:""}); return; } await new Promise(r=>setTimeout(r,800)); setForgotMsg({err:"",suc:`Reset link sent to ${forgotEmail}.`}); }; // ── LICENSE ACTIONS ── const toggleLicense = id => { setLicenses(p=>p.map(l=>l.id===id?{...l,is_active:l.is_active?0:1}:l)); showToast("License status updated."); }; const deleteLicense = id => { setLicenses(p=>p.filter(l=>l.id!==id)); setSelected(null); showToast("License deleted.","error"); }; const addLicense = () => { if (!form.client_name||!form.email||!form.expiry_date) { setFormErr("All fields are required."); return; } setLicenses(p=>[{...form,id:Date.now(),issued_date:new Date().toISOString().split("T")[0],is_active:1,current_activations:0},...p]); setForm({client_name:"",email:"",product:"BI Pro",expiry_date:"",max_activations:1,license_key:genKey()}); setFormErr(""); showToast("License created successfully!"); setPage("list"); }; const copyKey = k => { navigator.clipboard?.writeText(k); showToast("Key copied to clipboard!"); }; // ── FILTERED LIST ── const filtered = licenses.filter(l=>{ const q=search.toLowerCase(); const ms=!q||l.license_key.toLowerCase().includes(q)||l.client_name.toLowerCase().includes(q)||l.email.toLowerCase().includes(q); const mp=fProd==="All"||l.product===fProd; const mst=fStatus==="All"||(fStatus==="Active"&&l.is_active&&!isExpired(l.expiry_date))||(fStatus==="Expired"&&isExpired(l.expiry_date))||(fStatus==="Inactive"&&!l.is_active); return ms&&mp&&mst; }); const stats = { total:licenses.length, active:licenses.filter(l=>l.is_active&&!isExpired(l.expiry_date)).length, expired:licenses.filter(l=>isExpired(l.expiry_date)).length, inactive:licenses.filter(l=>!l.is_active).length }; // ════ STYLES ═══════════════════════════════════════════════ const S = { app: {fontFamily:"'Segoe UI',sans-serif",background:"#0f172a",minHeight:"100vh",color:"#e2e8f0"}, card: {background:"#1e293b",border:"1px solid #334155",borderRadius:12,padding:20}, inp: {width:"100%",background:"#0f172a",border:"1.5px solid #334155",color:"#e2e8f0",borderRadius:10,padding:"11px 14px",fontSize:13,outline:"none"}, lbl: {fontSize:11,color:"#94a3b8",marginBottom:5,display:"block",fontWeight:700,letterSpacing:.5}, btnP: {padding:"9px 18px",background:"#6366f1",color:"white",border:"none",borderRadius:8,fontSize:13,fontWeight:600,cursor:"pointer"}, btnG: {padding:"9px 18px",background:"#1e293b",color:"#94a3b8",border:"1px solid #334155",borderRadius:8,fontSize:13,fontWeight:600,cursor:"pointer"}, th: {padding:"10px 14px",textAlign:"left",color:"#64748b",fontSize:11,letterSpacing:.8,textTransform:"uppercase",borderBottom:"1px solid #334155"}, td: {padding:"12px 14px",borderBottom:"1px solid #1e293b",verticalAlign:"middle",fontSize:13}, }; // ════ CSS INJECTION ════════════════════════════════════════ useEffect(()=>{ const style=document.createElement("style"); style.innerHTML=` *{box-sizing:border-box;margin:0;padding:0} @keyframes si{from{transform:translateY(20px);opacity:0}to{transform:translateY(0);opacity:1}} @keyframes sp{to{transform:rotate(360deg)}} .spin{width:16px;height:16px;border:2px solid rgba(255,255,255,.3);border-top-color:#fff;border-radius:50%;animation:sp .7s linear infinite;display:inline-block;vertical-align:middle;margin-right:6px} .inp:focus{border-color:#6366f1!important;box-shadow:0 0 0 3px rgba(99,102,241,.15)} .btn-main{width:100%;padding:13px;background:linear-gradient(135deg,#6366f1,#8b5cf6);color:white;border:none;border-radius:10px;font-size:15px;font-weight:700;cursor:pointer;transition:opacity .2s} .btn-main:hover:not(:disabled){opacity:.88} .btn-main:disabled{opacity:.6;cursor:not-allowed} .nav-item{padding:10px 14px;border-radius:8px;cursor:pointer;font-size:13px;font-weight:600;color:#94a3b8;display:flex;align-items:center;gap:8px;transition:background .15s} .nav-item:hover{background:#1e293b;color:#fff} .nav-item.active{background:#312e81;color:#a5b4fc} .trow:hover td{background:#1e293b} .chip{background:#1e1b4b;border:1px solid #3730a3;color:#a5b4fc;padding:5px 12px;border-radius:6px;font-size:11px;cursor:pointer;font-weight:600} .chip:hover{background:#312e81} .key-chip{font-family:monospace;font-size:11px;background:#0f172a;border:1px solid #334155;padding:4px 8px;border-radius:6px;letter-spacing:1px;cursor:pointer;white-space:nowrap} .key-chip:hover{border-color:#6366f1} .pb{background:#0f172a;border-radius:10px;height:5px;overflow:hidden;margin-top:4px} .pf{height:100%;border-radius:10px;background:linear-gradient(90deg,#6366f1,#8b5cf6)} .modal-bg{position:fixed;inset:0;background:rgba(0,0,0,.75);display:flex;align-items:center;justify-content:center;z-index:100} .modal{background:#1e293b;border:1px solid #334155;border-radius:16px;padding:28px;width:500px;max-width:95vw} .div-line{display:flex;align-items:center;gap:12px;color:#475569;font-size:12px;margin:18px 0 12px} .div-line::before,.div-line::after{content:'';flex:1;height:1px;background:#334155} select{background:#0f172a;border:1.5px solid #334155;color:#e2e8f0;border-radius:10px;padding:11px 14px;font-size:13px;width:100%;outline:none} select:focus{border-color:#6366f1} input[type=date]{color-scheme:dark} .sb-btn:hover{background:#991b1b!important} `; document.head.appendChild(style); return ()=>document.head.removeChild(style); },[]); // ════ LOGIN SCREEN ════════════════════════════════════════ if (!user) return (
{page==="login"||page==="dashboard" ? (
🔑
LicenseHQ
Sheperd Limited — Admin Portal
Welcome back 👋
Sign in to manage your licenses
USERNAME
👤 {setCreds(f=>({...f,username:e.target.value}));setLoginErr("");}} onKeyDown={e=>e.key==="Enter"&&doLogin()} />
PASSWORD setPage("forgot")}>Forgot password?
🔒 {setCreds(f=>({...f,password:e.target.value}));setLoginErr("");}} onKeyDown={e=>e.key==="Enter"&&doLogin()} /> setShowPass(s=>!s)} style={{position:"absolute",right:13,top:"50%",transform:"translateY(-50%)",cursor:"pointer",fontSize:15,color:"#64748b"}}>{showPass?"🙈":"👁️"}
{loginErr &&
⚠️ {loginErr}
}
Quick Demo Login
{DEMO_USERS.map(u=>( setCreds({username:u.username,password:u.password})}> {roleIcon(u.role)} {u.username} ))}
Click a chip to auto-fill · Password: Admin@1234
© 2026 Sheperd Limited · All rights reserved
) : (
📧
Reset Password
Enter your email to receive a reset link
EMAIL ADDRESS
📧 {setForgotEmail(e.target.value);setForgotMsg({err:"",suc:""});}} />
{forgotMsg.err &&
⚠️ {forgotMsg.err}
} {forgotMsg.suc &&
✅ {forgotMsg.suc}
}
{setPage("login");setForgotMsg({err:"",suc:""});}}>← Back to Login
)}
); // ════ MAIN APP ════════════════════════════════════════════ return (
{/* ── SIDEBAR ── */}
🔑 LicenseHQ
Sheperd Limited
{[ ["dashboard","📊","Dashboard"], ["list","📋","All Licenses"], ...(can(user,"license.create")?[["add","➕","New License"]]:[]), ...(can(user,"user.manage")?[["users","👥","Users"]]:[]), ].map(([id,ic,lb])=>(
setPage(id)}>{ic} {lb}
))}
{user.full_name[0]}
{user.full_name}
{roleIcon(user.role)} {user.role}
Session Active
{/* ── CONTENT ── */}
{/* ── DASHBOARD PAGE ── */} {page==="dashboard" && (
Welcome back, {user.full_name.split(" ")[0]}! 👋
{new Date().toLocaleDateString("en-GB",{weekday:"long",year:"numeric",month:"long",day:"numeric"})} · Logged in as {user.username}
{roleIcon(user.role)} {user.role.toUpperCase()}
{/* Stats */}
{[ {label:"Total Licenses",val:stats.total,icon:"🔑",color:"#6366f1"}, {label:"Active",val:stats.active,icon:"✅",color:"#4ade80"}, {label:"Expired",val:stats.expired,icon:"⏰",color:"#fb923c"}, {label:"Inactive",val:stats.inactive,icon:"🚫",color:"#818cf8"}, ].map(s=>(
{s.icon}
{s.val}
{s.label}
))}
{/* Recent licenses */}
📋 Recent Licenses
{["Client","Product","Key","Expires","Status"].map(h=>)} {licenses.slice(0,5).map(l=>( setSelected(l)}> ))}
{h}
{l.client_name}
{l.email}
{l.product} {e.stopPropagation();copyKey(l.license_key);}}>{l.license_key} {l.expiry_date}
{daysLeft(l.expiry_date)}d left
)} {/* ── LIST PAGE ── */} {page==="list" && (
All Licenses
{filtered.length} of {licenses.length} licenses
{can(user,"license.create") && }
🔍 setSearch(e.target.value)}/>
{["Client","Product","License Key","Activations","Expires","Status","Actions"].map(h=>)} {filtered.map(l=>( ))} {filtered.length===0 && }
{h}
{l.client_name}
{l.email}
{l.product} copyKey(l.license_key)}>{l.license_key}
{l.current_activations}/{l.max_activations}
{l.expiry_date}
{daysLeft(l.expiry_date)}d left
{can(user,"license.toggle") && ( )}
No licenses found.
)} {/* ── ADD LICENSE PAGE ── */} {page==="add" && can(user,"license.create") && (
Create New License
Fill in the details to generate a license key
LICENSE KEY (AUTO-GENERATED)
CLIENT NAME * {setForm(f=>({...f,client_name:e.target.value}));setFormErr("");}}/>
EMAIL * {setForm(f=>({...f,email:e.target.value}));setFormErr("");}}/>
PRODUCT
MAX ACTIVATIONS setForm(f=>({...f,max_activations:parseInt(e.target.value)||1}))}/>
EXPIRY DATE * {setForm(f=>({...f,expiry_date:e.target.value}));setFormErr("");}}/>
{formErr &&
⚠️ {formErr}
}
)} {/* ── USERS PAGE ── */} {page==="users" && can(user,"user.manage") && (
User Management
Admin portal accounts and roles
{["User","Email","Role","Status","Actions"].map(h=>)} {DEMO_USERS.map(u=>( ))}
{h}
{u.full_name[0]}
{u.full_name}
@{u.username}
{u.email} {roleIcon(u.role)} {u.role} Active
{u.username!=="superadmin" && }
)}
{/* ── DETAIL MODAL ── */} {selected && (
setSelected(null)}>
e.stopPropagation()}>
License Details
{selected.license_key}
{[["Client",selected.client_name],["Email",selected.email],["Product",selected.product],["Issued",selected.issued_date],["Expires",`${selected.expiry_date} (${daysLeft(selected.expiry_date)} days left)`],["Activations",`${selected.current_activations} / ${selected.max_activations}`]].map(([k,v])=>(
{k}{v}
))}
Status
{can(user,"license.toggle")||can(user,"license.delete") ? (
{can(user,"license.toggle") && ( )} {can(user,"license.delete") && ( )}
) :
You have view-only access.
}
)}
); }