diff --git a/client/src/components/PDF/TripPDF.tsx b/client/src/components/PDF/TripPDF.tsx
index c83cc4b..57412d2 100644
--- a/client/src/components/PDF/TripPDF.tsx
+++ b/client/src/components/PDF/TripPDF.tsx
@@ -2,7 +2,7 @@
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 { accommodationsApi, mapsApi } from '../../api/client'
import type { Trip, Day, Place, Category, AssignmentsMap, DayNotesMap } from '../../types'
const NOTE_ICON_MAP = { FileText, Info, Clock, MapPin, Navigation, Train, Plane, Bus, Car, Ship, Coffee, Ticket, Star, Heart, Camera, Flag, Lightbulb, AlertTriangle, ShoppingBag, Bookmark }
@@ -115,6 +115,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 accomodations for the trip to display on the day sections and prefetch their photos if needed
+ const accomodations = await accommodationsApi.list(trip.id);
// Pre-fetch place photos from Google
const photoMap = await fetchPlacePhotos(assignments)
@@ -223,7 +225,45 @@ export async function downloadTripPDF({ trip, days, places, assignments, categor
${place.notes ? `
${escHtml(place.notes)}
` : ''}
`
- }).join('')
+ }).join('')
+
+ const accomodationsForDay = accomodations.accommodations?.filter(a =>
+ days.some(d => d.id >= a.start_day_id && d.id <= a.end_day_id && d.id === day?.id)
+ ).sort((a, b) => a.start_day_id - b.start_day_id);
+
+ const accomodationDetails = accomodationsForDay.map(item => {
+
+ const isCheckIn = day.id === item.start_day_id;
+ const isCheckOut = day.id === item.end_day_id;
+ const accomoAction = isCheckIn ? '🛎️ '+tr('reservations.meta.checkIn')
+ : isCheckOut ? '🧳 '+tr('reservations.meta.checkOut')
+ : '🏨 '+tr('reservations.meta.linkAccommodation')
+
+ const accomoEmoji = isCheckIn ? '🛎️'
+ : isCheckOut ? '🧳'
+ : ''
+
+ const accomoTime = isCheckIn ? item.check_in || 'N/A'
+ : isCheckOut ? item.check_out || 'N/A'
+ : ''
+
+ return `
+
+
${escHtml(accomoAction)}
+ ${accomoTime ? `
${accomoEmoji} ${accomoTime}
` : ''}
+
+
🏨 ${escHtml(item.place_name)}
+ ${item.place_address ? `
📌 ${escHtml(item.place_address)}
` : ''}
+ ${item.notes ? `
📝 ${escHtml(item.notes)}
` : ''}
+ ${isCheckIn && item.confirmation ? `
🔑 ${escHtml(item.confirmation)}
` : ''}
+
+ `
+ }).join('');
+
+ const accomodationsHtml = accomodationDetails ?
+ `
+
${accomodationDetails}
+
` : '';
return `
@@ -233,8 +273,8 @@ export async function downloadTripPDF({ trip, days, places, assignments, categor
${day.date ? `${shortDate(day.date, loc)}` : ''}
${cost ? `${cost}` : ''}
- ${itemsHtml}
- `
+ ${accomodationsHtml}${itemsHtml}
+ `
}).join('')
const html = `
@@ -317,6 +357,29 @@ export async function downloadTripPDF({ trip, days, places, assignments, categor
.day-cost { font-size: 9px; font-weight: 600; color: rgba(255,255,255,0.65); }
.day-body { padding: 12px 28px 6px; }
+ /* Accomodation info */
+ .day-accomodations-overview { font-size: 12px; }
+ .day-accomodations { display: flex; flex-direction: row; justify-content: space-between; }
+ .day-accomodations.single { justify-content: center; }
+
+ .day-accomodation {
+ width: 50%;
+ margin:10px;
+ padding:10px;
+ border:2px solid #e2e8f0;
+ border-radius: 12px;
+ justify-content: center;
+ display: flex;
+ flex-direction: column;
+ }
+
+ .day-accomodation-action {
+ font-size: 18px;
+ font-weight: 600;
+ text-align: center;
+ margin-bottom: 4px;
+ }
+
/* ── Place card ────────────────────────────────── */
.place-card {
display: flex; align-items: stretch;