From 540b8b407b3919b2156f5b4d1727559a61222d38 Mon Sep 17 00:00:00 2001 From: belviskhoremk Date: Wed, 12 Aug 2026 12:52:25 +0200 Subject: [PATCH] feat: wire up /admin/* routing Adds AdminApp as a lazy-loaded route subtree in App.tsx, mounting ProtectedRoute, AdminLogin, AdminLayout, and all five CRUD pages built in Tasks 3-11. Mounted as a sibling of the public Layout route (not nested under it), since the admin panel has its own AdminLayout sidebar rather than the public nav/footer. Manually verified end-to-end against the local Supabase stack: sign-in redirect guard, all five pages rendering real seeded data, creating and cancelling a real booking through the UI (confirming the booked_slots cleanup trigger from the merged Phase 2A follow-up fixes correctly frees the slot), and sign-out. No console errors across the flow. Claude-Session: https://claude.ai/code/session_01NhxA4npAXAxmCDEJt6kxSH --- .gitignore | 3 +++ src/App.tsx | 9 +++++++ src/pages/admin/AdminApp.test.tsx | 42 +++++++++++++++++++++++++++++++ src/pages/admin/AdminApp.tsx | 28 +++++++++++++++++++++ 4 files changed, 82 insertions(+) create mode 100644 src/pages/admin/AdminApp.test.tsx create mode 100644 src/pages/admin/AdminApp.tsx diff --git a/.gitignore b/.gitignore index d0bdbe6..38c141f 100644 --- a/.gitignore +++ b/.gitignore @@ -32,3 +32,6 @@ dist-ssr # Supabase CLI local artifacts supabase/.branches supabase/.temp + +# Playwright MCP scratch output (screenshots, console logs, page snapshots) +.playwright-mcp/ diff --git a/src/App.tsx b/src/App.tsx index 5990029..695e96e 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -6,6 +6,7 @@ import Book from './pages/Book' import Rules from './pages/Rules' const Home = lazy(() => import('./pages/Home')) +const AdminApp = lazy(() => import('./pages/admin/AdminApp')) interface AppProps { initialEntries?: string[] @@ -27,6 +28,14 @@ function AppRoutes() { } /> } /> + + + + } + /> ) } diff --git a/src/pages/admin/AdminApp.test.tsx b/src/pages/admin/AdminApp.test.tsx new file mode 100644 index 0000000..2642705 --- /dev/null +++ b/src/pages/admin/AdminApp.test.tsx @@ -0,0 +1,42 @@ +import { render, screen } from '@testing-library/react' +import { MemoryRouter, Routes, Route } from 'react-router-dom' +import { describe, it, expect, vi } from 'vitest' + +vi.mock('../../hooks/useAdminAuth', () => ({ + default: () => ({ session: { user: { id: 'admin' } }, loading: false }), +})) +vi.mock('../../lib/supabase', () => ({ + supabase: { + auth: { signOut: vi.fn() }, + from: () => ({ + select: () => ({ order: () => Promise.resolve({ data: [], error: null }) }), + }), + }, +})) + +import AdminApp from './AdminApp' + +describe('AdminApp routing', () => { + it('renders the login page at /admin/login', () => { + render( + + + } /> + + , + ) + expect(screen.getByRole('heading', { name: /admin login/i })).toBeInTheDocument() + }) + + it('renders the products page (with layout) at /admin/products when authenticated', async () => { + render( + + + } /> + + , + ) + expect(await screen.findByRole('heading', { name: /^products$/i })).toBeInTheDocument() + expect(screen.getByRole('link', { name: /bookings/i })).toBeInTheDocument() + }) +}) diff --git a/src/pages/admin/AdminApp.tsx b/src/pages/admin/AdminApp.tsx new file mode 100644 index 0000000..2aadf97 --- /dev/null +++ b/src/pages/admin/AdminApp.tsx @@ -0,0 +1,28 @@ +import { Routes, Route } from 'react-router-dom' +import ProtectedRoute from '../../components/ProtectedRoute' +import AdminLogin from './AdminLogin' +import AdminLayout from './AdminLayout' +import AdminProducts from './AdminProducts' +import AdminServices from './AdminServices' +import AdminSchedule from './AdminSchedule' +import AdminBookings from './AdminBookings' +import AdminInquiries from './AdminInquiries' + +function AdminApp() { + return ( + + } /> + }> + }> + } /> + } /> + } /> + } /> + } /> + + + + ) +} + +export default AdminApp