# Architecture Documentation Comprehensive guide to the Black Canyon Tickets React rebuild architecture, design patterns, and technical decisions. ## Project Structure Overview ``` src/ ├── components/ │ ├── ui/ # Design system primitives │ ├── layout/ # Application layout system │ ├── auth/ # Authentication components │ ├── loading/ # Loading states and skeletons │ ├── errors/ # Error boundaries and fallbacks │ ├── events/ # Event domain components │ ├── tickets/ # Ticketing domain components │ ├── checkout/ # Purchase flow components │ ├── billing/ # Payment and fee components │ └── scanning/ # QR scanning components ├── pages/ # Route-level components ├── contexts/ # React Context providers ├── hooks/ # Custom React hooks ├── types/ # TypeScript type definitions ├── design-tokens/ # Design system configuration ├── styles/ # CSS files and utilities └── utils/ # Utility functions ``` ## Architectural Principles ### 1. Component Composition **Philosophy**: Build complex UIs by composing smaller, focused components rather than creating monolithic components. ```tsx // Bad: Monolithic component function EventPage({ eventId }) { return (
...
...
...
...
); } // Good: Composed from smaller components function EventPage({ eventId }) { return ( ); } ``` ### 2. Design Token System **Philosophy**: Centralize design decisions in a token system that enables consistent theming and maintainable styles. ``` design-tokens/ ├── base.json # Core design tokens └── themes/ ├── light.json # Light theme overrides └── dark.json # Dark theme overrides ``` **Token Categories**: - **Colors**: Semantic color system (primary, surface, text, border) - **Typography**: Font sizes, line heights, font families - **Spacing**: Consistent spacing scale (1-20) - **Border Radius**: Corner radius values (sm, md, lg, xl, 2xl) - **Shadows**: Elevation system with multiple levels ### 3. Type-Driven Development **Philosophy**: Use TypeScript's type system to catch errors early and provide excellent developer experience. ```typescript // Comprehensive type definitions interface Event { id: string; title: string; description: string; date: string; venue: string; organization: Organization; ticketTypes: TicketType[]; status: EventStatus; } // Union types for controlled values type EventStatus = 'draft' | 'published' | 'active' | 'completed' | 'cancelled'; type UserRole = 'user' | 'admin' | 'super_admin'; // Strict component props interface EventCardProps { event: Event; showActions?: boolean; onEdit?: (event: Event) => void; onDelete?: (eventId: string) => void; } ``` ## Design Patterns ### 1. Compound Components **Use Case**: Complex components with multiple related parts that work together. ```tsx // Card component with sub-components function Card({ children, variant = 'default', ...props }) { return (
{children}
); } Card.Header = function CardHeader({ children, className = '', ...props }) { return (
{children}
); }; Card.Content = function CardContent({ children, className = '', ...props }) { return (
{children}
); }; // Usage

Event Details

``` ### 2. Render Props Pattern **Use Case**: Sharing stateful logic between components while maintaining flexibility in rendering. ```tsx // ProtectedRoute component using render props function ProtectedRoute({ permission, fallback, children }: ProtectedRouteProps) { const { user, hasPermission } = useAuth(); if (!user) { return ; } if (permission && !hasPermission(permission)) { return fallback || ; } return <>{children}; } // Usage } > ``` ### 3. Custom Hook Pattern **Use Case**: Extracting and reusing stateful logic across components. ```tsx // useAuth hook encapsulates authentication logic function useAuth() { const [user, setUser] = useState(null); const [loading, setLoading] = useState(true); const login = useCallback(async (credentials: LoginCredentials) => { setLoading(true); try { const user = await authService.login(credentials); setUser(user); return { success: true, user }; } catch (error) { return { success: false, error: error.message }; } finally { setLoading(false); } }, []); const logout = useCallback(() => { setUser(null); authService.logout(); }, []); const hasPermission = useCallback((permission: Permission) => { return user?.permissions.includes(permission) ?? false; }, [user]); return { user, loading, login, logout, hasPermission, isAuthenticated: !!user, }; } ``` ## State Management Strategy ### 1. Component State (useState) **Use For**: Local component state that doesn't need to be shared. ```tsx function TicketSelector({ ticketType }) { const [quantity, setQuantity] = useState(0); const [loading, setLoading] = useState(false); return (
); } ``` ### 2. Context State (React Context) **Use For**: Application-wide state that needs to be shared across many components. ```tsx // Theme context for global theme management const ThemeContext = createContext(undefined); function ThemeProvider({ children }: { children: React.ReactNode }) { const [theme, setTheme] = useState('dark'); const toggleTheme = useCallback(() => { setTheme(prev => prev === 'light' ? 'dark' : 'light'); }, []); return ( {children} ); } // Auth context for user authentication state const AuthContext = createContext(undefined); function AuthProvider({ children }: { children: React.ReactNode }) { const auth = useAuth(); // Custom hook with auth logic return ( {children} ); } ``` ### 3. URL State (React Router) **Use For**: State that should be reflected in the URL for bookmarking and sharing. ```tsx // Search and filter state in URL parameters function EventsPage() { const [searchParams, setSearchParams] = useSearchParams(); const search = searchParams.get('search') || ''; const category = searchParams.get('category') || 'all'; const updateSearch = (newSearch: string) => { setSearchParams(prev => { prev.set('search', newSearch); return prev; }); }; return (
); } ``` ## Error Handling Architecture ### 1. Error Boundaries **Strategy**: Catch React component errors and provide graceful fallbacks. ```tsx // App-level error boundary class AppErrorBoundary extends Component { constructor(props: ErrorBoundaryProps) { super(props); this.state = { hasError: false, error: null }; } static getDerivedStateFromError(error: Error): ErrorBoundaryState { return { hasError: true, error }; } componentDidCatch(error: Error, errorInfo: ErrorInfo) { console.error('Error caught by boundary:', error, errorInfo); // Report to error tracking service } render() { if (this.state.hasError) { return this.props.fallback || ; } return this.props.children; } } // Usage }> ``` ### 2. Loading States **Strategy**: Provide consistent loading experiences across the application. ```tsx // Suspense for route-level loading function App() { return ( }> } /> ); } // Component-level loading with Skeleton function EventCard({ eventId }: { eventId: string }) { const { event, loading, error } = useEvent(eventId); if (loading) return ; if (error) return ; if (!event) return ; return ; } ``` ## Authentication Architecture ### 1. Mock Authentication System **Design**: Simulates real authentication without external dependencies. ```typescript // Mock auth service class MockAuthService { private static users: User[] = [ { id: '1', email: 'demo@blackcanyontickets.com', role: 'user', permissions: ['events:read', 'tickets:purchase'] }, { id: '2', email: 'admin@blackcanyontickets.com', role: 'admin', permissions: ['events:read', 'events:write', 'users:read'] } ]; async login(credentials: LoginCredentials): Promise { const user = this.users.find(u => u.email === credentials.email); if (!user) throw new Error('Invalid credentials'); // Simulate API delay await new Promise(resolve => setTimeout(resolve, 1000)); // Store in localStorage for persistence localStorage.setItem('auth_user', JSON.stringify(user)); return user; } logout(): void { localStorage.removeItem('auth_user'); } getCurrentUser(): User | null { const stored = localStorage.getItem('auth_user'); return stored ? JSON.parse(stored) : null; } } ``` ### 2. Permission System **Design**: Role-based access control with granular permissions. ```typescript // Permission definitions type Permission = | 'events:read' | 'events:write' | 'events:delete' | 'tickets:read' | 'tickets:purchase' | 'tickets:scan' | 'users:read' | 'users:write' | 'analytics:read' | 'settings:write'; // Role definitions const ROLE_PERMISSIONS: Record = { user: [ 'events:read', 'tickets:read', 'tickets:purchase' ], admin: [ 'events:read', 'events:write', 'tickets:read', 'tickets:scan', 'users:read', 'analytics:read' ], super_admin: [ 'events:read', 'events:write', 'events:delete', 'tickets:read', 'tickets:scan', 'users:read', 'users:write', 'analytics:read', 'settings:write' ] }; ``` ## Component Testing Strategy ### 1. Unit Testing **Focus**: Individual component behavior and props handling. ```typescript // Button component tests import { render, screen, fireEvent } from '@testing-library/react'; import { Button } from '@/components/ui/Button'; describe('Button Component', () => { test('renders with correct variant styles', () => { render(); const button = screen.getByRole('button'); expect(button).toHaveClass('bg-primary'); }); test('handles click events', () => { const handleClick = jest.fn(); render(); fireEvent.click(screen.getByRole('button')); expect(handleClick).toHaveBeenCalledTimes(1); }); test('displays loading state', () => { render(); expect(screen.getByRole('button')).toBeDisabled(); expect(screen.getByText('Loading')).toBeInTheDocument(); }); }); ``` ### 2. Integration Testing with Playwright **Focus**: End-to-end user workflows and cross-component interactions. ```typescript // Authentication flow test import { test, expect } from '@playwright/test'; test('user can log in and access dashboard', async ({ page }) => { await page.goto('/login'); // Fill login form await page.fill('[data-testid="email-input"]', 'demo@blackcanyontickets.com'); await page.fill('[data-testid="password-input"]', 'demo123'); // Submit and verify redirect await page.click('[data-testid="login-button"]'); await expect(page).toHaveURL('/dashboard'); // Verify user is authenticated await expect(page.getByText('Welcome back')).toBeVisible(); }); ``` ### 3. Visual Regression Testing **Focus**: Ensure UI changes don't break visual design. ```typescript // Visual tests with Playwright test('homepage renders correctly', async ({ page }) => { await page.goto('/'); await expect(page).toHaveScreenshot('homepage.png'); }); test('login form in both themes', async ({ page }) => { // Test light theme await page.goto('/login'); await page.getByTestId('theme-toggle').click(); // Switch to light await expect(page.getByTestId('login-form')).toHaveScreenshot('login-light.png'); // Test dark theme await page.getByTestId('theme-toggle').click(); // Switch to dark await expect(page.getByTestId('login-form')).toHaveScreenshot('login-dark.png'); }); ``` ## Performance Architecture ### 1. Code Splitting **Strategy**: Split code at route boundaries and for large dependencies. ```tsx // Route-based code splitting const HomePage = lazy(() => import('@/pages/HomePage')); const DashboardPage = lazy(() => import('@/pages/DashboardPage')); const EventsPage = lazy(() => import('@/pages/EventsPage')); function App() { return ( }> } /> }> } /> ); } ``` ### 2. Component Optimization **Strategy**: Use React.memo and useMemo to prevent unnecessary re-renders. ```tsx // Memoized component to prevent re-renders const EventCard = memo(function EventCard({ event, onEdit }: EventCardProps) { const formattedDate = useMemo(() => { return formatDate(event.date); }, [event.date]); return (

{event.title}

{formattedDate}

); }); // Optimized list rendering function EventList({ events }: { events: Event[] }) { const sortedEvents = useMemo(() => { return [...events].sort((a, b) => new Date(a.date).getTime() - new Date(b.date).getTime() ); }, [events]); return (
{sortedEvents.map(event => ( ))}
); } ``` ## Accessibility Architecture ### 1. Semantic HTML Foundation **Strategy**: Use semantic HTML elements that provide built-in accessibility. ```tsx // Good: Semantic structure function EventForm() { return (
Event Details