From baa5a4aaa07eee0bb714805949c46186a1e2cb95 Mon Sep 17 00:00:00 2001 From: loppify Date: Sun, 20 Sep 2026 17:42:56 +0200 Subject: [PATCH] polish design --- frontend/src/app/error.tsx | 5 +++-- frontend/src/app/not-found.tsx | 5 +++-- frontend/src/features/dashboard/pages.tsx | 11 ++++++----- frontend/src/features/overview/mock-data.ts | 2 +- frontend/src/lib/mock-data.ts | 9 ++++++++- 5 files changed, 21 insertions(+), 11 deletions(-) diff --git a/frontend/src/app/error.tsx b/frontend/src/app/error.tsx index 57a1c5e..b2cdea6 100644 --- a/frontend/src/app/error.tsx +++ b/frontend/src/app/error.tsx @@ -1,8 +1,9 @@ "use client"; -import { Fault, Mark } from "@/features/desk/primitives"; import Link from "next/link"; +import { AppShell } from "@/components/app-shell"; +import { DashboardPage, PageHeader } from "@/components/dashboard-ui"; export default function Error({ reset }: { reset: () => void }) { - return
ackvia.Open the desk
; + return Open Overview} />; } diff --git a/frontend/src/app/not-found.tsx b/frontend/src/app/not-found.tsx index 72e9ceb..a23866b 100644 --- a/frontend/src/app/not-found.tsx +++ b/frontend/src/app/not-found.tsx @@ -1,6 +1,7 @@ -import { Mark } from "@/features/desk/primitives"; import Link from "next/link"; +import { AppShell } from "@/components/app-shell"; +import { DashboardPage, PageHeader } from "@/components/dashboard-ui"; export default function NotFound() { - return
ackvia.

This route doesn’t exist.

Return to the investigation desk to choose a form and submission.

Open the desk
; + return Return to Overview} />; } diff --git a/frontend/src/features/dashboard/pages.tsx b/frontend/src/features/dashboard/pages.tsx index 337599b..88fd387 100644 --- a/frontend/src/features/dashboard/pages.tsx +++ b/frontend/src/features/dashboard/pages.tsx @@ -2,7 +2,7 @@ import Link from "next/link"; import { ArrowLeft, CheckCircle2, RefreshCw, Webhook } from "lucide-react"; import { AppShell } from "@/components/app-shell"; import { CodeBlock, DashboardPage, DataTable, DetailFields, EmptyState, HealthBadge, Panel, PanelTitle, PageHeader, StatStrip, StatusBadge, Timeline } from "@/components/dashboard-ui"; -import { attempts, clients, deliveries, getClientForSite, getDeliveryForAttempt, getMockAttempt, getMockClient, getMockDelivery, getMockIncident, getMockLead, getMockLeadPath, getMockSite, incidents, leadPaths, leads, sites } from "@/lib/mock-data"; +import { attempts, clients, deliveries, getClientForSite, getMockAttempt, getMockClient, getMockDelivery, getMockIncident, getMockLead, getMockLeadPath, getMockSite, incidents, leadPaths, leads, sites } from "@/lib/mock-data"; const deliveryTone = { Pending: "neutral", Processing: "warn", "Awaiting retry": "warn", Delivered: "good", Failed: "bad", Unknown: "neutral" } as const; const attemptTone = { Succeeded: "good", "Retryable failure": "warn", "Permanent failure": "bad", "Unknown result": "neutral" } as const; @@ -21,7 +21,7 @@ export function ClientDetailPage({ clientId }: { clientId: string }) { if (!client) return ; const clientSites = sites.filter((site) => site.clientId === client.id); const clientLeads = leads.filter((lead) => lead.clientId === client.id); - return } />
{clientSites.map((site) => {site.name}{site.domain})}
{client.incidents ?
CRM Webhook delivery failuresStarted 08:43:03 · 31 affected leads
: }
{clientLeads.map((lead) => {lead.id}{lead.customerName}{lead.capturedAt}{getMockSite(lead.siteId)?.domain}{getMockLeadPath(lead.leadPathId)?.name}{lead.deliveryIds.length} destinations)}
; + return } />
{clientSites.map((site) => {site.name}{site.domain})}
{client.incidents ?
CRM Webhook delivery failuresStarted 08:43:03 · 31 affected leads
: }
{clientLeads.map((lead) => {lead.id}{lead.customerName}{lead.capturedAt}{getMockSite(lead.siteId)?.domain}{getMockLeadPath(lead.leadPathId)?.name}{lead.deliveryIds.length} destinations)}
; } export function SitesPage() { @@ -53,7 +53,7 @@ export function LeadDetailPage({ leadId }: { leadId: string }) { if (!lead) return ; const site = getMockSite(lead.siteId); const deliveriesForLead = deliveries.filter((delivery) => lead.deliveryIds.includes(delivery.id)); - return } />
{site.domain} : "Unknown" }, { label: "Lead path", value: getMockLeadPath(lead.leadPathId)?.name ?? "Unknown" }, { label: "Capture state", value: }, { label: "Message", value: lead.message }]} />{JSON.stringify({ name: lead.customerName, email: lead.email, phone: lead.phone, message: lead.message }, null, 2)}
{deliveriesForLead.map((delivery) => {delivery.destination}{delivery.attemptIds.length} attempt{delivery.attemptIds.length === 1 ? "" : "s"})} ({ label: `${delivery.destination} · ${delivery.state}`, time: delivery.deliveredAt ?? delivery.createdAt, tone: delivery.state === "Delivered" ? "good" : "warn" }))} />
; + return } />
{site.domain} : "Unknown" }, { label: "Lead path", value: getMockLeadPath(lead.leadPathId)?.name ?? "Unknown" }, { label: "Capture state", value: }, { label: "Message", value: lead.message }]} />{JSON.stringify({ name: lead.customerName, email: lead.email, phone: lead.phone, message: lead.message }, null, 2)}
{deliveriesForLead.map((delivery) => {delivery.destination}{delivery.attemptIds.length} attempt{delivery.attemptIds.length === 1 ? "" : "s"})}
; } export function IncidentsPage() { @@ -81,12 +81,13 @@ export function DeliveryDetailPage({ deliveryId }: { deliveryId: string }) { export function AttemptDetailPage({ deliveryId, attemptId }: { deliveryId: string; attemptId: string }) { const attempt = getMockAttempt(attemptId); - const delivery = attempt ? getDeliveryForAttempt(attempt.id) : getMockDelivery(deliveryId); + const delivery = attempt?.deliveryId === deliveryId ? getMockDelivery(deliveryId) : undefined; if (!attempt || !delivery) return ; const lead = getMockLead(delivery.leadId); const previous = getMockAttempt(delivery.attemptIds[attempt.number - 2] ?? ""); const next = getMockAttempt(delivery.attemptIds[attempt.number] ?? ""); - return } />
{previous ? Attempt #{previous.number} : } {next && Attempt #{next.number}}
}, { label: "Next retry", value: attempt.nextRetry ?? "—", mono: true }]} />
{delivery.destination} }, { label: "Lead", value: {delivery.leadId} }, { label: "Endpoint", value: "https://crm.kellersolar.com/api/leads", mono: true }, { label: "Method", value: "POST", mono: true }, { label: "Timeout", value: "10 s", mono: true }]} />
DNS Connect TLS Request Response
{JSON.stringify({ name: lead?.customerName, email: lead?.email, message: lead?.message }, null, 2)}{JSON.stringify({ status: attempt.providerStatus, message: attempt.providerMessage }, null, 2)}
; + const classification = attempt.result === "Succeeded" ? "Success" : attempt.result === "Retryable failure" ? "Retryable" : attempt.result === "Permanent failure" ? "Permanent" : "Unknown"; + return } />
{previous ? Attempt #{previous.number} : } {next && Attempt #{next.number}}
}, { label: "Next retry", value: attempt.nextRetry ?? "—", mono: true }]} />
{delivery.destination} }, { label: "Lead", value: {delivery.leadId} }, { label: "Endpoint", value: "https://crm.kellersolar.com/api/leads", mono: true }, { label: "Method", value: "POST", mono: true }, { label: "Timeout", value: "10 s", mono: true }]} />
DNS Connect TLS Request Response
{JSON.stringify({ name: lead?.customerName, email: lead?.email, message: lead?.message }, null, 2)}{JSON.stringify({ status: attempt.providerStatus, message: attempt.providerMessage }, null, 2)}
; } function ChevronRightIcon() { return ; } diff --git a/frontend/src/features/overview/mock-data.ts b/frontend/src/features/overview/mock-data.ts index ce3acf6..25d3c66 100644 --- a/frontend/src/features/overview/mock-data.ts +++ b/frontend/src/features/overview/mock-data.ts @@ -6,4 +6,4 @@ export type SiteHealth = { id: string; name: string; domain: string; leads: stri export { deliveryBreakdown }; export const activityEvents = activities; -export const siteHealth: SiteHealth[] = sites.map((site) => ({ id: site.id, name: site.name, domain: site.domain, leads: site.leads.toLocaleString(), deliveryRate: site.deliveryRate, status: site.health })); +export const siteHealth: SiteHealth[] = sites.slice(0, 5).map((site) => ({ id: site.id, name: site.name, domain: site.domain, leads: site.leads.toLocaleString(), deliveryRate: site.deliveryRate, status: site.health })); diff --git a/frontend/src/lib/mock-data.ts b/frontend/src/lib/mock-data.ts index 69240af..154dd33 100644 --- a/frontend/src/lib/mock-data.ts +++ b/frontend/src/lib/mock-data.ts @@ -26,6 +26,7 @@ export const clients: Client[] = [ export const sites: Site[] = [ { id: "keller-solar-site", clientId: "keller-solar", name: "Keller Solar", domain: "kellersolar.com", leadPathIds: ["keller-contact", "keller-quote"], leads: 48, deliveryRate: "96.2%", health: "Attention", lastActivity: "08:50" }, { id: "northwind-main", clientId: "northwind-dental", name: "Northwind Dental", domain: "northwinddental.com", leadPathIds: ["northwind-contact", "northwind-booking"], leads: 142, deliveryRate: "100%", health: "Healthy", lastActivity: "08:31" }, + { id: "northwind-ortho", clientId: "northwind-dental", name: "Northwind Ortho", domain: "northwindortho.com", leadPathIds: ["northwind-ortho-contact"], leads: 0, deliveryRate: "—", health: "Healthy", lastActivity: "No recent activity" }, { id: "smith-realty-site", clientId: "smith-realty", name: "Smith Realty", domain: "smithrealty.com", leadPathIds: ["smith-contact", "smith-viewing"], leads: 87, deliveryRate: "99.8%", health: "Healthy", lastActivity: "Yesterday" }, { id: "pizza-roma-site", clientId: "pizza-roma", name: "Pizza Roma", domain: "pizzaroma.com", leadPathIds: ["pizza-contact"], leads: 24, deliveryRate: "100%", health: "Healthy", lastActivity: "Yesterday" }, { id: "old-mill-site", clientId: "old-mill-studio", name: "Old Mill Studio", domain: "oldmillstudio.com", leadPathIds: ["old-mill-contact"], leads: 31, deliveryRate: "99.7%", health: "Healthy", lastActivity: "2 days ago" }, @@ -36,13 +37,19 @@ export const leadPaths: LeadPath[] = [ { id: "keller-quote", siteId: "keller-solar-site", name: "Quote Request", status: "Healthy", recentLeads: 17, destinations: ["Telegram", "CRM Webhook"], deliveryHealth: "100%", lastEvent: "Yesterday" }, { id: "northwind-contact", siteId: "northwind-main", name: "Contact Us", status: "Healthy", recentLeads: 84, destinations: ["CRM Webhook", "Email"], deliveryHealth: "100%", lastEvent: "08:31" }, { id: "northwind-booking", siteId: "northwind-main", name: "Book an Appointment", status: "Healthy", recentLeads: 58, destinations: ["CRM Webhook"], deliveryHealth: "100%", lastEvent: "Yesterday" }, + { id: "northwind-ortho-contact", siteId: "northwind-ortho", name: "Contact Us", status: "Healthy", recentLeads: 0, destinations: ["CRM Webhook"], deliveryHealth: "—", lastEvent: "No recent activity" }, { id: "smith-contact", siteId: "smith-realty-site", name: "Contact Us", status: "Healthy", recentLeads: 52, destinations: ["CRM Webhook"], deliveryHealth: "100%", lastEvent: "Yesterday" }, { id: "smith-viewing", siteId: "smith-realty-site", name: "Book a Viewing", status: "Healthy", recentLeads: 35, destinations: ["CRM Webhook"], deliveryHealth: "99.7%", lastEvent: "Yesterday" }, { id: "pizza-contact", siteId: "pizza-roma-site", name: "Contact Us", status: "Healthy", recentLeads: 24, destinations: ["Email"], deliveryHealth: "100%", lastEvent: "Yesterday" }, { id: "old-mill-contact", siteId: "old-mill-site", name: "Project Enquiry", status: "Healthy", recentLeads: 31, destinations: ["CRM Webhook"], deliveryHealth: "99.7%", lastEvent: "2 days ago" }, ]; -export const leads: Lead[] = [{ id: "LD-2026-001245", clientId: "keller-solar", siteId: "keller-solar-site", leadPathId: "keller-contact", customerName: "Sarah Mitchell", email: "sarah@example.com", phone: "+49 151 23456789", message: "Hi, I'm interested in getting a quote for a solar panel installation for our house. Please contact me regarding the options and pricing. Thank you!", capturedAt: "Sep 20, 2026 — 08:42:31", state: "Captured safely", deliveryIds: ["delivery-telegram-001245", "delivery-keller-crm"] }]; +export const leads: Lead[] = [ + { id: "LD-2026-001245", clientId: "keller-solar", siteId: "keller-solar-site", leadPathId: "keller-contact", customerName: "Sarah Mitchell", email: "sarah@example.com", phone: "+49 151 23456789", message: "Hi, I'm interested in getting a quote for a solar panel installation for our house. Please contact me regarding the options and pricing. Thank you!", capturedAt: "Sep 20, 2026 — 08:42:31", state: "Captured safely", deliveryIds: ["delivery-telegram-001245", "delivery-keller-crm"] }, + { id: "lead-northwind-0831", clientId: "northwind-dental", siteId: "northwind-main", leadPathId: "northwind-contact", customerName: "Emily Carter", email: "emily@example.com", phone: "+1 555 0142", message: "I would like to book a consultation.", capturedAt: "Sep 20, 2026 — 08:31:02", state: "Captured safely", deliveryIds: ["delivery-northwind-001"] }, + { id: "lead-smith-001", clientId: "smith-realty", siteId: "smith-realty-site", leadPathId: "smith-contact", customerName: "Daniel Brooks", email: "daniel@example.com", phone: "+1 555 0187", message: "Could I arrange a viewing this week?", capturedAt: "Sep 19, 2026 — 14:22:00", state: "Captured safely", deliveryIds: ["delivery-smith-001"] }, + { id: "lead-pizza-001", clientId: "pizza-roma", siteId: "pizza-roma-site", leadPathId: "pizza-contact", customerName: "Marco Rossi", email: "marco@example.com", phone: "+1 555 0124", message: "I have a question about catering.", capturedAt: "Sep 19, 2026 — 11:04:00", state: "Captured safely", deliveryIds: ["delivery-pizza-001"] }, +]; export const deliveries: Delivery[] = [ { id: "delivery-telegram-001245", leadId: "LD-2026-001245", destination: "Telegram", state: "Delivered", attemptIds: ["attempt-telegram-1"], createdAt: "08:42:31", deliveredAt: "08:42:32" },