import { useState, useEffect, useRef } from "react"; // ── DESIGN TOKENS ───────────────────────────────────────────────────────────── const C = { primary: "#6760f9", primaryHover: "#5a53e0", primarySurface: "#eff2fe", textBase: "#040711", textSecondary: "#656975", textDisabled: "#9fa2ab", white: "#ffffff", bg0: "#ffffff", bg05: "#fbfbfb", bg1: "#f6f6f7", bg2: "#f2f2f2", bg3: "#ebebed", borderT0: "rgba(0,0,0,0.05)", borderT1: "rgba(0,0,0,0.10)", borderT2: "rgba(0,0,0,0.20)", solidBorder1: "#d6d8db", quoted: "#ef9536", newClient: "#49a08a", imported: "#3382f4", sold: "#5353f0", followUpBg: "#f8d2e0", lost: "#b7b5b5", errorRed: "#ef4444", successGreen: "#10b981", infoBlue: "#3b82f6", }; const FONT = { fontFamily: "Inter, -apple-system, sans-serif" }; // ── NOTIFICATION DATA ───────────────────────────────────────────────────────── const initNotifications = [ { id: 1, type: "error", action: "Fix Now", time: "2m ago", read: false, order: 1 }, { id: 2, type: "error", action: "Add Email Address", time: "5m ago", read: false, order: 2 }, { id: 3, type: "error", action: "Add Policy", time: "12m ago", read: false, order: 3 }, { id: 12, type: "error", action: "Fix Now", time: "2h ago", read: false, order: 4 }, { id: 6, type: "info", action: null, time: "3h ago", read: true, order: 5 }, { id: 14, type: "error", action: "Fix Now", time: "3h ago", read: true, order: 6 }, { id: 15, type: "info", action: null, time: "3h ago", read: true, order: 7 }, { id: 7, type: "info", action: null, time: "4h ago", read: true, order: 8 }, { id: 5, type: "error", action: "Resend Link", time: "4h ago", read: true, order: 9 }, { id: 17, type: "success", action: "Download", time: "5h ago", read: true, order: 10 }, { id: 16, type: "info", action: null, time: "5h ago", read: true, order: 11 }, { id: 9, type: "info", action: null, time: "6h ago", read: true, order: 12 }, { id: 18, type: "info", action: null, time: "6h ago", read: true, order: 13 }, { id: 11, type: "info", action: null, time: "7h ago", read: true, order: 14 }, { id: 19, type: "info", action: null, time: "7h ago", read: true, order: 15 }, { id: 10, type: "info", action: null, time: "Yesterday", read: true, order: 16 }, ]; const whatsNew = [ { id: 1, title: "Screenshot-to-Quote", desc: "Capture a screenshot of any carrier quote and let AI extract the data automatically." }, { id: 2, title: "Client Events", desc: "Track client activity including portal visits, quote responses, document uploads, and more." }, { id: 3, title: "Create New Clients via OCR", desc: "Create new clients manually or by uploading a document and letting OCR extract the details." }, ]; // ── SETTINGS DATA ───────────────────────────────────────────────────────────── const settingsGroups = [ { id: "client", label: "Client Updates", desc: "New leads, assignments, and status changes.", items: [ { id: "client_assigned", label: "You were assigned a new client" }, { id: "client_lead", label: "A new lead came in" }, { id: "client_status", label: "Client status changed" }, ], }, { id: "forms", label: "Form & Document Activity", desc: "Form submissions, document uploads, and share link activity.", items: [ { id: "form_submission", label: "Client completed a form submission" }, { id: "form_pdf", label: "Client completed a PDF supplement" }, { id: "form_upload", label: "Client uploaded a document" }, { id: "form_quote", label: "Client responded to their quote" }, { id: "form_link_opened", label: "Form share link was opened" }, { id: "form_link_expired", label: "Form link expired" }, { id: "form_export", label: "Your Advanced Export is ready" }, ], }, { id: "workflow", label: "Workflow Activity", desc: "Completed workflows and workflow errors.", items: [ { id: "workflow_completed", label: "Workflow completed" }, { id: "workflow_failed", label: "Workflow failed" }, ], }, ]; // ── CLIENTS DATA ────────────────────────────────────────────────────────────── const CLIENTS = [ { id: 1, name: "John Doe", status: "Follow Up", days: 8, pipeline: "New Business", lines: ["home","auto"], form: "New Policy Application Form", ftype: "Intake form", source: "Website", agent: "John Doe" }, { id: 2, name: "Alex Carter", status: "Lost", days: 0, pipeline: "Re-Marketing", lines: ["life"], form: "Audit Request Form", ftype: "Customer form", source: "Referral", agent: "Alex Carter" }, { id: 3, name: "Sophia Taylor", status: "Quoted", days: 4, pipeline: "Re-Marketing", lines: ["home","umbrella"], form: "Account Verification Form", ftype: "Intake form", source: "Call-In", agent: "Sophia Taylor" }, { id: 4, name: "Jessica Brown", status: "Imported", days: 2, pipeline: "Marketing Leads", lines: ["auto","home","umbrella","life"], form: "User Access Request Form", ftype: "Intake form", source: "Referral", agent: "Jessica Brown" }, { id: 5, name: "Daniel Martinez", status: "Sold", days: 4, pipeline: "New Business", lines: ["home"], form: "Service Request Form", ftype: "Customer form", source: "Website", agent: "Daniel Martinez" }, { id: 6, name: "Olivia Garcia", status: "Quoted", days: 1, pipeline: "Re-Marketing", lines: ["auto","home","life"], form: "Data Privacy Consent Form", ftype: "Customer form", source: "Call-In", agent: "Olivia Garcia" }, { id: 7, name: "Mia Harris", status: "Follow Up", days: 8, pipeline: "New Business", lines: ["auto"], form: "Incident Report Form", ftype: "Intake form", source: "Referral", agent: "Mia Harris" }, { id: 8, name: "Ethan White", status: "New Client", days: 0, pipeline: "Marketing Leads", lines: ["home"], form: "Claim Submission Form", ftype: "Intake form", source: "Call-In", agent: "Ethan White" }, { id: 9, name: "Isabella Lewis", status: "Lost", days: 8, pipeline: "Marketing Leads", lines: [], form: "Feedback Survey Form", ftype: "Intake form", source: "Website", agent: "Isabella Lewis" }, { id: 10, name: "Ava Jackson", status: "Quoted", days: 1, pipeline: "Re-Marketing", lines: ["auto","home","life"], form: "Customer Feedback Form", ftype: "Customer form", source: "Referral", agent: "Ava Jackson" }, { id: 11, name: "William Thomas", status: "Sold", days: 0, pipeline: "New Business", lines: ["auto"], form: "Change of Beneficiary Form", ftype: "Intake form", source: "Call-In", agent: "William Thomas" }, { id: 12, name: "David Wilson", status: "Imported", days: 4, pipeline: "Re-Marketing", lines: ["home"], form: "Coverage Adjustment Form", ftype: "Customer form", source: "Call-In", agent: "David Wilson" }, { id: 13, name: "Emily Davis", status: "Follow Up", days: 8, pipeline: "Re-Marketing", lines: ["home","auto"], form: "Risk Assessment Form", ftype: "Intake form", source: "Referral", agent: "Emily Davis" }, ]; const STATUS_STYLE = { "Follow Up": { bg: C.followUpBg, color: C.textBase }, "Lost": { bg: C.lost, color: C.white }, "Quoted": { bg: C.quoted, color: C.white }, "Imported": { bg: C.imported, color: C.white }, "Sold": { bg: C.sold, color: C.white }, "New Client": { bg: C.newClient, color: C.white }, }; const STATUS_TABS = [ { label: "Total (80)", amount: "$500k" }, { label: "Quoted (20)", amount: "$200k", bg: C.quoted, color: C.white }, { label: "New Client (30)", amount: "$50k", bg: C.newClient, color: C.white }, { label: "Imported (10)", amount: "$100k", bg: C.imported, color: C.white }, { label: "Sold (5)", amount: "$75k", bg: C.sold, color: C.white }, { label: "Follow Up (10)", amount: "$50k", bg: C.followUpBg, color: C.textBase }, { label: "Lost (5)", amount: "$25k", bg: C.lost, color: C.white }, ]; // ── AVATAR ──────────────────────────────────────────────────────────────────── const PALETTE = [ { bg: "#eff2fe", fg: "#6760f9" }, { bg: "#e4fbe8", fg: "#3c7f3f" }, { bg: "#cefafe", fg: "#007595" }, { bg: "#f8e4e2", fg: "#cc311a" }, { bg: "#fbf4cb", fg: "#a85701" }, { bg: "#f2f2f2", fg: "#656975" }, ]; const initials = (n) => n.split(" ").map(w => w[0]).join("").slice(0,2).toUpperCase(); const Avatar = ({ name, size = 24 }) => { const { bg, fg } = PALETTE[name.charCodeAt(0) % PALETTE.length]; return ( {initials(name)} ); }; // ── POLICY LINE ICONS ───────────────────────────────────────────────────────── const PolicyIcon = ({ type }) => { const paths = { home: "M2 7.5L8 2l6 5.5V14a1 1 0 0 1-1 1H3a1 1 0 0 1-1-1V7.5zM6 15v-5h4v5", auto: "M2 9l1.5-4h9L14 9v3H2V9zM4.5 12a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3zm7 0a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3", umbrella: "M8 2a6 6 0 0 0-6 6h12a6 6 0 0 0-6-6zM8 8v5a2 2 0 0 0 4 0", life: "M8 14s-6-3.5-6-7.5a3.5 3.5 0 0 1 6-2.45A3.5 3.5 0 0 1 14 6.5C14 10.5 8 14 8 14z", }; return ( ); }; const PolicyLines = ({ lines }) => (
{lines.slice(0,3).map((l,i) => )} {lines.length > 3 && +{lines.length-3}}
); // ── SOURCE CELL ─────────────────────────────────────────────────────────────── const SOURCE_CFG = { Website: { color: C.quoted, path: "M10 3a7 7 0 1 0 0 14A7 7 0 0 0 10 3zm0 0c-2 2-3 4.5-3 7s1 5 3 7m0-14c2 2 3 4.5 3 7s-1 5-3 7M3 10h14" }, Referral: { color: C.newClient, path: "M7 9a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm-5.5 8a5.5 5.5 0 0 1 11 0" }, "Call-In":{ color: C.imported, path: "M4 9a6 6 0 0 1 12 0v3.5L17.5 15h-15L4 12.5V9zM8.5 15.5a1.5 1.5 0 0 0 3 0" }, }; const SourceCell = ({ source }) => { const { color, path } = SOURCE_CFG[source]; return (
{source}
); }; // ── NOTIFICATION HELPERS ────────────────────────────────────────────────────── const NL = ({ children }) => ( {children} ); const renderTitle = (n) => { switch (n.id) { case 1: return <>Applied Epic Policy Renewal Workflow: Outlook disconnected; case 2: return <>Applied Epic Policy Renewal Workflow for Michael Chen: Missing email address; case 3: return <>Applied Epic Policy Renewal Workflow for Michael Chen: Policy not found in Applied Epic; case 5: return <>Form link expired for David Kim; case 6: return <>Sarah Johnson completed a form submission; case 7: return <>David Kim uploaded a document; case 9: return <>You were assigned a new client: Emily Ross; case 10: return <>Workflow "Auto Follow-Up" completed for Michael Chen; case 11: return <>Emily Ross responded to their quote; case 12: return <>Applied Epic Policy Renewal Workflow: Google Gmail disconnected; case 14: return <>AMS360 connection lost; case 15: return <>Michael Chen completed a PDF supplement; case 16: return <>Form share link was opened by David Kim; case 17: return <>Your Advanced Export is ready; case 18: return <>A new lead came in from Referral Partner: State Farm; case 19: return <>Michael Chen status changed to Quoted; default: return null; } }; const NIcon = ({ type }) => { if (type === "error") return ( ); if (type === "success") return ( ); return ( ); }; // ── TOGGLE ──────────────────────────────────────────────────────────────────── const Toggle = ({ checked, onChange }) => (
); // ── NAV ICONS ───────────────────────────────────────────────────────────────── const NavIcons = { search: ( ), clients: ( ), folder: ( ), file: ( ), form: ( ), check: ( ), chart: ( ), connect: ( ), settings: ( ), help: ( ), }; const NAV_ITEMS = [ { id: "clients", icon: NavIcons.clients, active: true }, { id: "folder", icon: NavIcons.folder }, { id: "file", icon: NavIcons.file }, { id: "form", icon: NavIcons.form }, { id: "check", icon: NavIcons.check }, { id: "chart", icon: NavIcons.chart }, { id: "connect", icon: NavIcons.connect }, { id: "settings", icon: NavIcons.settings, settings: true }, ]; // ── OUTLINE BUTTON STYLE ────────────────────────────────────────────────────── const outlineBtn = { display: "inline-flex", alignItems: "center", gap: 2, padding: "4px", background: C.white, borderRadius: 8, border: `1px solid ${C.borderT1}`, boxShadow: "0 2px 3px rgba(0,0,0,0.03)", color: C.textBase, fontSize: 15, fontWeight: 500, cursor: "pointer", ...FONT, }; // ── MAIN APP ────────────────────────────────────────────────────────────────── export default function App() { const [items, setItems] = useState(initNotifications); const [filter, setFilter] = useState("all"); const [notifTab, setNotifTab] = useState("notifications"); const [popoverOpen, setPopover] = useState(false); const [activePage, setActivePage] = useState("clients"); const [activeStatusTab, setActiveStatusTab] = useState(0); const [selectedRows, setSelectedRows] = useState(new Set([8])); const popoverRef = useRef(null); const bellRef = useRef(null); // Init settings const initPrefs = {}; settingsGroups.forEach(g => { initPrefs[g.id] = true; g.items.forEach(i => { initPrefs[i.id] = true; }); }); const [prefs, setPrefs] = useState(initPrefs); const togglePref = (id, groupId) => { setPrefs(p => { const next = { ...p, [id]: !p[id] }; if (groupId) { const g = settingsGroups.find(g => g.id === groupId); next[groupId] = g.items.every(item => item.id === id ? !p[id] : p[item.id]); } else { const g = settingsGroups.find(g => g.id === id); if (g) g.items.forEach(item => { next[item.id] = !p[id]; }); } return next; }); }; useEffect(() => { const handler = (e) => { if (popoverOpen && popoverRef.current && !popoverRef.current.contains(e.target) && bellRef.current && !bellRef.current.contains(e.target)) { setItems(prev => prev.map(n => ({ ...n, read: true }))); setPopover(false); } }; document.addEventListener("mousedown", handler); return () => document.removeEventListener("mousedown", handler); }, [popoverOpen]); const unreadCount = items.filter(n => !n.read).length; const markAllRead = () => { setItems(items.map(n => ({ ...n, read: true }))); setFilter("all"); }; const sorted = [...items].sort((a, b) => a.read !== b.read ? (a.read ? 1 : -1) : a.order - b.order); const filtered = filter === "unread" ? sorted.filter(n => !n.read) : sorted; const openPopover = () => { if (popoverOpen) setItems(prev => prev.map(n => ({ ...n, read: true }))); setPopover(p => !p); }; const toggleRow = (id) => setSelectedRows(prev => { const n = new Set(prev); n.has(id) ? n.delete(id) : n.add(id); return n; }); // ── SIDEBAR ────────────────────────────────────────────────────────────── const Sidebar = () => ( ); // ── CLIENTS PAGE ────────────────────────────────────────────────────────── const ClientsPage = () => (
{/* Actions bar */}
{[ { label: "Export PDF", icon: "M5 3h7l4 4v10a1 1 0 0 1-1 1H5a1 1 0 0 1-1-1V4a1 1 0 0 1 1-1zm7 0v4h4" }, { label: "Import", icon: "M10 13V4M7 7l3-3 3 3m-9 8v2a1 1 0 0 0 1 1h10a1 1 0 0 0 1-1v-2" }, ].map((b, i) => (
{i > 0 &&
}
))}
{/* Status tabs */}
{STATUS_TABS.map((tab, i) => ( ))}
{/* Search & filter */}
{/* Table */}
{[ { label: "Client", icon: "M8 9a3 3 0 1 0 0-6 3 3 0 0 0 0 6zM2 17a6 6 0 0 1 12 0" }, { label: "Status", icon: "M10 3a7 7 0 1 0 0 14A7 7 0 0 0 10 3zM10 7v3.5l2 1.5" }, { label: "Pipeline", icon: "M2 5h4v4H2zm6 0h4v4H8zm6 0h4v4h-4zM2 11h4v4H2zm6 0h4v4H8zm6 0h4v4h-4z" }, { label: "Policy Lines", icon: "M8 6a6 6 0 1 1 0 12A6 6 0 0 1 8 6z" }, { label: "Form", icon: "M5 2h7l4 4v10H5V2zm7 0v4h4m-9 4h6m-6 3h6m-6 3h4" }, { label: "Source", icon: "M8 6a6 6 0 1 1 0 12A6 6 0 0 1 8 6z" }, { label: "Assigned Agent", icon: "M8 9a3 3 0 1 0 0-6 3 3 0 0 0 0 6zM2 17a6 6 0 0 1 12 0" }, ].map(h => ( ))} {CLIENTS.map(c => { const sel = selectedRows.has(c.id); return ( { if (!sel) e.currentTarget.style.background = C.bg05; }} onMouseLeave={e => { if (!sel) e.currentTarget.style.background = C.white; }} > ); })}
{h.label}
toggleRow(c.id)} style={{ accentColor: C.primary, cursor: "pointer" }} />
{c.name}
{c.status} {c.days}d
{c.pipeline}
{c.form}
{c.ftype}
{c.agent}
); // ── SETTINGS PAGE ───────────────────────────────────────────────────────── const SettingsPage = () => (
{/* Settings sidebar */}
{[ { section: "Organization", items: ["Users", "Groups"] }, { section: "CRM & Data", items: ["CRM (Tracking)", "Clients", "Referral Source"] }, { section: "Content", items: ["Forms", "Custom Field", "Proposal Templates"] }, { section: "Automation", items: ["Workflow", "Applications"] }, { section: "Brand & Company", items: ["Company", "Branding", "Proposal Templates"] }, ].map(g => (
{g.section}
{g.items.map(item => (
e.currentTarget.style.background = C.bg1} onMouseLeave={e => e.currentTarget.style.background = "transparent"} >{item}
))}
))}
{["API", "Sys Admins", "Notifications"].map(item => (
{ if (item !== "Notifications") e.currentTarget.style.background = C.bg1; }} onMouseLeave={e => { if (item !== "Notifications") e.currentTarget.style.background = "transparent"; }} >{item}
))}
{/* Settings content */}
Notification Preferences
Choose which notifications you receive in-app.
{settingsGroups.map(g => (
{g.label}
{g.desc}
togglePref(g.id)} />
{prefs[g.id] && g.items.map((item, ii) => (
{item.label} togglePref(item.id, g.id)} />
))}
))}
); // ── POPOVER ─────────────────────────────────────────────────────────────── const Popover = () => (
{/* Tabs */}
{[["notifications","Notifications"],["whats_new","What's New"]].map(([id, label]) => ( ))}
{notifTab === "notifications" && <> {/* Controls */}
{[["all","All"],["unread","Unread"]].map(([f, label]) => ( ))}
{/* List */}
{filtered.length === 0 ? (
You're all caught up
No new notifications
) : filtered.map((n, i) => (
e.currentTarget.style.background = C.bg1} onMouseLeave={e => e.currentTarget.style.background = n.read ? C.white : C.primarySurface + "55"} >
{renderTitle(n)}
{n.time} {!n.read &&
}
{n.action && ( )}
))}
} {notifTab === "whats_new" && (
{whatsNew.map((item, i) => (
e.currentTarget.style.background = C.bg1} onMouseLeave={e => e.currentTarget.style.background = C.white} >
{item.title}
{item.desc}
))}
)} {/* Footer */}
); // ── RENDER ──────────────────────────────────────────────────────────────── return (
{activePage === "clients" ? : } {popoverOpen && }
); }