Smart Mobility Predictor - Developer Guide
Quick Start
Prerequisites
- Node.js 18+
- npm or yarn
- Git
- Code editor (VS Code recommended)
Setup
bash# Clone repository git clone <repo-url> cd smart-mobility-predictor # Install dependencies npm install # Run development server npm run dev # Open http://localhost:3000
Architecture Overview
Layer Model
┌─────────────────────────────────────┐
│ User Interface (React) │
│ - Components & Pages │
│ - Form inputs & Results display │
└────────────────────┬────────────────┘
│
┌────────────────────▼────────────────┐
│ State Management & Context │
│ - useLanguage (i18n) │
│ - useTheme (light/dark) │
│ - useState (form state) │
└────────────────────┬────────────────┘
│
┌────────────────────▼────────────────┐
│ Utilities & Services │
│ - i18n (translations) │
│ - currency (TND formatting) │
│ - ml-engine (predictions) │
│ - types (TypeScript) │
└────────────────────┬────────────────┘
│
┌────────────────────▼────────────────┐
│ API Routes (Next.js) │
│ - /api/predict - ML predictions │
│ - Validation & error handling │
└────────────────────┬────────────────┘
│
┌────────────────────▼────────────────┐
│ External Services │
│ - Browser localStorage │
│ - Intl API (formatting) │
└─────────────────────────────────────┘
Component Development
Creating a New Component
1. Define Types
typescript// lib/types.ts export interface MyFeature { id: string; name: string; data: Record<string, unknown>; }
2. Create Component
typescript// components/my-feature.tsx 'use client'; import { MyFeature } from '@/lib/types'; import { useTranslation } from '@/lib/language-context'; import { Card } from '@/components/ui/card'; interface MyFeatureProps { feature: MyFeature; onUpdate: (feature: MyFeature) => void; } export function MyFeature({ feature, onUpdate }: MyFeatureProps) { const t = useTranslation(); return ( <Card className="p-6"> <h2 className="text-lg font-semibold text-foreground"> {t('feature.title')} </h2> <p className="text-sm text-muted-foreground mt-2"> {t('feature.description')} </p> </Card> ); }
3. Add Translations
typescript// lib/i18n.ts export const translations = { en: { feature: { title: 'My Feature', description: 'Feature description', }, }, fr: { feature: { title: 'Ma Fonctionnalité', description: 'Description de la fonctionnalité', }, }, };
4. Use in Page
typescript// app/page.tsx import { MyFeature } from '@/components/my-feature'; export default function Home() { return ( <div className="space-y-6"> <MyFeature feature={myData} onUpdate={handleUpdate} /> </div> ); }
i18n (Internationalization) Guide
Supported Languages
- English (en) - Default
- French (fr) - Complete translations
Adding New Strings
- Open
lib/i18n.ts - Add to both EN and FR objects:
typescriptexport const translations = { en: { newFeature: { title: 'My Title', description: 'My description', }, }, fr: { newFeature: { titre: 'Mon Titre', description: 'Ma description', }, }, };
- Use in component:
typescriptconst t = useTranslation(); <h1>{t('newFeature.title')}</h1>
Translation Keys Hierarchy
header - Page header & navigation
hero - Hero section
main - Main content
form - Form labels & inputs
results - Results display
footer - Footer content
messages - Error & success messages
zones - Tunis zone names
Best Practices
- Keep keys short and descriptive
- Group related keys together
- Maintain consistent capitalization
- Don't hard-code user-facing strings
Currency (TND) Guide
Using Currency Functions
Format a Number
typescriptimport { formatTND, formatSimpleTND } from '@/lib/currency'; // Full formatting with locale formatTND(150.5); // "د.ت 150.500" (locale-aware) // Simple formatting formatSimpleTND(150.5); // "د.ت 150.500" // Null safe formatTND(null); // "د.ت0.000" formatTND(undefined); // "د.ت0.000"
Calculate Differences
typescriptimport { calculateSavings } from '@/lib/currency'; const savings = calculateSavings(100, 75); // { difference: 25, percentageSavings: 25 }
Parse Currency Strings
typescriptimport { parseTND } from '@/lib/currency'; const amount = parseTND('د.ت 50.500'); // Returns: 50.5
Currency Format Rules
- Symbol: د.ت (Right-to-left ready)
- Decimals: Always 3 places
- Locale: ar-TN (Tunisia)
- Code: TND
Example Usage in Components
tsximport { formatTND } from '@/lib/currency'; import { useTranslation } from '@/lib/language-context'; export function PriceDisplay({ price }: { price: number }) { const t = useTranslation(); return ( <div> <p className="text-sm text-muted-foreground"> {t('results.estimatedCost')} </p> <p className="text-2xl font-bold text-foreground"> {formatTND(price)} </p> </div> ); }
ML Engine Development
Understanding the Models
Regression (Travel Time)
typescript// Input variables - distance: number (km) - weather: WeatherType - traffic: TrafficState - hour: number (0-23) - weather_intensity: number (0-1) // Output - estimatedTime: number (minutes) - confidence: number (0-100) - confidence_interval: { lower, upper }
Classification (Traffic State)
typescript// Input variables - current_speed: number (km/h) - speed_limit: number (km/h) - vehicle_density: number (cars/km) // Output - state: 'fluide' | 'normal' | 'dense' | 'saturated' - probability: number (0-100) - stateDistribution: { fluide, normal, dense, saturated }
Clustering (Zone Profiling)
typescript// Input variables - zone_population: number - average_density: number - congestion_pattern: number[] - business_hours_activity: number // Output - clusterId: number - clusterName: string - characteristics: ZoneCharacteristics - silhouetteScore: number (0-1)
Modifying ML Logic
typescript// lib/ml-engine.ts export function predictTrafficState( currentSpeed: number, speedLimit: number, vehicleDensity: number ): ClassificationPrediction { // Add your logic here const speedRatio = currentSpeed / speedLimit; if (speedRatio > 0.9) return FLUIDE_PREDICTION; if (speedRatio > 0.6) return NORMAL_PREDICTION; if (speedRatio > 0.3) return DENSE_PREDICTION; return SATURATED_PREDICTION; }
API Development
Creating API Routes
Structure
typescript// app/api/[route]/route.ts import { NextRequest, NextResponse } from 'next/server'; export async function POST(request: NextRequest) { try { const body = await request.json(); // Validate input if (!body.required_field) { return NextResponse.json( { success: false, error: 'Missing required field' }, { status: 400 } ); } // Process request const result = processRequest(body); // Return response return NextResponse.json({ success: true, data: result }); } catch (error) { return NextResponse.json( { success: false, error: error instanceof Error ? error.message : 'Unknown error' }, { status: 500 } ); } }
Testing API Routes
bash# Using curl curl -X POST http://localhost:3000/api/predict \ -H "Content-Type: application/json" \ -d '{"origin": {...}, "destination": {...}}' # Using fetch in browser console fetch('/api/predict', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ /* data */ }) }) .then(r => r.json()) .then(console.log) .catch(console.error)
Performance Optimization
Code Splitting
typescript// Lazy load heavy components import dynamic from 'next/dynamic'; const PredictionResults = dynamic( () => import('@/components/prediction-results'), { loading: () => <div>Loading...</div> } );
Memoization
typescriptimport React from 'react'; export const MemoizedComponent = React.memo(function Component(props) { return <div>{props.children}</div>; });
Image Optimization
tsximport Image from 'next/image'; <Image src="/logo.png" alt="Logo" width={40} height={40} priority />
Data Fetching
typescript// Use SWR for client-side data import useSWR from 'swr'; const { data, error, isLoading } = useSWR('/api/predict', fetcher);
Testing Guide
Unit Tests
typescript// components/my-component.test.tsx import { render, screen } from '@testing-library/react'; import { MyComponent } from './my-component'; describe('MyComponent', () => { it('renders correctly', () => { render(<MyComponent />); expect(screen.getByText('Expected text')).toBeInTheDocument(); }); });
Integration Tests
typescript// app/api/predict.test.ts describe('POST /api/predict', () => { it('returns predictions', async () => { const response = await fetch('/api/predict', { method: 'POST', body: JSON.stringify({ /* test data */ }), }); const data = await response.json(); expect(data.success).toBe(true); }); });
Debugging
Debug Console Logs
typescript// Log with context console.log('[v0] User data received:', userData); console.log('[v0] API call starting with params:', params); console.log('[v0] Component rendered with props:', props); console.log('[v0] Error occurred in function:', error.message);
Browser DevTools
javascript// Check localStorage localStorage.getItem('smart-mobility-language') // Check API response fetch('/api/predict', { /* ... */ }) .then(r => r.json()) .then(console.log) // Check component state React DevTools in Chrome/Firefox
Network Debugging
javascript// Monitor fetch requests window.addEventListener('fetch', (event) => { console.log('Fetch:', event.request.url); });
Error Handling
API Error Pattern
typescripttry { const response = await fetch('/api/predict', options); if (!response.ok) { const error = await response.json(); throw new Error(error.message || 'API error'); } return await response.json(); } catch (err) { console.error('[v0] API Error:', err); return null; }
Null Safety Pattern
typescript// Safe property access const value = obj?.property?.nested?.value ?? defaultValue; // Safe method calls const result = array?.map(item => item.name) ?? []; // Safe numeric operations const fixed = number != null ? number.toFixed(3) : '0.000';
Code Style Guide
TypeScript
typescript// Use interfaces for object shapes interface User { id: string; name: string; email: string; } // Use enums for fixed values enum Status { PENDING = 'pending', COMPLETE = 'complete', ERROR = 'error', } // Use strict null checks const value: string | null = getData(); if (value !== null) { console.log(value); }
React Components
typescript// Use named exports export function MyComponent() { /* ... */ } // Define prop interfaces interface MyComponentProps { title: string; onSubmit: (data: Data) => void; } // Use proper hooks order function Component(props: Props) { const state = useState(); const effect = useEffect(() => {}, []); const translation = useTranslation(); return <div>{state}</div>; }
Styling
typescript// Use Tailwind classes className="flex items-center justify-between p-4 gap-2" // Use semantic naming className="flex items-center gap-2 p-4 rounded-lg border border-primary/20" // Avoid arbitrary values // ❌ className="p-[25px]" // ✅ className="p-6"
Git Workflow
Commit Messages
bashgit commit -m "feat: add language switcher component" git commit -m "fix: null check in currency formatter" git commit -m "docs: add implementation guide" git commit -m "refactor: simplify prediction logic"
Branch Naming
bashfeature/add-currency-support bugfix/fix-language-persistence docs/add-deployment-guide chore/update-dependencies
Deployment Checklist
Before Push
- Code compiles without errors
- No TypeScript errors
- ESLint passes
- All features tested
- Commit message is descriptive
- Documentation updated
After Deployment
- Verify in production
- Check analytics
- Monitor error logs
- Test in multiple browsers
- Check mobile responsiveness
Common Patterns
Using Translation Hook
typescriptimport { useTranslation } from '@/lib/language-context'; export function MyComponent() { const t = useTranslation(); return <h1>{t('feature.title')}</h1>; }
Using Currency Formatter
typescriptimport { formatTND } from '@/lib/currency'; export function Price({ amount }: { amount: number }) { return <p>{formatTND(amount)}</p>; }
API Call Pattern
typescriptconst handleSubmit = async (data: Data) => { setLoading(true); try { const response = await fetch('/api/predict', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(data), }); const result = await response.json(); if (result.success) { setData(result.data); } else { setError(result.error); } } catch (err) { setError('Network error'); } finally { setLoading(false); } };
Resources
Support
Need help? Check:
- Implementation Guide:
/docs/IMPLEMENTATION_GUIDE.md - Code comments
- Type definitions in
lib/types.ts - Existing component examples
Last Updated: January 23, 2026
Version: 1.0.0