# 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 (
    <Box>
      <Typography variant="h4">My Page</Typography>
    </Box>
  );
}
```

2. Add route in `src/App.tsx`:

```typescript
import { MyPage } from './pages/MyPage';

<Route path="/my-page" element={<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 (
    <div>
      {isLoading && <Loading />}
      {data && <DataDisplay data={data} />}
      <button onClick={() => mutation.mutate(formData)}>Create</button>
    </div>
  );
}
```

## Creating Reusable Components

```typescript
// src/components/DataTable.tsx
import { Table, TableBody, TableCell, TableHead, TableRow } from '@mui/material';

interface DataTableProps<T> {
  data: T[];
  columns: Column<T>[];
}

export function DataTable<T>({ data, columns }: DataTableProps<T>) {
  return (
    <Table>
      <TableHead>
        <TableRow>
          {columns.map(col => (
            <TableCell key={col.key}>{col.header}</TableCell>
          ))}
        </TableRow>
      </TableHead>
      <TableBody>
        {data.map((row, idx) => (
          <TableRow key={idx}>
            {columns.map(col => (
              <TableCell key={col.key}>{col.render(row)}</TableCell>
            ))}
          </TableRow>
        ))}
      </TableBody>
    </Table>
  );
}
```

## 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 (
    <form onSubmit={handleSubmit(onSubmit)}>
      <TextField
        {...register('symbol')}
        error={!!errors.symbol}
        helperText={errors.symbol?.message}
      />
      <Button type="submit">Place Order</Button>
    </form>
  );
}
```

## 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 && (
        <ErrorDisplay
          error={error}
          title="Operation Failed"
          onRetry={handleAction}
        />
      )}
    </>
  );
}
```

### 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
<Box
  sx={{
    padding: 2,
    backgroundColor: 'background.paper',
    borderRadius: 1
  }}
>
  Content
</Box>
```

## 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
