288 lines
7.0 KiB
Markdown
288 lines
7.0 KiB
Markdown
# Route Generation System - Quick Integration Guide
|
|
|
|
## ๐ Quick Start
|
|
|
|
### 1. Add OpenAI API Key
|
|
Add your OpenAI API key to `.env`:
|
|
```env
|
|
VITE_OPENAI_API_KEY=sk-your-api-key-here
|
|
```
|
|
|
|
### 2. Integrate MapTiler Map
|
|
|
|
Replace existing map component in TripPlanner:
|
|
|
|
```typescript
|
|
import { MapTilerMap } from '@/components/TripPlanner/Map/MapTilerMap';
|
|
import { useRouteStore } from '@/store/route-store';
|
|
import { getAllCappadociaPOIs } from '@/services/poi-service';
|
|
|
|
// In your component
|
|
const { allPOIs, setAllPOIs } = useRouteStore();
|
|
|
|
// Load POIs on mount
|
|
useEffect(() => {
|
|
const loadPOIs = async () => {
|
|
const pois = await getAllCappadociaPOIs();
|
|
setAllPOIs(pois);
|
|
};
|
|
loadPOIs();
|
|
}, []);
|
|
|
|
// Render map
|
|
<MapTilerMap
|
|
places={tripPlaces}
|
|
allPOIs={allPOIs}
|
|
center={[38.6431, 34.8289]}
|
|
zoom={11}
|
|
/>
|
|
```
|
|
|
|
### 3. Add Route Generator Button
|
|
|
|
```typescript
|
|
import { RouteGeneratorWizard } from '@/components/TripPlanner/RouteGenerator';
|
|
import { useState } from 'react';
|
|
|
|
const [showRouteGenerator, setShowRouteGenerator] = useState(false);
|
|
|
|
// Button
|
|
<Button
|
|
onClick={() => setShowRouteGenerator(true)}
|
|
className="fixed bottom-6 right-6 rounded-full shadow-lg"
|
|
size="lg"
|
|
>
|
|
<Sparkles className="mr-2 h-5 w-5" />
|
|
Generate Personalized Route
|
|
</Button>
|
|
|
|
// Wizard
|
|
<RouteGeneratorWizard
|
|
open={showRouteGenerator}
|
|
onClose={() => setShowRouteGenerator(false)}
|
|
onComplete={(route) => {
|
|
// Add route places to trip
|
|
route.days.forEach((day, dayIndex) => {
|
|
day.places.forEach((place) => {
|
|
// Add place to trip day
|
|
addPlaceToTripDay(dayIndex + 1, place);
|
|
});
|
|
});
|
|
setShowRouteGenerator(false);
|
|
toast.success('Route added to your trip!');
|
|
}}
|
|
/>
|
|
```
|
|
|
|
## ๐ฆ Available Components
|
|
|
|
### MapTilerMap
|
|
```typescript
|
|
<MapTilerMap
|
|
places={Place[]} // Places in route
|
|
allPOIs={POI[]} // All available POIs
|
|
center={[lat, lng]} // Map center (optional)
|
|
zoom={number} // Zoom level (optional)
|
|
className={string} // CSS class (optional)
|
|
/>
|
|
```
|
|
|
|
### RouteGeneratorWizard
|
|
```typescript
|
|
<RouteGeneratorWizard
|
|
open={boolean} // Show/hide wizard
|
|
onClose={() => void} // Close handler
|
|
onComplete={(route: RouteRecommendation) => void} // Success handler
|
|
/>
|
|
```
|
|
|
|
## ๐ง Utility Functions
|
|
|
|
### Route Optimizer
|
|
```typescript
|
|
import { optimizeRoute, calculateTotalDistance, getRouteStatistics } from '@/utils/route-optimizer';
|
|
|
|
// Optimize places by distance
|
|
const optimized = optimizeRoute(places, {
|
|
maxDurationMinutes: 480, // 8 hours
|
|
priorityWeight: 0.5
|
|
});
|
|
|
|
// Calculate distance
|
|
const distance = calculateTotalDistance(places);
|
|
|
|
// Get statistics
|
|
const stats = getRouteStatistics(places);
|
|
// Returns: { totalDistance, totalTravelTime, totalActivityTime, totalTime }
|
|
```
|
|
|
|
### Map Interactions
|
|
```typescript
|
|
import { addPOIToRoute, removePlaceFromRoute, isPlaceInRoute } from '@/utils/map-interactions';
|
|
|
|
// Add POI to route
|
|
await addPOIToRoute(poiId);
|
|
|
|
// Remove place from route
|
|
removePlaceFromRoute(placeId);
|
|
|
|
// Check if place is in route
|
|
const inRoute = isPlaceInRoute(placeId);
|
|
```
|
|
|
|
### POI Service
|
|
```typescript
|
|
import { getAllCappadociaPOIs, getPOIById, getPOIsByCategory, searchPOIs } from '@/services/poi-service';
|
|
|
|
// Get all POIs
|
|
const allPOIs = await getAllCappadociaPOIs();
|
|
|
|
// Get single POI
|
|
const poi = await getPOIById(id);
|
|
|
|
// Get by category
|
|
const restaurants = await getPOIsByCategory('restaurant');
|
|
|
|
// Search
|
|
const results = await searchPOIs('Gรถreme');
|
|
```
|
|
|
|
## ๐จ Customization
|
|
|
|
### Change Map Style
|
|
Edit `MapTilerMap.tsx`:
|
|
```typescript
|
|
const MAPTILER_STYLE = 'outdoor-v2'; // or 'streets-v2', 'satellite', etc.
|
|
```
|
|
|
|
### Modify Interests
|
|
Edit `PreferencesStep.tsx`:
|
|
```typescript
|
|
const INTERESTS = [
|
|
{ id: 'custom', label: 'Custom Interest', icon: '๐ฏ' },
|
|
// Add more interests
|
|
];
|
|
```
|
|
|
|
### Adjust Rate Limits
|
|
Edit `api-rate-limiter.ts`:
|
|
```typescript
|
|
export const openaiRateLimiter = new RateLimiter({
|
|
maxRequests: 20, // Increase limit
|
|
windowMs: 60 * 60 * 1000, // 1 hour
|
|
});
|
|
```
|
|
|
|
### Customize Marker Icons
|
|
Edit `MapTilerMap.tsx` `getCategoryIcon()` function:
|
|
```typescript
|
|
const iconConfig = {
|
|
restaurant: { color: '#FF6347', icon: '๐ฝ๏ธ' },
|
|
custom: { color: '#YOUR_COLOR', icon: '๐ฏ' },
|
|
// Add more categories
|
|
};
|
|
```
|
|
|
|
## ๐ Security
|
|
|
|
### Rate Limiting
|
|
- OpenAI: 10 requests/hour per user
|
|
- MapTiler: 100 requests/minute per user
|
|
- Automatic cleanup of expired entries
|
|
|
|
### API Key Protection
|
|
- OpenAI key stored in environment variables
|
|
- Never exposed to client (use Edge Functions for production)
|
|
- Rate limiter prevents abuse
|
|
|
|
## ๐ Troubleshooting
|
|
|
|
### Map Not Loading
|
|
1. Check MapTiler API key in `.env`
|
|
2. Verify internet connection
|
|
3. Check browser console for errors
|
|
4. Ensure Leaflet CSS is imported
|
|
|
|
### Route Generation Fails
|
|
1. Check OpenAI API key is set
|
|
2. Verify API key has credits
|
|
3. Check rate limit not exceeded
|
|
4. Review browser console for errors
|
|
|
|
### POIs Not Showing
|
|
1. Verify places exist in database
|
|
2. Check POI service returns data
|
|
3. Ensure `setAllPOIs()` is called
|
|
4. Check map bounds include POIs
|
|
|
|
### Markers Not Clickable
|
|
1. Verify `map-interactions.ts` is imported in `main.tsx`
|
|
2. Check global functions are defined
|
|
3. Ensure popup HTML is correct
|
|
4. Test on different browsers
|
|
|
|
## ๐ Monitoring
|
|
|
|
### Check API Usage
|
|
```typescript
|
|
import { openaiRateLimiter } from '@/utils/api-rate-limiter';
|
|
|
|
// Get remaining requests
|
|
const remaining = openaiRateLimiter.getRemainingRequests(userId);
|
|
|
|
// Get reset time
|
|
const resetTime = openaiRateLimiter.getResetTime(userId);
|
|
```
|
|
|
|
### Database Queries
|
|
```sql
|
|
-- Check generated routes
|
|
SELECT * FROM generated_routes WHERE user_id = 'user-id';
|
|
|
|
-- Check API usage
|
|
SELECT * FROM api_usage WHERE user_id = 'user-id' ORDER BY created_at DESC;
|
|
```
|
|
|
|
## ๐ฏ Best Practices
|
|
|
|
1. **Load POIs Once**: Load POIs on component mount, not on every render
|
|
2. **Debounce Map Updates**: Avoid updating map too frequently
|
|
3. **Cache Routes**: Store generated routes in database
|
|
4. **Error Boundaries**: Wrap components in error boundaries
|
|
5. **Loading States**: Show loading indicators during API calls
|
|
6. **User Feedback**: Use toast notifications for actions
|
|
7. **Mobile First**: Test on mobile devices
|
|
8. **Accessibility**: Ensure keyboard navigation works
|
|
|
|
## ๐ Resources
|
|
|
|
- [MapTiler Docs](https://docs.maptiler.com/)
|
|
- [Leaflet Docs](https://leafletjs.com/)
|
|
- [OpenAI API Docs](https://platform.openai.com/docs)
|
|
- [Leaflet.markercluster](https://github.com/Leaflet/Leaflet.markercluster)
|
|
|
|
## ๐ Support
|
|
|
|
For issues or questions:
|
|
1. Check implementation summary: `ROUTE_GENERATION_IMPLEMENTATION.md`
|
|
2. Review component source code
|
|
3. Check browser console for errors
|
|
4. Test with sample data
|
|
5. Verify environment variables
|
|
|
|
## โ
Checklist
|
|
|
|
Before deploying:
|
|
- [ ] OpenAI API key configured
|
|
- [ ] MapTiler API key verified
|
|
- [ ] Database migrations applied
|
|
- [ ] POIs loaded successfully
|
|
- [ ] Map renders correctly
|
|
- [ ] Route generation works
|
|
- [ ] Rate limiting active
|
|
- [ ] Error handling tested
|
|
- [ ] Mobile responsive
|
|
- [ ] Loading states working
|
|
- [ ] Toast notifications showing
|
|
- [ ] Lint checks passed
|