# Frontend Integration - Step by Step ## Current Status ✅ **API Infrastructure Complete** - API client with axios interceptors - Authentication hooks - All feature hooks (customers, services, resources, appointments, business) - Playwright testing setup - Login page component - Example App.tsx with real auth ✅ **Components Extracted** - All components from zip copied to `src/*-extracted/` directories - TypeScript types copied to `src/types.ts` ## Quick Start (5 Minutes) ### 1. Install Dependencies ```bash cd frontend npm install npx playwright install ``` ### 2. Start Backend ```bash # In another terminal cd backend docker-compose up docker-compose exec backend python manage.py migrate docker-compose exec backend python manage.py createsuperuser ``` ### 3. Start Frontend ```bash npm run dev ``` ### 4. Test Login - Go to `http://lvh.me:5173` - Login with your superuser credentials - You should see a welcome screen with your user info! ## Integration Steps ### Step 1: Replace App.tsx ```bash # Backup current App.tsx mv src/App.tsx src/App.tsx.backup # Use the integrated version mv src/App-integrated.tsx src/App.tsx ``` ### Step 2: Copy Components ```bash # Copy all components at once cp -r src/components-extracted/* src/components/ 2>/dev/null || true cp -r src/layouts-extracted/* src/layouts/ 2>/dev/null || true cp -r src/pages-extracted/* src/pages/ 2>/dev/null || true # Or copy selectively, one feature at a time (recommended) ``` ### Step 3: Update Component Imports For each component you copy, replace mock data with API hooks. #### Example: Dashboard.tsx **Before:** ```typescript import { APPOINTMENTS, SERVICES } from '../mockData'; const Dashboard = () => { const [appointments] = useState(APPOINTMENTS); const [services] = useState(SERVICES); // ... } ``` **After:** ```typescript import { useAppointments } from '../hooks/useAppointments'; import { useServices } from '../hooks/useServices'; const Dashboard = () => { const { data: appointments, isLoading: apptLoading } = useAppointments(); const { data: services, isLoading: servicesLoading } = useServices(); if (apptLoading || servicesLoading) { return
Loading...
; } // ... } ``` #### Example: Customers.tsx **Before:** ```typescript import { CUSTOMERS } from '../mockData'; const Customers = () => { const [customers] = useState(CUSTOMERS); const [searchTerm, setSearchTerm] = useState(''); // ... } ``` **After:** ```typescript import { useCustomers } from '../hooks/useCustomers'; const Customers = () => { const [searchTerm, setSearchTerm] = useState(''); const { data: customers, isLoading } = useCustomers({ search: searchTerm }); if (isLoading) { return
Loading...
; } // ... } ``` #### Example: Scheduler.tsx **Before:** ```typescript import { APPOINTMENTS, RESOURCES, SERVICES } from '../mockData'; const Scheduler = () => { const [appointments] = useState(APPOINTMENTS); const [resources] = useState(RESOURCES); const [services] = useState(SERVICES); // ... } ``` **After:** ```typescript import { useAppointments } from '../hooks/useAppointments'; import { useResources } from '../hooks/useResources'; import { useServices } from '../hooks/useServices'; const Scheduler = () => { const { data: appointments, isLoading: apptLoading } = useAppointments(); const { data: resources, isLoading: resLoading } = useResources(); const { data: services, isLoading: servicesLoading } = useServices(); if (apptLoading || resLoading || servicesLoading) { return
Loading...
; } // ... } ``` ### Step 4: Handle Create/Update/Delete Operations For mutations, use the mutation hooks: ```typescript import { useCreateCustomer, useUpdateCustomer, useDeleteCustomer } from '../hooks/useCustomers'; const Customers = () => { const { data: customers } = useCustomers(); const createMutation = useCreateCustomer(); const updateMutation = useUpdateCustomer(); const deleteMutation = useDeleteCustomer(); const handleCreateCustomer = (data: any) => { createMutation.mutate(data, { onSuccess: () => { console.log('Customer created!'); // Maybe close a modal or reset a form }, onError: (error) => { console.error('Failed to create customer:', error); } }); }; const handleUpdateCustomer = (id: string, updates: any) => { updateMutation.mutate({ id, updates }, { onSuccess: () => { console.log('Customer updated!'); } }); }; const handleDeleteCustomer = (id: string) => { deleteMutation.mutate(id, { onSuccess: () => { console.log('Customer deleted!'); } }); }; return ( // Your JSX with handlers ); }; ``` ### Step 5: Update App.tsx with Full Routing Once components are copied and updated, implement role-based routing in App.tsx: ```typescript // Import all your pages import Dashboard from './pages/Dashboard'; import Scheduler from './pages/Scheduler'; import Customers from './pages/Customers'; // ... etc const AppContent = () => { const { data: user } = useCurrentUser(); const { data: business } = useCurrentBusiness(); if (!user) return ; // Platform users if (['superuser', 'platform_manager', 'platform_support'].includes(user.role)) { return ( }> } /> } /> {/* ... more platform routes */} ); } // Customer users if (user.role === 'customer') { return ( }> } /> } /> {/* ... more customer routes */} ); } // Business users (owner, manager, staff, resource) return ( }> } /> } /> } /> } /> {/* ... more business routes */} ); }; ``` ## Testing with Playwright ### Run Visual Tests ```bash # Run tests and compare with extracted frontend npm run test:headed # Or use UI mode for debugging npm run test:ui ``` ### Create New Tests Create test files in `tests/e2e/`: ```typescript // tests/e2e/customers.spec.ts import { test, expect } from '@playwright/test'; test.describe('Customers Page', () => { test.beforeEach(async ({ page }) => { // Login await page.goto('/'); await page.getByLabel(/username/i).fill('testowner'); await page.getByLabel(/password/i).fill('testpass123'); await page.getByRole('button', { name: /sign in/i }).click(); await page.waitForURL(/\//); }); test('should display customers list', async ({ page }) => { await page.goto('/customers'); // Wait for customers to load await page.waitForSelector('table tbody tr, [data-testid="customer-list"]'); // Take screenshot for comparison await expect(page).toHaveScreenshot('customers-list.png'); }); test('should filter customers by status', async ({ page }) => { await page.goto('/customers'); // Click status filter await page.getByRole('button', { name: /filter/i }).click(); await page.getByRole('option', { name: /active/i }).click(); // Verify filtered results const rows = await page.locator('table tbody tr').count(); expect(rows).toBeGreaterThan(0); }); }); ``` ## Troubleshooting ### Issue: Types don't match **Symptom**: TypeScript errors about id being string vs number **Solution**: The hooks already handle transformation. Make sure you're using the hooks, not calling apiClient directly. ### Issue: Components look different from extracted version **Symptom**: Visual differences in Playwright screenshots **Solution**: 1. Check Tailwind classes are identical 2. Verify dark mode is applied correctly 3. Compare CSS files from extracted version 4. Use Playwright UI mode to inspect elements ### Issue: CORS errors in console **Symptom**: "Access-Control-Allow-Origin" errors **Solution**: 1. Verify backend is running 2. Check CORS settings in `backend/config/settings/base.py` 3. Ensure `X-Business-Subdomain` header is in CORS_ALLOW_HEADERS ### Issue: 404 on API calls **Symptom**: API calls return 404 **Solution**: 1. Check you're using correct subdomain: `acme.lvh.me:5173` 2. Verify backend middleware is processing `X-Business-Subdomain` header 3. Check business exists in database with correct subdomain ### Issue: Data not loading **Symptom**: Components show loading forever **Solution**: 1. Check browser console for errors 2. Verify backend migrations are applied 3. Create test data in backend 4. Check React Query DevTools (install `@tanstack/react-query-devtools`) ## Adding React Query DevTools For debugging: ```bash npm install @tanstack/react-query-devtools ``` In App.tsx: ```typescript import { ReactQueryDevtools } from '@tanstack/react-query-devtools'; ``` ## Component Integration Checklist - [ ] Login page works - [ ] Dashboard displays - [ ] Sidebar navigation works - [ ] Dark mode toggle works - [ ] Customers page loads data from API - [ ] Can create new customer - [ ] Can edit customer - [ ] Can delete customer - [ ] Services page loads data - [ ] Resources page loads data - [ ] Scheduler displays appointments - [ ] Can create appointment - [ ] Can drag-and-drop appointments - [ ] Settings page loads business data - [ ] Can update business settings - [ ] Visual tests pass - [ ] No console errors ## Next Steps After Basic Integration 1. **Error Boundaries**: Add error boundaries for better error handling 2. **Loading States**: Improve loading UI with skeletons 3. **Optimistic Updates**: Add optimistic updates for better UX 4. **Form Validation**: Add form validation with react-hook-form or similar 5. **Toast Notifications**: Add toast library for success/error messages 6. **Accessibility**: Add ARIA labels and keyboard navigation 7. **Performance**: Optimize re-renders with React.memo 8. **Tests**: Add more comprehensive Playwright tests ## Resources - **Main Guide**: `../FRONTEND_INTEGRATION_GUIDE.md` - **Backend API**: `../BACKEND_IMPLEMENTATION_SUMMARY.md` - **All Hooks**: Check `src/hooks/` directory - **Type Definitions**: `src/types.ts` - **Example Components**: `src/*-extracted/` directories You're ready to integrate! Start with the Dashboard, then move to individual features one by one.