import { useState, useReducer, useCallback } from "react"; import { Home, Calendar, PawPrint, FileText, CreditCard, MessageSquare, Settings, Eye, LogOut, Clock, Shield, } from "lucide-react"; import { Dashboard } from "./sections/Dashboard.js"; import { AppointmentsSection } from "./sections/Appointments.js"; import { PetProfiles } from "./sections/PetProfiles.js"; import { ReportCards } from "./sections/ReportCards.js"; import { BillingPayments } from "./sections/BillingPayments.js"; import { Communication } from "./sections/Communication.js"; import { AccountSettings } from "./sections/AccountSettings.js"; import { ImpersonationBanner } from "./ImpersonationBanner.js"; import { AuditLogViewer } from "./AuditLogViewer.js"; import type { ImpersonationSession, AuditEntry } from "./mockData.js"; import { CUSTOMER } from "./mockData.js"; type Section = "dashboard" | "appointments" | "pets" | "reports" | "billing" | "messages" | "settings"; const NAV_ITEMS: { id: Section; label: string; icon: typeof Home }[] = [ { id: "dashboard", label: "Home", icon: Home }, { id: "appointments", label: "Appointments", icon: Calendar }, { id: "pets", label: "My Pets", icon: PawPrint }, { id: "reports", label: "Report Cards", icon: FileText }, { id: "billing", label: "Billing", icon: CreditCard }, { id: "messages", label: "Messages", icon: MessageSquare }, { id: "settings", label: "Settings", icon: Settings }, ]; type ImpersonationAction = | { type: "START"; staffName: string; staffRole: string; reason: string } | { type: "END" } | { type: "EXTEND" } | { type: "LOG"; entry: AuditEntry }; function impersonationReducer( state: ImpersonationSession | null, action: ImpersonationAction ): ImpersonationSession | null { switch (action.type) { case "START": { const now = new Date(); const expires = new Date(now.getTime() + 30 * 60 * 1000); return { active: true, staffName: action.staffName, staffRole: action.staffRole, customerName: CUSTOMER.name, reason: action.reason, startedAt: now.toISOString(), expiresAt: expires.toISOString(), extended: false, readOnly: true, auditLog: [{ id: "audit-0", timestamp: now.toISOString(), action: "session_start", detail: `Impersonation started by ${action.staffName} (${action.staffRole}). Reason: ${action.reason}`, }], }; } case "END": if (!state) return null; return { ...state, active: false, auditLog: [...state.auditLog, { id: `audit-${state.auditLog.length}`, timestamp: new Date().toISOString(), action: "session_end", detail: "Impersonation session ended", }], }; case "EXTEND": if (!state) return null; return { ...state, expiresAt: new Date(new Date(state.expiresAt).getTime() + 30 * 60 * 1000).toISOString(), extended: true, auditLog: [...state.auditLog, { id: `audit-${state.auditLog.length}`, timestamp: new Date().toISOString(), action: "session_extended", detail: "Session extended by 30 minutes", }], }; case "LOG": if (!state) return null; return { ...state, auditLog: [...state.auditLog, action.entry] }; default: return state; } } export function CustomerPortal() { const [activeSection, setActiveSection] = useState
("dashboard"); const [mobileNavOpen, setMobileNavOpen] = useState(false); const [showAuditLog, setShowAuditLog] = useState(false); const [showImpersonationSetup, setShowImpersonationSetup] = useState(false); const [impersonation, dispatchImpersonation] = useReducer(impersonationReducer, null); const logPageView = useCallback((page: string) => { if (impersonation?.active) { dispatchImpersonation({ type: "LOG", entry: { id: `audit-${Date.now()}`, timestamp: new Date().toISOString(), action: "page_view", detail: `Viewed: ${page}`, }, }); } }, [impersonation?.active]); const handleNavClick = (section: Section) => { setActiveSection(section); setMobileNavOpen(false); logPageView(section); }; const isReadOnly = impersonation?.active && impersonation.readOnly; const renderSection = () => { switch (activeSection) { case "dashboard": return ; case "appointments": return ; case "pets": return ; case "reports": return ; case "billing": return ; case "messages": return ; case "settings": return ; } }; return (
{impersonation?.active && ( <> dispatchImpersonation({ type: "END" })} onExtend={() => dispatchImpersonation({ type: "EXTEND" })} onShowAudit={() => setShowAuditLog(true)} /> {/* Watermark */}
STAFF VIEW
)} {showAuditLog && impersonation && ( setShowAuditLog(false)} /> )} {/* Mobile Header */}
Paws & Reflect
SM
{/* Sidebar Navigation */} {/* Mobile nav overlay */} {mobileNavOpen && (
setMobileNavOpen(false)} /> )} {/* Main Content */}

{NAV_ITEMS.find(n => n.id === activeSection)?.label}

Hi, {CUSTOMER.name.split(" ")[0]}
SM
{renderSection()}
{/* Impersonation Setup Modal */} {showImpersonationSetup && { dispatchImpersonation({ type: "START", staffName: "Chris", staffRole: "Admin", reason }); setShowImpersonationSetup(false); }} onCancel={() => setShowImpersonationSetup(false)} />}
); } function ImpersonationSetupModal({ onStart, onCancel }: { onStart: (reason: string) => void; onCancel: () => void }) { const [reason, setReason] = useState(""); return (

Start Staff Impersonation

View portal as {CUSTOMER.name}