// Hero platform mock — styled to match the real ActiveManage admin UI const { useState: useStateMock, useEffect: useEffectMock } = React; // Fixed platform palette (the app is light + blue, regardless of site theme — // this reads as a genuine screenshot of the product). const PB = { page: "#F6F8FA", side: "#EAEDF1", sideBorder: "#DDE2E8", blue: "#1C82C4", blueDark:"#176FA8", blueTile:"#E7F1FB", red: "#E5484D", card: "#FFFFFF", cardBorder: "#E5E9ED", title: "#2B4257", label: "#46535F", faint: "#8A95A1", line: "#EDF0F3", }; const NAV_VIEWS = [ { id: "home", label: "Admin Home" }, { id: "datastores", label: "Datastores" }, { id: "forms", label: "Forms" }, { id: "dashboards", label: "Dashboards" }, { id: "permissions",label: "Permissions" }, { id: "communication", label: "Communication" }, { id: "booking", label: "Booking" }, { id: "ecommerce", label: "eCommerce" }, { id: "api", label: "API Server" }, ]; function PlatformMock() { const [view, setView] = useStateMock(0); const [tick, setTick] = useStateMock(0); const [paused, setPaused] = useStateMock(false); useEffectMock(() => { if (paused) return; // Home view dwells longer so the full feature list can scroll past const dwell = NAV_VIEWS[view].id === "home" ? 16000 : 7000; const t = setTimeout(() => setView(v => (v + 1) % NAV_VIEWS.length), dwell); return () => clearTimeout(t); }, [paused, view]); useEffectMock(() => { setTick(0); const t = setInterval(() => setTick(v => v + 1), 600); return () => clearInterval(t); }, [view]); const v = NAV_VIEWS[view].id; return (
setPaused(true)} onMouseLeave={() => setPaused(false)}>
app.activemanage.co.uk
setView(i)} />
{/* faint warm top accent like the real app */}
{v === "home" && } {v === "datastores" && } {v === "forms" && } {v === "dashboards" && } {v === "permissions"&& } {v === "communication" && } {v === "booking" && } {v === "ecommerce" && } {v === "api" && }
); } function PlatformSidebar({ view, onPick }) { const pill = (label, active, i) => ( ); const navItem = (label, viewId, idx) => { const active = view === viewId; return ( ); }; return (
ActiveManage
{pill("Admin Home", view === "home", 0)} {pill("Architect Panel", view !== "home" && view !== "status", null)} {pill("Status Panel", false, null)}
ARCHITECT
{NAV_VIEWS.filter(nv => nv.id !== "home").map(nv => navItem(nv.label, nv.id, NAV_VIEWS.findIndex(x => x.id === nv.id)))}
SUPPORT
{["New Requests", "All Users", "Invoices"].map(l => (
{l}
))}
AM Support
); } // Tiny blue line-icon set used in cards function Ico({ name }) { const p = { shield: , form: <>, data: <>, layout: <>, activity: , plug: <>, cart: <>, chat: , cog: <>, cal: <>, api: <>, bolt: , search: <>, globe: <>, }[name] || ; return ( {p} ); } function ArchitectHome({ tick }) { // The full Architect Panel — every category, split across 3 columns, // continuously scrolling so nothing has to be shrunk. const columns = [ [ ["Security", "shield", ["Permissions", "Authentication Methods", "Security Settings", "Blocked User Accounts", "Blocked IP Addresses"]], ["Subscriptions", "bolt", ["Feature Sets", "Features", "Subscription Packages"]], ["Searching", "search", ["Site Searching"]], ["Internationalisation", "globe", ["Languages"]], ], [ ["Forms", "form", ["Conditional Forms", "Dynamic Add Fields", "Custom Fields", "Custom Forms", "Line Item Builders", "User Input Views"]], ["Dashboards", "layout", ["Custom Dashboard Blocks", "Dashboard Styles", "Shared Dashboard Layout"]], ["Commercial", "cart", ["Carts"]], ["Communication", "chat", ["Manage Meetings", "Manage Chat Engines"]], ], [ ["Integration & Connections", "plug", ["Database Hosts", "E-mail Accounts", "API Server", "Table Sync", "Deployments", "API Clients", "Azure AD Tenants"]], ["Data", "data", ["Datastores", "File Stores", "Data Extraction", "File Import Routines"]], ["Layout & Pages", "layout", ["Pages", "Browse Views", "Document Templates", "Admin Panel Builder", "Header"]], ["Configuration", "cog", ["Site Settings", "Multitenancy", "Friendly URLs", "SEO"]], ["Activity", "activity", ["Activity Log", "E-mail Log", "Error Log", "SMS Log"]], ["Automation", "cal", ["Tasks", "Task Log", "Polling"]], ["Styling", "cog", ["Logo"]], ["Help & Support", "chat", ["Manage Articles"]], ], ]; const Grid = () => (
{columns.map((col, ci) => (
{col.map(([title, icon, items]) => (
{title}
{items.map(it => (
{it}
))}
))}
))}
); return (
Architect Panel
60+ tools
); } function ScreenHeader({ title, sub, action }) { return (
{title}
{sub &&
{sub}
}
{action && {action}}
); } function DatastoresScreen({ tick }) { const fields = [ ["ref", "Random Alphanumeric", "PK"], ["patient_name", "Text Box", "req"], ["nhs_number", "Text Box · indexed", "idx"], ["dob", "Date", ""], ["address", "Postal Address", ""], ["consultant", "User Search", ""], ["consent", "Signature", ""], ["risk", "Slider · 1–10", ""], ["status", "Pills", ""], ]; const rows = [ ["P-00481", "S. Patel", "Active"], ["P-00480", "M. Hughes", "Active"], ["P-00479", "R. Khan", "Triage"], ["P-00478", "T. Brown", "Active"], ["P-00477", "A. Singh", "Critical"], ["P-00476", "L. Wright", "Closed"], ]; const statusColour = (s) => s === "Critical" ? PB.red : s === "Triage" ? "#C77700" : s === "Closed" ? PB.faint : "#1F9254"; return (
{fields.map(([n, t, tag], i) => (
{n} {tag && {tag}}{t}
))}
refnamestatus
{rows.map((r, i) => (
{r[0]} {r[1]} {r[2]}
))}
AUTO: form · API · search · audit
); } function FormsScreen({ tick }) { const chips = ["Text Box", "Dropdown", "Date", "Slider", "Tickboxes", "Postal Address", "Signature", "AJAX Search", "File Upload", "Dynamic Add", "Conditional", "Line Items"]; return (
Field types
{chips.map((c, i) => ( {c} ))} +38
{[["Full name", "Sarah Patel"], ["NHS number", "885 391 044"], ["Date of birth", "14 / 04 / 1986"]].map(([l, v]) => ( ))}
Risk score
6.2
Allergies
{["Penicillin", "Nuts", "Latex"].map((a, i) => ( {[0,2].includes(i) ? "✓ " : ""}{a} ))}
VALIDATED 14/14 Submit
); } function PLabel({ children }) { return
{children}
; } function PField({ label, value }) { return (
{label}
{value}
); } function DashboardScreen({ tick }) { const bars = [42, 58, 71, 65, 80, 92, 88, 95, 78, 90]; return (
{[["Active", "12,847", "+12%"], ["Triaged", "284", "+8"], ["Avg wait", "9m", "-2m"], ["P0", "0", "—"]].map(([l, v, d]) => (
{l}
{v}
{d}
))}
Throughput · 10 weeks
{bars.map((h, i) => (
))}
Triage mix
); } function PermissionsScreen({ tick }) { const groups = ["Super Admin", "Clinician", "Reception", "Auditor", "Patient"]; const cols = ["Patients", "Appts", "Rx", "Audit", "Billing"]; const matrix = [ [3, 3, 3, 3, 3], [2, 2, 2, 1, 0], [2, 2, 0, 0, 1], [1, 1, 1, 1, 1], [1, 1, 0, 0, 1], ]; const lbl = ["—", "R", "RW", "ALL"]; const bg = (l) => l === 3 ? PB.blue : l === 2 ? "#9Fc6E6" : l === 2 ? "#9FC6E6" : l === 1 ? "#DCEAF6" : "#F0F2F5"; const fg = (l) => l === 3 ? "#fff" : "#46535F"; return (
Group
{cols.map(c =>
{c}
)}
{groups.map((g, i) => (
{g}
{matrix[i].map((l, j) => (
{lbl[l]}
))}
))}
Field-level: nhs_number · masked for Reception billing · hidden
); } function CommunicationScreen({ tick }) { const msgs = [ ["✉", "Appointment confirmation", "Delivered", "SendGrid", "#1F9254"], ["✉", "Renewal reminder · 14 days", "Opened", "SMTP", "#1C82C4"], ["☎", "2FA passcode", "Delivered", "SMS · Twilio", "#1F9254"], ["✉", "Invoice INV-2847", "Clicked", "MS Graph", "#1C82C4"], ["☎", "Booking reminder", "Queued", "SMS", "#C77700"], ["✉", "Password reset", "Delivered", "SES", "#1F9254"], ]; return (
{msgs.map((m, i) => (
{m[0]}
{m[1]}
{m[3]}
{m[2]}
))}
{[["Sent today", "1,284"], ["Open rate", "62%"], ["SMS delivered", "418"]].map(([k, v]) => (
{k}
{v}
))}
INBOX ACTION · parse → datastore
); } function BookingScreen({ tick }) { const days = ["Mon", "Tue", "Wed", "Thu", "Fri"]; const slots = ["09:00", "10:00", "11:00", "13:00", "14:00", "15:00"]; // booking state per [slot][day]: 0 free, 1 booked, 2 held const state = [ [1, 0, 1, 0, 2], [0, 1, 0, 1, 0], [1, 1, 0, 0, 1], [0, 0, 2, 1, 0], [1, 0, 1, 0, 1], [0, 1, 0, 1, 0], ]; return (
{days.map(d =>
{d}
)}
{slots.map((s, si) => (
{s}
{days.map((d, di) => { const st = state[si][di]; return (
{st === 1 ? "BKD" : st === 2 ? "HELD" : "·"}
); })}
))}
Booked Held Free Auto-confirm · e-mail + SMS
); } function EcommerceScreen({ tick }) { const orders = [ ["#4821", "A. Chen", "£128.00", "Paid", "#1F9254"], ["#4820", "R. Okafor", "£54.00", "Fulfilled", "#1C82C4"], ["#4819", "M. Díaz", "£312.00", "Paid", "#1F9254"], ["#4818", "K. Yamada", "£19.99", "Refunded", "#8A95A1"], ["#4817", "S. Ahmed", "£86.50", "Pending", "#C77700"], ]; return (
OrderCustomerTotalStatus
{orders.map((o, i) => (
{o[0]} {o[1]} {o[2]} {o[3]}
))}
{[["Revenue · today", "£4,182"], ["Orders", "38"], ["Avg. basket", "£110"]].map(([k, v]) => (
{k}
{v}
))}
● Stripe connected
); } function ApiScreen({ tick }) { const eps = [ ["GET", "/api/patients", "list, filter"], ["GET", "/api/patients/:id", "single record"], ["POST", "/api/patients", "create + validate"], ["PATCH", "/api/patients/:id", "partial update"], ["DELETE", "/api/patients/:id", "soft delete"], ["GET", "/api/patients/export.csv", "CSV export"], ]; const mc = { GET: "#1F9254", POST: PB.blue, PATCH: "#C77700", DELETE: PB.red }; return (
{eps.map(([m, p, h], i) => (
{m} {p}
))}
GET /api/patients/P-00481
← 200 OK · 142ms
{"{"}
{[["ref", "P-00481"], ["patient_name", "Sarah Patel"], ["nhs_number", "885 391 044"], ["risk", "6.2"], ["status", "Active"]].map(([k, v], i) => (
"{k}": "{v}"{i < 4 ? "," : ""}
))}
{"}"}
); } /* ============================================================================= INTEGRATED ITSM — the support desk that lives inside every app we ship. Styled with the fixed platform palette (PB) so it reads as a real screenshot of the product, matching PlatformMock. ============================================================================= */ function ItsmSection({ onNavigate }) { const shots = [ { src: "images/itsm/tickettypes.png", step: "01", cap: "Pick the type of request", url: "support · new request" }, { src: "images/itsm/lognewticket.png", step: "02", cap: "Log the details in-app", url: "support · new request" }, { src: "images/itsm/mytickets.png", step: "03", cap: "Track every request & SLA", url: "support · my requests" }, ]; const points = [ ["In-app request logging", "No separate portal, no tier-1 queue, no offshore call centre — it's a panel inside the software you already use."], ["Incidents, changes & features", "Raise a bug fix, change request, feature idea or how-to question — each routed and tracked against its own SLA."], ["Approvals & full history", "Electronic authorisation, live status and a complete audit trail on every request and reply."], ["Straight to the engineers", "The people who built your software are the people who answer — nothing gets lost in translation."], ]; return (
Support, built in

Every app ships with its own
integrated service desk.

Our own ITSM is woven directly into the software we build for you. Log a bug, request a change or suggest a feature without ever leaving the app — it lands straight with the engineers who built it.

{/* Real screenshots of the built-in support desk, framed like the product */}
{shots.map((s) => (
{s.url}
{s.cap}
{s.step}{s.cap}
))}
    {points.map(([t, d]) => (
  • {t} {d}
  • ))}
); } Object.assign(window, { PlatformMock, ItsmSection }); const _mockScrollStyle = document.createElement("style"); _mockScrollStyle.innerHTML = ` .mock-vscroll { animation: mockVScroll 26s linear infinite; will-change: transform; } @keyframes mockVScroll { 0% { transform: translateY(0); } 100% { transform: translateY(-50%); } } .mock:hover .mock-vscroll { animation-play-state: paused; } @media (prefers-reduced-motion: reduce) { .mock-vscroll { animation: none; } } `; document.head.appendChild(_mockScrollStyle);