# Route POI Search - Feature Documentation

## Overview

| Property | Value |
|----------|-------|
| Feature | POI Search on Route Segments |
| Status | ✅ Complete |
| Version | 1.0.0 |
| Date | 2025-11-24 |
| Components | RouteSegment.vue, RouteAISearch.vue |
| Dependencies | POIDiscoveryPanel.vue, useMobilePoiDiscovery, aiStore |

## Purpose

Enable users to discover and add Points of Interest (POIs) directly from route segments in the Timeline view, with contextual filters and intelligent suggestions.

## Architecture

### Component Hierarchy

| Component | Role | Location |
|-----------|------|----------|
| `RouteSegment.vue` | Display route segment with POI search trigger | `apps/web/src/modules/planner/components/` |
| `RouteAISearch.vue` | Smart POI search interface with filters | `apps/web/src/modules/planner/components/` |
| `POIDiscoveryPanel.vue` | Display POI results (grid/list) | `apps/web/src/modules/planner/components/` |
| `PlannerPage.web.vue` | Desktop planner container | `apps/web/src/modules/planner/pages/` |
| `PlannerPage.mobile.vue` | Mobile planner container | `apps/web/src/modules/planner/pages/` |

### Data Flow

| Step | Component | Action |
|------|-----------|--------|
| 1 | RouteSegment | User clicks "Découvrir des POIs" button |
| 2 | RouteSegment | Opens q-dialog with RouteAISearch |
| 3 | RouteAISearch | User configures filters (time, activity, categories) |
| 4 | RouteAISearch | Calls aiStore.generatePOISuggestions() |
| 5 | RouteAISearch | Displays results via POIDiscoveryPanel |
| 6 | RouteAISearch | User clicks POI → createStage() at toStageIndex |
| 7 | RouteAISearch | Emits 'poi-added' event |
| 8 | PlannerPage | Shows success notification |
| 9 | RouteSegment | Dialog auto-closes after 500ms |

## Files Created

| File | Lines | Purpose |
|------|-------|---------|
| `RouteAISearch.vue` | 800+ | Smart POI search with filters & quick actions |

## Files Modified

| File | Changes | Reason |
|------|---------|--------|
| `RouteSegment.vue` | Added POI dialog, search button, imports | Enable POI search from segments |
| `PlannerPage.web.vue` | Added stage indexes props, poi-added handler | Pass context to RouteSegment |
| `PlannerPage.mobile.vue` | Added stage indexes props, poi-added handler | Pass context to RouteSegment |

## Files Deleted

| File | Reason |
|------|--------|
| `RouteSegmentPOIDialog.vue` | Replaced by inline dialog in RouteSegment.vue |

## Component Details

### RouteSegment.vue

**New Props:**

| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `fromStage` | Stage | ✅ | Starting stage of route |
| `toStage` | Stage | ✅ | Ending stage of route |
| `fromStageIndex` | number | ✅ | Index of starting stage |
| `toStageIndex` | number | ✅ | Index where POI will be inserted |
| `distance` | number | ❌ | Route distance in meters |
| `duration` | number | ❌ | Route duration in minutes |

**New Events:**

| Event | Payload | Description |
|-------|---------|-------------|
| `poi-added` | `(poi: AIPOISuggestion, insertIndex: number)` | Emitted when POI is added to route |

**New UI Elements:**

| Element | Location | Action |
|---------|----------|--------|
| "Découvrir des POIs" button | Expanded route section | Opens POI search dialog |
| q-dialog | Root level | Contains RouteAISearch component |

### RouteAISearch.vue

**Props:**

| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `fromStage` | Stage | ✅ | Starting stage of route |
| `toStage` | Stage | ✅ | Ending stage of route |
| `fromStageIndex` | number | ✅ | Index of starting stage |
| `toStageIndex` | number | ✅ | Index where POI will be inserted |

**State Management:**

| State | Type | Default | Purpose |
|-------|------|---------|---------|
| `radiusKm` | number | 25 | Search radius in kilometers |
| `selectedCategories` | string[] | [] | Active category filters |
| `timeContext` | string | 'anytime' | Time of day context |
| `departureTime` | string | '' | Specific departure time (HH:mm) |
| `arrivalTime` | string | '' | Specific arrival time (HH:mm) |
| `activityType` | string | 'any' | Type of activity searched |
| `customQuery` | string | '' | Free-text search query |
| `isLoading` | boolean | false | Loading state |
| `results` | AIPOISuggestion[] | [] | Search results |
| `error` | string \| null | null | Error message |

**Filter Options:**

#### Time Context Options

| Value | Label | Use Case |
|-------|-------|----------|
| `anytime` | N'importe quand | No time constraint |
| `morning` | Matin (6h-12h) | Morning activities |
| `afternoon` | Après-midi (12h-18h) | Afternoon activities |
| `evening` | Soirée (18h-22h) | Evening activities |
| `night` | Nuit (22h-6h) | Night activities |
| `sunrise` | Lever du soleil | Sunrise viewing |
| `sunset` | Coucher du soleil | Sunset viewing |
| `specific` | Horaire spécifique | Custom time range |

#### Activity Type Options

| Value | Label | Examples |
|-------|-------|----------|
| `any` | Tout type | No filter |
| `essential` | Services essentiels | Docteur, pharmacie, magasin |
| `meal` | Repas / Pause gourmande | Restaurant, café |
| `rest` | Pause repos / Nuit | Hôtel, aire de repos |
| `fuel` | Carburant / Services auto | Station-service |
| `scenic` | Points de vue / Photos | Panoramas, spots photo |
| `cultural` | Culture / Patrimoine | Musées, monuments |
| `nature` | Nature / Randonnée | Parcs, sentiers |
| `shopping` | Shopping / Courses | Magasins, centres commerciaux |
| `entertainment` | Divertissement / Loisirs | Activités, parcs d'attractions |

#### Quick Action Templates

| ID | Emoji | Label | Pre-configured Filters |
|----|-------|-------|------------------------|
| `sunset` | 🌅 | Coucher de soleil | time: sunset, activity: scenic, category: viewpoint, query: "Vue panoramique" |
| `coffee` | ☕ | Pause café | time: anytime, activity: meal, category: cafe, query: "Café cosy" |
| `lunch` | 🍽️ | Déjeuner | time: afternoon, activity: meal, category: restaurant, query: "Restaurant local" |
| `photo` | 📸 | Photo spot | time: anytime, activity: scenic, category: viewpoint, query: "Point de vue Instagram" |
| `nature` | 🌲 | Pause nature | time: anytime, activity: nature, category: park, query: "Balade nature courte" |
| `fuel` | ⛽ | Ravitaillement | time: anytime, activity: fuel, radius: 50km, query: "Station avec commodités" |
| `surprise` | 🎲 | Surprise-moi ! | time: anytime, activity: any, query: "Lieu unique et insolite" |

**Key Methods:**

| Method | Parameters | Returns | Purpose |
|--------|------------|---------|---------|
| `applyTemplate()` | template | void | Apply quick action template to filters |
| `toggleCategory()` | category: string | void | Toggle category filter on/off |
| `generateSuggestions()` | - | Promise | Call AI API to get POI suggestions |
| `handleAddPOI()` | poi: AIPOISuggestion | Promise | Add POI to plan at toStageIndex |

**API Integration:**

| Call | Method | Payload |
|------|--------|---------|
| AI Suggestions | `aiStore.generatePOISuggestions()` | location (midpoint), radiusKm, categories, context, customPrompt |
| Create Stage | `plannerStore.createStage()` | planId, CreateStageDTO with type='poi', order=toStageIndex |

### PlannerPage Updates

**Web Version:**

| Change | Location | Purpose |
|--------|----------|---------|
| Added `:from-stage-index="index"` | RouteSegmentComponent | Pass stage index |
| Added `:to-stage-index="index + 1"` | RouteSegmentComponent | Pass insertion index |
| Added `@poi-added="handlePOIAddedToRoute"` | RouteSegmentComponent | Handle POI addition |
| Added `handlePOIAddedToRoute()` | Script setup | Show success notification |

**Mobile Version:**

| Change | Location | Purpose |
|--------|----------|---------|
| Same as web | RouteSegmentComponent | Same functionality |
| Uses `showMobileFeedback()` | Handler | Mobile-specific notification |

## User Flow

| Step | User Action | System Response |
|------|-------------|-----------------|
| 1 | Clicks route segment | Segment expands with details |
| 2 | Clicks "Découvrir des POIs" | Dialog opens with filters |
| 3 | (Optional) Clicks quick action | Filters auto-populate + search starts |
| 4 | Adjusts filters | UI updates reactively |
| 5 | Clicks "Rechercher des POIs" | Loading state + AI call |
| 6 | Views results | POIDiscoveryPanel shows suggestions |
| 7 | Clicks POI card | Stage created at toStageIndex |
| 8 | - | Success notification + dialog closes |
| 9 | - | Timeline refreshes with new POI |

## Technical Decisions

### Why No RouteSegmentPOIDialog?

| Option | Chosen | Reason |
|--------|--------|--------|
| Separate wrapper component | ❌ | Unnecessary abstraction |
| Inline dialog in RouteSegment | ✅ | Simpler, less boilerplate |

### Why New RouteAISearch Component?

| Alternative | Issue | Solution |
|-------------|-------|----------|
| Reuse POIDiscoveryPanel | No filters/configuration | RouteAISearch wraps it with context |
| Reuse DashboardAIAssistantNew | Too many irrelevant options | RouteAISearch is route-specific |

### Why Quick Actions?

| Problem | Solution | Impact |
|---------|----------|--------|
| Too many filters = friction | One-click templates | Instant gratification |
| Users don't know what to search | Curated common scenarios | Discovery |
| Complex configuration | Pre-filled values | Reduced cognitive load |

## Context Prompt Engineering

**AI receives enriched context:**

| Input | Example | Purpose |
|-------|---------|---------|
| Route info | "Route Paris → Lyon" | Geographic context |
| Time context | "Moment recherché: au coucher du soleil" | Temporal context |
| Activity type | "Type recherché: points de vue pour photos" | Intent context |
| Custom query | "Demande spécifique: Vue sur mer" | User refinement |

**Prompt Template:**
```
Recherche sur la route entre "{fromStage}" et "{toStage}".
[+ Moment recherché: {timeLabel}]
[+ Type recherché: {activityLabel}]
[+ Demande spécifique: "{customQuery}"]
```

## UI/UX Features

### Visual Hierarchy

| Level | Element | Purpose |
|-------|---------|---------|
| 1 | Context banner | Route + timing info |
| 2 | Quick actions grid | One-click templates |
| 3 | Detailed filters | Fine-tuning |
| 4 | Search button | Action trigger |
| 5 | Results display | POI cards |

### Responsive Design

| Breakpoint | Quick Actions Grid | Dialog Size |
|------------|-------------------|-------------|
| Desktop (>768px) | auto-fit minmax(100px, 1fr) | 90vw max 900px |
| Mobile (<768px) | auto-fit minmax(100px, 1fr) | 95vw |

### Animations

| Element | Effect | Timing |
|---------|--------|--------|
| Dialog | scale in/out | 300ms |
| Quick action hover | translateY(-2px) | 200ms ease |
| Template apply | Auto-search delay | 300ms |
| Dialog close | After POI add | 500ms |

## Performance

| Metric | Value | Notes |
|--------|-------|-------|
| Dialog open | <100ms | Instant |
| Template apply | 300ms | Debounced auto-search |
| AI search | 2-5s | Backend dependent |
| POI add | <500ms | Firestore write |
| Dialog close | 500ms | UX delay |

## Error Handling

| Error | User Message | Recovery |
|-------|--------------|----------|
| Invalid coordinates | "Coordonnées invalides" | Prevent search |
| No quota | "Quota épuisé" | Disable button |
| API error | Backend message | Show retry option |
| No results | "Aucune suggestion trouvée" | Suggest filter changes |
| Stage creation fail | "Impossible d'ajouter ce POI" | Rollback state |

## Accessibility

| Feature | Implementation |
|---------|---------------|
| Keyboard navigation | q-btn, q-select support |
| Screen readers | Semantic HTML, ARIA labels |
| Color contrast | WCAG AA compliant |
| Focus management | Auto-focus on dialog open |

## Testing Checklist

- [ ] Route segment button appears
- [ ] Dialog opens with correct route info
- [ ] Quick actions populate filters
- [ ] Time-specific fields show/hide
- [ ] Custom query field works
- [ ] Radius slider updates chip
- [ ] Category chips toggle
- [ ] Search button triggers API
- [ ] Loading state displays
- [ ] Results render in POIDiscoveryPanel
- [ ] POI add creates stage at correct index
- [ ] Success notification appears
- [ ] Dialog auto-closes
- [ ] Timeline updates with new POI
- [ ] Error states handle gracefully
- [ ] Mobile responsive layout
- [ ] Web responsive layout

## Future Enhancements

| Feature | Priority | Effort | Impact |
|---------|----------|--------|--------|
| Mini-map preview | High | Medium | High - Visual context |
| Smart default suggestions | High | Low | High - Auto-magic |
| Photo previews in results | Medium | High | High - Visual appeal |
| Timeline impact preview | Medium | Medium | Medium - Planning aid |
| Social recommendations | Low | High | Medium - Trust signal |
| Gamification (surprise mode) | Low | Medium | High - Fun factor |
| Drag-and-drop POI reorder | Medium | Medium | Medium - Flexibility |
| Historical weather data | Low | High | Low - Edge case |

## Related Documentation

| Document | Purpose |
|----------|---------|
| `docs/REFERENCE.md` | API endpoints, schemas |
| `docs/ARCHITECTURE.md` | System design |
| `.github/instructions/FOCUS.instructions.md` | Code standards |
| `packages/types/src/planner.types.ts` | TypeScript types |

## Maintenance Notes

| Area | Consideration |
|------|---------------|
| AI Prompts | Review effectiveness monthly |
| Quick Actions | Add/remove based on usage analytics |
| Filter Options | Expand based on user feedback |
| Performance | Monitor AI response times |
| Mobile UX | Test on various devices |

## Version History

| Version | Date | Changes |
|---------|------|---------|
| 1.0.0 | 2025-11-24 | Initial implementation |
