diff --git a/client/src/components/PDF/TripPDF.tsx b/client/src/components/PDF/TripPDF.tsx index 2a4c03a..91da01d 100644 --- a/client/src/components/PDF/TripPDF.tsx +++ b/client/src/components/PDF/TripPDF.tsx @@ -1,22 +1,33 @@ // Trip PDF via browser print window import { createElement } from 'react' import { getCategoryIcon } from '../shared/categoryIcons' -import { FileText, Info, Clock, MapPin, Navigation, Train, Plane, Bus, Car, Ship, Coffee, Ticket, Star, Heart, Camera, Flag, Lightbulb, AlertTriangle, ShoppingBag, Bookmark } from 'lucide-react' -import { mapsApi } from '../../api/client' +import { FileText, Info, Clock, MapPin, Navigation, Train, Plane, Bus, Car, Ship, Coffee, Ticket, Star, Heart, Camera, Flag, Lightbulb, AlertTriangle, ShoppingBag, Bookmark, Hotel, LogIn, LogOut, KeyRound, BedDouble, LucideIcon } from 'lucide-react' +import { accommodationsApi, mapsApi } from '../../api/client' import type { Trip, Day, Place, Category, AssignmentsMap, DayNotesMap } from '../../types' +function renderLucideIcon(icon:LucideIcon, props = {}) { + if (!_renderToStaticMarkup) return '' + return _renderToStaticMarkup( + createElement(icon, props) + ); +} + const NOTE_ICON_MAP = { FileText, Info, Clock, MapPin, Navigation, Train, Plane, Bus, Car, Ship, Coffee, Ticket, Star, Heart, Camera, Flag, Lightbulb, AlertTriangle, ShoppingBag, Bookmark } function noteIconSvg(iconId) { - if (!_renderToStaticMarkup) return '' const Icon = NOTE_ICON_MAP[iconId] || FileText - return _renderToStaticMarkup(createElement(Icon, { size: 14, strokeWidth: 1.8, color: '#94a3b8' })) + return renderLucideIcon(Icon, { size: 14, strokeWidth: 1.8, color: '#94a3b8' }) } const TRANSPORT_ICON_MAP = { flight: Plane, train: Train, bus: Bus, car: Car, cruise: Ship } function transportIconSvg(type) { - if (!_renderToStaticMarkup) return '' const Icon = TRANSPORT_ICON_MAP[type] || Ticket - return _renderToStaticMarkup(createElement(Icon, { size: 14, strokeWidth: 1.8, color: '#3b82f6' })) + return renderLucideIcon(Icon, { size: 14, strokeWidth: 1.8, color: '#3b82f6' }) +} + +const ACCOMMODATION_ICON_MAP = { accommodation: Hotel, checkin: LogIn, checkout: LogOut, location: MapPin, note: FileText, confirmation: KeyRound } +function accommodationIconSvg(type) { + const Icon = ACCOMMODATION_ICON_MAP[type] || BedDouble + return renderLucideIcon(Icon, { size: 14, strokeWidth: 1.8, color: '#03398f', className: 'accommodation-icon' }) } // ── SVG inline icons (for chips) ───────────────────────────────────────────── @@ -115,6 +126,8 @@ export async function downloadTripPDF({ trip, days, places, assignments, categor const sorted = [...(days || [])].sort((a, b) => a.day_number - b.day_number) const range = longDateRange(sorted, loc) const coverImg = safeImg(trip?.cover_image) + //retrieve accommodations for the trip to display on the day sections and prefetch their photos if needed + const accommodations = await accommodationsApi.list(trip.id); // Pre-fetch place photos from Google const photoMap = await fetchPlacePhotos(assignments) @@ -223,7 +236,53 @@ export async function downloadTripPDF({ trip, days, places, assignments, categor ${place.notes ? `