fix(pdf): clean up accommodation rendering in trip PDF

- Remove duplicate icon display on check-in/check-out time row
- Remove hardcoded 'N/A' fallback, show time only when available
- Fix inconsistent indentation and variable naming
- Add flex-wrap to accommodation layout for 3+ accommodations per day
- Use icon-per-call instead of pre-cached variables for clarity
This commit is contained in:
mauriceboe
2026-04-04 17:53:03 +02:00
parent c8421eb1fc
commit b26023e32a

View File

@@ -238,51 +238,39 @@ export async function downloadTripPDF({ trip, days, places, assignments, categor
</div>` </div>`
}).join('') }).join('')
const accommodationsForDay = accommodations.accommodations?.filter(a => const accommodationsForDay = (accommodations.accommodations || []).filter(a =>
days.some(d => d.id >= a.start_day_id && d.id <= a.end_day_id && d.id === day?.id) 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); ).sort((a, b) => a.start_day_id - b.start_day_id)
//Const icons for accommodation actions and details const accommodationDetails = accommodationsForDay.map(item => {
const ICON_ACC_CHECKIN = accommodationIconSvg('checkin'); const isCheckIn = day.id === item.start_day_id
const ICON_ACC_CHECKOUT = accommodationIconSvg('checkout'); const isCheckOut = day.id === item.end_day_id
const ICON_ACC_LOCATION = accommodationIconSvg('location'); const actionLabel = isCheckIn ? tr('reservations.meta.checkIn')
const ICON_ACC_NOTE = accommodationIconSvg('note'); : isCheckOut ? tr('reservations.meta.checkOut')
const ICON_ACC_CONFIRMATION = accommodationIconSvg('confirmation'); : tr('reservations.meta.linkAccommodation')
const ICON_ACC_ACCOMMODATION = accommodationIconSvg('accommodation'); const actionIcon = isCheckIn ? accommodationIconSvg('checkin')
: isCheckOut ? accommodationIconSvg('checkout')
const accommodationDetails = accommodationsForDay.map(item => { : accommodationIconSvg('accommodation')
const timeStr = isCheckIn ? (item.check_in || '')
const isCheckIn = day.id === item.start_day_id; : isCheckOut ? (item.check_out || '')
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 ? ICON_ACC_CHECKIN
: isCheckOut ? ICON_ACC_CHECKOUT
: ICON_ACC_ACCOMMODATION
const accomoTime = isCheckIn ? item.check_in || 'N/A'
: isCheckOut ? item.check_out || 'N/A'
: ''
return ` return `
<div class="day-accommodation"> <div class="day-accommodation">
<div class="day-accommodation-title accommodation-center-icon" >${accomoEmoji} ${escHtml(accomoAction)}</div> <div class="day-accommodation-title accommodation-center-icon">${actionIcon} ${escHtml(actionLabel)}</div>
${accomoTime ? `<div class="accommodation-center-icon">${accomoEmoji} <b>${accomoTime}</b></div>` : ''} ${timeStr ? `<div class="accommodation-center-icon">${accommodationIconSvg('checkin')} <b>${escHtml(timeStr)}</b></div>` : ''}
<div class="accommodation-center-icon">${accommodationIconSvg('accommodation')} ${escHtml(item.place_name)}</div>
${item.place_address ? `<div class="accommodation-center-icon">${accommodationIconSvg('location')} ${escHtml(item.place_address)}</div>` : ''}
${item.notes ? `<div class="accommodation-center-icon">${accommodationIconSvg('note')} ${escHtml(item.notes)}</div>` : ''}
${isCheckIn && item.confirmation ? `<div class="accommodation-center-icon">${accommodationIconSvg('confirmation')} ${escHtml(item.confirmation)}</div>` : ''}
</div>`
}).join('')
<div class="accommodation-center-icon">${ICON_ACC_ACCOMMODATION} ${escHtml(item.place_name)}</div> const accommodationsHtml = accommodationsForDay.length > 0
${item.place_address ? `<div class="accommodation-center-icon">${ICON_ACC_LOCATION} ${escHtml(item.place_address)}</div>` : ''} ? `<div class="day-accommodations-overview">
${item.notes ? `<div class="accommodation-center-icon">${ICON_ACC_NOTE} ${escHtml(item.notes)}</div>` : ''} <div class="day-accommodations ${accommodationsForDay.length === 1 ? 'single' : ''}">${accommodationDetails}</div>
${isCheckIn && item.confirmation ? `<div class="accommodation-center-icon">${ICON_ACC_CONFIRMATION} ${escHtml(item.confirmation)}</div>` : ''} </div>`
</div> : ''
`
}).join('');
const accommodationsHtml = accommodationDetails ?
`<div class="day-accommodations-overview">
<div class="day-accommodations ${accommodationsForDay.length === 1 ? 'single' : ''}">${accommodationDetails}</div>
</div>` : '';
return ` return `
<div class="day-section${di > 0 ? ' page-break' : ''}"> <div class="day-section${di > 0 ? ' page-break' : ''}">
@@ -377,38 +365,20 @@ export async function downloadTripPDF({ trip, days, places, assignments, categor
.day-body { padding: 12px 28px 6px; } .day-body { padding: 12px 28px 6px; }
/* accommodation info */ /* accommodation info */
.day-accommodations-overview { font-size: 12px; } .day-accommodations-overview { font-size: 12px; }
.day-accommodations { display: flex; flex-direction: row; justify-content: space-between; } .day-accommodations { display: flex; flex-wrap: wrap; gap: 8px; justify-content: space-between; }
.day-accommodations.single { justify-content: center; } .day-accommodations.single { justify-content: center; }
.day-accommodation {
.day-accommodation { flex: 1 1 45%; min-width: 200px; margin: 4px 0; padding: 10px;
width: 50%; border: 2px solid #e2e8f0; border-radius: 12px;
margin:10px; display: flex; flex-direction: column;
padding:10px;
border:2px solid #e2e8f0;
border-radius: 12px;
justify-content: center;
display: flex;
flex-direction: column;
} }
.day-accommodation-title { .day-accommodation-title {
font-size: 18px; font-size: 16px; font-weight: 600; text-align: center;
font-weight: 600; margin-bottom: 4px; align-self: center;
text-align: center;
margin-bottom: 4px;
align-self: center;
} }
.accommodation-center-icon { display: flex; align-items: center; gap: 4px; }
.accommodation-center-icon {
display: flex;
align-items: center;
}
.accommodation-icon {
margin-right: 4px;
}
/* ── Place card ────────────────────────────────── */ /* ── Place card ────────────────────────────────── */
.place-card { .place-card {