This repository has been archived on 2026-05-24. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
app/apps/web/src/App.tsx
T
Groom Book CTO 81a348a2f4 feat(web): add customer portal with 7 sections and staff impersonation
Implements the customer-facing portal for pet parents with:
- Dashboard showing upcoming appointments, pet cards, loyalty rewards
- Multi-step appointment booking flow with recurring scheduling
- Pet profiles with medical/behavioral notes and vaccination tracking
- Grooming report cards with before/after, behavior assessment, sharing
- Billing & payments with invoices, saved methods, autopay, tips, packages
- Communication with chat-style messaging and notification preferences
- Account settings with personal info, password, pet management, agreements
- Staff impersonation mode with required reason, 30-min session timer,
  non-dismissable banner, viewport border, watermark, read-only enforcement,
  and full audit trail viewer

Also adds Tailwind CSS, lucide-react, and recharts as dependencies.

Closes #53

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-03-18 23:28:16 +00:00

91 lines
3.0 KiB
TypeScript

import { Routes, Route, Link, useLocation } from "react-router-dom";
import { AppointmentsPage } from "./pages/Appointments.js";
import { ClientsPage } from "./pages/Clients.js";
import { ServicesPage } from "./pages/Services.js";
import { StaffPage } from "./pages/Staff.js";
import { InvoicesPage } from "./pages/Invoices.js";
import { BookPage } from "./pages/Book.js";
import { ReportsPage } from "./pages/Reports.js";
import { GroupBookingPage } from "./pages/GroupBooking.js";
import { CustomerPortal } from "./portal/CustomerPortal.js";
const NAV_LINKS = [
{ to: "/", label: "Appointments" },
{ to: "/clients", label: "Clients" },
{ to: "/services", label: "Services" },
{ to: "/staff", label: "Staff" },
{ to: "/invoices", label: "Invoices" },
{ to: "/group-bookings", label: "Group Bookings" },
{ to: "/reports", label: "Reports" },
{ to: "/portal", label: "Customer Portal" },
];
export function App() {
const location = useLocation();
return (
<div style={{ minHeight: "100vh", fontFamily: "system-ui, sans-serif" }}>
<nav
style={{
padding: "0.75rem 1rem",
borderBottom: "1px solid #e2e8f0",
display: "flex",
alignItems: "center",
gap: "0.25rem",
background: "#fff",
}}
>
<strong style={{ marginRight: "1rem", fontSize: 16 }}>Groom Book</strong>
<Link
to="/book"
style={{
padding: "0.35rem 0.75rem",
borderRadius: 4,
textDecoration: "none",
fontSize: 14,
fontWeight: 600,
color: "#fff",
background: "#4f8a6f",
marginRight: "0.5rem",
}}
>
Book
</Link>
{NAV_LINKS.map(({ to, label }) => {
const active =
to === "/" ? location.pathname === "/" : location.pathname.startsWith(to);
return (
<Link
key={to}
to={to}
style={{
padding: "0.35rem 0.75rem",
borderRadius: 4,
textDecoration: "none",
fontSize: 14,
fontWeight: active ? 600 : 400,
color: active ? "#1d4ed8" : "#374151",
background: active ? "#eff6ff" : "transparent",
}}
>
{label}
</Link>
);
})}
</nav>
<main style={{ padding: "1rem 1.5rem" }}>
<Routes>
<Route path="/" element={<AppointmentsPage />} />
<Route path="/clients" element={<ClientsPage />} />
<Route path="/services" element={<ServicesPage />} />
<Route path="/staff" element={<StaffPage />} />
<Route path="/invoices" element={<InvoicesPage />} />
<Route path="/book" element={<BookPage />} />
<Route path="/group-bookings" element={<GroupBookingPage />} />
<Route path="/reports" element={<ReportsPage />} />
<Route path="/portal" element={<CustomerPortal />} />
</Routes>
</main>
</div>
);
}