# Frontend Development Guide This guide explains how to develop and extend frontend components in Crypto Trader. ## Tech Stack - **React 18** - UI framework - **TypeScript** - Type safety - **Material-UI (MUI)** - Component library - **React Query** - Data fetching and caching - **React Router** - Routing - **Vite** - Build tool ## Project Structure ``` frontend/ ├── src/ │ ├── pages/ # Page components │ ├── components/ # Reusable components │ ├── api/ # API client functions │ ├── hooks/ # Custom React hooks │ ├── types/ # TypeScript types │ └── App.tsx # Main app component ├── public/ # Static assets └── package.json # Dependencies ``` ## Development Setup ```bash cd frontend npm install npm run dev ``` Access at: http://localhost:3000 ## Creating a New Page 1. Create page component in `src/pages/`: ```typescript // src/pages/MyPage.tsx import { Box, Typography } from '@mui/material'; export function MyPage() { return ( My Page ); } ``` 2. Add route in `src/App.tsx`: ```typescript import { MyPage } from './pages/MyPage'; } /> ``` ## API Integration ### Creating API Functions ```typescript // src/api/myService.ts import { apiClient } from './client'; export const myServiceApi = { async getData() { const response = await apiClient.get('/api/my-service/data'); return response.data; }, async createItem(data: CreateItemDto) { const response = await apiClient.post('/api/my-service/items', data); return response.data; } }; ``` ### Using React Query ```typescript import { useQuery, useMutation } from '@tanstack/react-query'; import { myServiceApi } from '@/api/myService'; function MyComponent() { // Fetch data const { data, isLoading, error } = useQuery({ queryKey: ['myData'], queryFn: myServiceApi.getData }); // Mutate data const mutation = useMutation({ mutationFn: myServiceApi.createItem, onSuccess: () => { queryClient.invalidateQueries({ queryKey: ['myData'] }); } }); return (
{isLoading && } {data && }
); } ``` ## Creating Reusable Components ```typescript // src/components/DataTable.tsx import { Table, TableBody, TableCell, TableHead, TableRow } from '@mui/material'; interface DataTableProps { data: T[]; columns: Column[]; } export function DataTable({ data, columns }: DataTableProps) { return ( {columns.map(col => ( {col.header} ))} {data.map((row, idx) => ( {columns.map(col => ( {col.render(row)} ))} ))}
); } ``` ## Custom Hooks ```typescript // src/hooks/useOrders.ts import { useQuery, useMutation } from '@tanstack/react-query'; import { tradingApi } from '@/api/trading'; export function useOrders() { const { data: orders, isLoading, error } = useQuery({ queryKey: ['orders'], queryFn: () => tradingApi.getOrders() }); const placeOrder = useMutation({ mutationFn: tradingApi.placeOrder, onSuccess: () => { queryClient.invalidateQueries({ queryKey: ['orders'] }); } }); return { orders: orders ?? [], isLoading, error, placeOrder: placeOrder.mutate }; } ``` ## WebSocket Integration The application uses an enhanced WebSocket system with message type handling: ```typescript // Using the WebSocket context import { useWebSocketContext } from '@/components/WebSocketProvider'; import { useRealtimeData } from '@/hooks/useRealtimeData'; function MyComponent() { const { isConnected, lastMessage, subscribe } = useWebSocketContext(); // Subscribe to specific message types useEffect(() => { const unsubscribe = subscribe('order_update', (message) => { // Handle order update console.log('Order updated:', message); }); return unsubscribe; }, [subscribe]); // Or use the real-time data hook for automatic query invalidation useRealtimeData(); // Automatically handles common message types } ``` ### Message Types The WebSocket supports these message types: - `order_update`: Order status changes - `position_update`: Position changes - `price_update`: Price updates - `alert_triggered`: Alert notifications - `strategy_signal`: Strategy signal notifications - `system_event`: System events and errors ## Form Handling ```typescript import { useForm } from 'react-hook-form'; import { yupResolver } from '@hookform/resolvers/yup'; import * as yup from 'yup'; const schema = yup.object({ symbol: yup.string().required(), quantity: yup.number().positive().required() }); function OrderForm() { const { register, handleSubmit, formState: { errors } } = useForm({ resolver: yupResolver(schema) }); const onSubmit = async (data) => { await tradingApi.placeOrder(data); }; return (
); } ``` ## Error Handling The application uses a centralized Snackbar context for error handling: ```typescript import { useSnackbar } from '@/contexts/SnackbarContext'; import ErrorDisplay from '@/components/ErrorDisplay'; function MyComponent() { const { showError, showSuccess, showWarning, showInfo } = useSnackbar(); const handleAction = async () => { try { await apiCall(); showSuccess('Action completed successfully'); } catch (err) { showError(err instanceof Error ? err.message : 'An error occurred'); } }; // For complex error display with retry return ( <> {error && ( )} ); } ``` ### Available Components - `ErrorDisplay`: Enhanced error display with retry functionality - `LoadingSkeleton`: Loading placeholders for tables, cards, lists - `ProgressOverlay`: Overlay with progress indicator - `StatusIndicator`: Connection status indicators - `DataFreshness`: Data freshness timestamps - `HelpTooltip`: Contextual help tooltips - `InfoCard`: Collapsible information cards - `OperationsPanel`: Panel showing running operations ## Styling ### Material-UI Theming ```typescript // src/theme.ts import { createTheme } from '@mui/material/styles'; export const theme = createTheme({ palette: { mode: 'dark', primary: { main: '#1976d2' } } }); ``` ### Component Styling Use Material-UI's `sx` prop for inline styles: ```typescript Content ``` ## Testing See [Testing Guide](./testing.md) for frontend testing strategies. ## Best Practices 1. **Type Safety**: Always use TypeScript types 2. **Component Composition**: Prefer composition over inheritance 3. **Custom Hooks**: Extract reusable logic into hooks 4. **Error Handling**: Handle errors gracefully with user feedback 5. **Loading States**: Always show loading indicators 6. **Accessibility**: Use semantic HTML and ARIA labels 7. **Performance**: Use React.memo, useMemo, useCallback appropriately 8. **Code Splitting**: Use lazy loading for large components 9. **Form Validation**: Validate on both client and server 10. **Consistent Patterns**: Follow established patterns in the codebase