# Development Guide Complete guide for developing the Yaltopia Ticket Admin application. ## Tech Stack - **Frontend**: React 18 + TypeScript + Vite - **UI**: TailwindCSS + shadcn/ui - **State**: React Query (TanStack Query) - **Routing**: React Router v6 - **HTTP Client**: Axios - **Forms**: React Hook Form + Zod - **Charts**: Recharts - **Notifications**: Sonner - **Error Tracking**: Sentry - **Testing**: Vitest + Testing Library ## Quick Start ```bash # Install dependencies npm install # Set up environment cp .env.example .env # Edit .env with your backend URL # Start development server npm run dev # Run tests npm run test # Build for production npm run build ``` ## Project Structure ``` src/ ├── components/ # Reusable UI components ├── pages/ # Page components ├── services/ # API service layer │ ├── api/ │ │ └── client.ts # Axios instance │ ├── auth.service.ts │ ├── user.service.ts │ └── ... ├── layouts/ # Layout components ├── lib/ # Utilities └── test/ # Test utilities ``` ## API Architecture ### Service Layer Pattern All API calls go through typed service classes: ``` Component → Service → API Client → Backend ``` ### Available Services ```typescript import { authService, // Authentication userService, // User management analyticsService, // Analytics securityService, // Security systemService, // System health announcementService,// Announcements auditService, // Audit logs settingsService // Settings } from '@/services' ``` ### Usage Examples **Fetching Data:** ```typescript import { useQuery } from '@tanstack/react-query' import { userService } from '@/services' const { data, isLoading } = useQuery({ queryKey: ['users'], queryFn: () => userService.getUsers({ page: 1, limit: 20 }) }) ``` **Mutations:** ```typescript import { useMutation, useQueryClient } from '@tanstack/react-query' import { userService } from '@/services' const queryClient = useQueryClient() const mutation = useMutation({ mutationFn: (id: string) => userService.deleteUser(id), onSuccess: () => { queryClient.invalidateQueries({ queryKey: ['users'] }) toast.success('User deleted') } }) ``` **Direct Calls:** ```typescript import { authService } from '@/services' const response = await authService.login({ email, password }) ``` ## Authentication ### Setup 1. Backend must return tokens on login 2. Frontend stores in httpOnly cookies (recommended) or localStorage 3. All requests automatically include auth token 4. 401 errors trigger automatic token refresh ### Login Flow ```typescript // User logs in const response = await authService.login({ email, password }) // Token stored automatically // User redirected to dashboard // All subsequent requests include token await userService.getUsers() // Token added automatically ``` ### Protected Routes ```typescript }> } /> ``` ### Logout ```typescript await authService.logout() // Clears tokens & cookies navigate('/login') ``` ## API Standards ### Service Methods All service methods: - Return typed data (no `response.data` unwrapping needed) - Throw errors with `error.response.data.message` - Use consistent naming (get, create, update, delete) ### Error Handling ```typescript try { await userService.deleteUser(id) toast.success('User deleted') } catch (error: any) { toast.error(error.response?.data?.message || 'Operation failed') } ``` ### Type Safety ```typescript // All responses are typed const users: PaginatedResponse = await userService.getUsers() const stats: OverviewStats = await analyticsService.getOverview() ``` ## Environment Variables ```bash # Required VITE_BACKEND_API_URL=http://localhost:3001/api/v1 # Optional (Sentry) VITE_SENTRY_DSN=your-sentry-dsn VITE_SENTRY_ENVIRONMENT=development ``` ## Common Tasks ### Adding a New Service Method ```typescript // src/services/user.service.ts async exportUserData(userId: string): Promise { const response = await apiClient.get(`/admin/users/${userId}/export`, { responseType: 'blob' }) return response.data } ``` ### Adding a New Page 1. Create page component in `src/pages/` 2. Add route in `src/App.tsx` 3. Import required services 4. Use React Query for data fetching ### Adding a New Component 1. Create in `src/components/` 2. Use TypeScript for props 3. Follow existing patterns 4. Add to component exports if reusable ## Best Practices ### React Query ```typescript // Good - specific query keys queryKey: ['users', page, limit, search] // Bad - too generic queryKey: ['data'] ``` ### Service Layer ```typescript // Good - use services import { userService } from '@/services' await userService.getUsers() // Bad - direct axios import axios from 'axios' await axios.get('/api/users') ``` ### Error Handling ```typescript // Good - handle errors try { await userService.deleteUser(id) } catch (error: any) { toast.error(error.response?.data?.message) } // Bad - no error handling await userService.deleteUser(id) ``` ### Type Safety ```typescript // Good - use types const users: PaginatedResponse = await userService.getUsers() // Bad - any type const users: any = await userService.getUsers() ``` ## Troubleshooting ### CORS Errors - Ensure backend has CORS configured - Check `withCredentials: true` in API client - Verify `VITE_BACKEND_API_URL` is correct ### 401 Errors - Check token is being sent - Verify backend token validation - Check token expiration ### Build Errors - Run `npm run build` to check TypeScript errors - Fix any type errors - Ensure all imports are correct ### Test Failures - Run `npm run test` to see failures - Check mock implementations - Verify test data matches types ## Additional Resources - [Testing Guide](./TESTING.md) - [Deployment Guide](./DEPLOYMENT.md) - [Security Guide](./SECURITY.md) - [Troubleshooting](./TROUBLESHOOTING.md)