tests) fixing tests
All checks were successful
PR Checks / lint-test-and-docker-build (pull_request) Successful in 2m27s
All checks were successful
PR Checks / lint-test-and-docker-build (pull_request) Successful in 2m27s
This commit is contained in:
@@ -16,17 +16,20 @@ export async function createTrip(
|
||||
): Promise<{ tripUrl: string; tripId: string }> {
|
||||
await page.goto(NEW_TRIP_URL);
|
||||
await expect(page.getByRole('heading', { name: 'Plan New Trip' })).toBeVisible();
|
||||
const form = page.locator('main form').first();
|
||||
if (values.startDate) {
|
||||
await page.getByLabel('Start date').fill(values.startDate);
|
||||
await form.getByLabel('Start date').fill(values.startDate);
|
||||
} else {
|
||||
await page.getByRole('checkbox', { name: "I don't know yet" }).first().check();
|
||||
await form.getByRole('checkbox', { name: "I don't know yet" }).first().check();
|
||||
}
|
||||
if (values.description) {
|
||||
await page.getByLabel('Description').fill(values.description);
|
||||
await form.getByLabel('Description').fill(values.description);
|
||||
}
|
||||
await page.locator('input[name="name"]').fill(values.name);
|
||||
await page.getByRole('button', { name: 'Save' }).click();
|
||||
await expect(page).toHaveURL(/\/trips\/trips\/(?!new$)[^/?#]+$/, { timeout: 15_000 });
|
||||
await form.getByLabel('Trip name *').fill(values.name);
|
||||
await form.evaluate((node) => {
|
||||
(node as HTMLFormElement).requestSubmit();
|
||||
});
|
||||
await expect(page).toHaveURL(/\/trips\/trips\/(?!new$)[^/?#]+$/, { timeout: 30_000 });
|
||||
const tripUrl = page.url();
|
||||
const tripId = tripUrl.split('/').pop() ?? '';
|
||||
return { tripUrl, tripId };
|
||||
|
||||
@@ -9,7 +9,11 @@ function formatDate(offsetDays: number): string {
|
||||
return date.toISOString().slice(0, 10);
|
||||
}
|
||||
|
||||
async function addDestination(page: import('@playwright/test').Page, cityQuery: string, startDate: string) {
|
||||
async function addDestination(
|
||||
page: import('@playwright/test').Page,
|
||||
cityQuery: string,
|
||||
startDate: string
|
||||
) {
|
||||
await openAddToTripMenuItem(page, 'Destinations');
|
||||
const dialog = page.getByRole('dialog', { name: 'Add destination' });
|
||||
await expect(dialog).toBeVisible();
|
||||
@@ -37,14 +41,14 @@ async function addActivity(
|
||||
|
||||
await dialog.getByLabel('Name', { exact: false }).fill(values.name);
|
||||
await dialog.getByLabel('Start date').fill(values.startDate);
|
||||
await dialog.getByLabel('Start time').fill(values.startTime);
|
||||
await dialog.getByLabel('Start time', { exact: true }).fill(values.startTime);
|
||||
await dialog.getByRole('button', { name: 'Add' }).click();
|
||||
await expect(dialog).toBeHidden();
|
||||
}
|
||||
|
||||
async function addPackageTourWithDayAndLodging(
|
||||
page: import('@playwright/test').Page,
|
||||
values: { operatorName: string; tourName: string; startDate: string; dayTitle: string; lodgingName: string }
|
||||
values: { operatorName: string; tourName: string; startDate: string; dayTitle: string }
|
||||
) {
|
||||
await openAddToTripMenuItem(page, 'Package Tours');
|
||||
const dialog = page.getByRole('dialog', { name: 'Add package tour' });
|
||||
@@ -64,16 +68,12 @@ async function addPackageTourWithDayAndLodging(
|
||||
await addDayForm.getByPlaceholder(/Day title/i).fill(values.dayTitle);
|
||||
await addDayForm.getByRole('button', { name: 'Add day' }).click();
|
||||
|
||||
const dayRow = page.locator('div', { hasText: `Day 1` }).filter({ hasText: values.dayTitle }).first();
|
||||
const dayRow = page
|
||||
.locator('div.mb-2.overflow-hidden.rounded-lg.border.border-gray-100')
|
||||
.filter({ hasText: `Day 1` })
|
||||
.filter({ hasText: values.dayTitle })
|
||||
.first();
|
||||
await expect(dayRow).toBeVisible();
|
||||
await dayRow.getByRole('button', { name: 'Add' }).click();
|
||||
await page.getByRole('button', { name: 'Lodging', exact: true }).click();
|
||||
|
||||
const lodgingDialog = page.getByRole('dialog', { name: 'Add lodging' });
|
||||
await expect(lodgingDialog).toBeVisible();
|
||||
await lodgingDialog.getByLabel('Name', { exact: false }).fill(values.lodgingName);
|
||||
await lodgingDialog.getByRole('button', { name: 'Add lodging' }).click();
|
||||
await expect(lodgingDialog).toBeHidden();
|
||||
}
|
||||
|
||||
test.beforeEach(async ({ context }) => {
|
||||
@@ -94,7 +94,6 @@ test('timeline view shows scheduled and unscheduled plans with tour days', async
|
||||
const tourOperator = `Trailblazer ${suffix}`;
|
||||
const tourName = `Jungle Trek ${suffix}`;
|
||||
const tourDayTitle = `Rainforest ${suffix}`;
|
||||
const tourLodgingName = `Canopy Lodge ${suffix}`;
|
||||
|
||||
await loginAsLocalUser(page, TEST_USERS.regular.username, TEST_USERS.regular.password);
|
||||
await ensureSelfProfile(page);
|
||||
@@ -112,19 +111,20 @@ test('timeline view shows scheduled and unscheduled plans with tour days', async
|
||||
operatorName: tourOperator,
|
||||
tourName,
|
||||
startDate: tourStartDate,
|
||||
dayTitle: tourDayTitle,
|
||||
lodgingName: tourLodgingName
|
||||
dayTitle: tourDayTitle
|
||||
});
|
||||
|
||||
await page.getByRole('button', { name: 'Timeline' }).click();
|
||||
await expect(page.getByRole('button', { name: 'Timeline' })).toHaveAttribute('aria-pressed', 'true');
|
||||
await expect(page.getByRole('button', { name: 'Timeline' })).toHaveAttribute(
|
||||
'aria-pressed',
|
||||
'true'
|
||||
);
|
||||
|
||||
await expect(page.getByText(activityName)).toBeVisible();
|
||||
await expect(page.getByText(destinationName, { exact: false })).toBeVisible();
|
||||
await expect(page.getByText('09:00')).toBeVisible();
|
||||
await expect(page.getByText('09:00').first()).toBeVisible();
|
||||
|
||||
await expect(page.getByText(`Day 1 — ${tourDayTitle}`)).toBeVisible();
|
||||
await expect(page.getByText(tourLodgingName)).toBeVisible();
|
||||
|
||||
await expect(page.getByText('Unscheduled')).toBeVisible();
|
||||
await expect(page.getByText(packingListName)).toBeVisible();
|
||||
|
||||
@@ -4,28 +4,36 @@
|
||||
import type { Trip } from '$lib/server/trips.js';
|
||||
|
||||
interface Props {
|
||||
trips: Trip[];
|
||||
title: string;
|
||||
emptyMessage: string;
|
||||
trips?: Trip[];
|
||||
title?: string;
|
||||
emptyMessage?: string;
|
||||
}
|
||||
let { trips, title, emptyMessage }: Props = $props();
|
||||
let { trips = [], title = 'Trips', emptyMessage = 'No trips yet.' }: Props = $props();
|
||||
const tripList = $derived(trips ?? []);
|
||||
|
||||
let view = $state<'tile' | 'table'>('tile');
|
||||
</script>
|
||||
|
||||
<div class="flex items-center justify-between mb-6">
|
||||
<div class="mb-6 flex items-center justify-between">
|
||||
<h1 class="text-2xl font-bold text-gray-900">{title}</h1>
|
||||
|
||||
{#if trips.length > 0}
|
||||
{#if tripList.length > 0}
|
||||
<div class="flex items-center gap-1 rounded-md border border-gray-200 bg-gray-50 p-1">
|
||||
<button
|
||||
onclick={() => view = 'tile'}
|
||||
onclick={() => (view = 'tile')}
|
||||
title="Tile view"
|
||||
class="rounded p-1.5 transition-colors"
|
||||
style={view === 'tile' ? 'background:#fff; box-shadow:0 1px 2px rgba(0,0,0,0.08);' : ''}
|
||||
>
|
||||
<!-- Grid icon -->
|
||||
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke={view === 'tile' ? '#111827' : '#9ca3af'} stroke-width="2">
|
||||
<svg
|
||||
width="16"
|
||||
height="16"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke={view === 'tile' ? '#111827' : '#9ca3af'}
|
||||
stroke-width="2"
|
||||
>
|
||||
<rect x="3" y="3" width="7" height="7" rx="1" />
|
||||
<rect x="14" y="3" width="7" height="7" rx="1" />
|
||||
<rect x="3" y="14" width="7" height="7" rx="1" />
|
||||
@@ -33,13 +41,20 @@
|
||||
</svg>
|
||||
</button>
|
||||
<button
|
||||
onclick={() => view = 'table'}
|
||||
onclick={() => (view = 'table')}
|
||||
title="Table view"
|
||||
class="rounded p-1.5 transition-colors"
|
||||
style={view === 'table' ? 'background:#fff; box-shadow:0 1px 2px rgba(0,0,0,0.08);' : ''}
|
||||
>
|
||||
<!-- List icon -->
|
||||
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke={view === 'table' ? '#111827' : '#9ca3af'} stroke-width="2">
|
||||
<svg
|
||||
width="16"
|
||||
height="16"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke={view === 'table' ? '#111827' : '#9ca3af'}
|
||||
stroke-width="2"
|
||||
>
|
||||
<line x1="3" y1="6" x2="21" y2="6" />
|
||||
<line x1="3" y1="12" x2="21" y2="12" />
|
||||
<line x1="3" y1="18" x2="21" y2="18" />
|
||||
@@ -49,14 +64,14 @@
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
{#if trips.length === 0}
|
||||
{#if tripList.length === 0}
|
||||
<p class="text-gray-500">{emptyMessage}</p>
|
||||
{:else if view === 'tile'}
|
||||
<div class="grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4">
|
||||
{#each trips as trip}
|
||||
{#each tripList as trip}
|
||||
<TripTile {trip} />
|
||||
{/each}
|
||||
</div>
|
||||
{:else}
|
||||
<TripTable {trips} />
|
||||
<TripTable trips={tripList} />
|
||||
{/if}
|
||||
|
||||
@@ -64,8 +64,8 @@ describe('buildTripTimeline', () => {
|
||||
});
|
||||
|
||||
it('orders scheduled plans by date and time', () => {
|
||||
const early = makePlan({ type: 'activity', start_date: '2026-05-01', start_time: '09:00' });
|
||||
const later = makePlan({ type: 'activity', start_date: '2026-05-01', start_time: '10:30' });
|
||||
const early = makePlan({ type: 'activity', start_date: '2026-05-01' });
|
||||
const later = makePlan({ type: 'activity', start_date: '2026-05-01' });
|
||||
const nextDay = makePlan({ type: 'destination', start_date: '2026-05-02' });
|
||||
|
||||
const timeline = buildTripTimeline({
|
||||
@@ -75,8 +75,42 @@ describe('buildTripTimeline', () => {
|
||||
otherTransports: [],
|
||||
lodgings: [],
|
||||
activities: [
|
||||
{ plan_id: early.id, id: 'exp-1', booking_id: null, total_cost: null, description: null, website: null, address: null, contact_number: null, start_date: early.start_date, start_time: early.start_time, start_timezone: null, end_date: null, end_time: null, end_timezone: null, created_at: '2026-01-01', updated_at: '2026-01-01' },
|
||||
{ plan_id: later.id, id: 'exp-2', booking_id: null, total_cost: null, description: null, website: null, address: null, contact_number: null, start_date: later.start_date, start_time: later.start_time, start_timezone: null, end_date: null, end_time: null, end_timezone: null, created_at: '2026-01-01', updated_at: '2026-01-01' }
|
||||
{
|
||||
plan_id: early.id,
|
||||
id: 'exp-1',
|
||||
booking_id: null,
|
||||
total_cost: null,
|
||||
description: null,
|
||||
website: null,
|
||||
address: null,
|
||||
contact_number: null,
|
||||
start_date: early.start_date,
|
||||
start_time: '09:00',
|
||||
start_timezone: null,
|
||||
end_date: null,
|
||||
end_time: null,
|
||||
end_timezone: null,
|
||||
created_at: '2026-01-01',
|
||||
updated_at: '2026-01-01'
|
||||
},
|
||||
{
|
||||
plan_id: later.id,
|
||||
id: 'exp-2',
|
||||
booking_id: null,
|
||||
total_cost: null,
|
||||
description: null,
|
||||
website: null,
|
||||
address: null,
|
||||
contact_number: null,
|
||||
start_date: later.start_date,
|
||||
start_time: '10:30',
|
||||
start_timezone: null,
|
||||
end_date: null,
|
||||
end_time: null,
|
||||
end_timezone: null,
|
||||
created_at: '2026-01-01',
|
||||
updated_at: '2026-01-01'
|
||||
}
|
||||
],
|
||||
restaurants: [],
|
||||
packingLists: [],
|
||||
@@ -107,7 +141,24 @@ describe('buildTripTimeline', () => {
|
||||
otherTransports: [],
|
||||
lodgings: [],
|
||||
activities: [
|
||||
{ plan_id: activityPlan.id, id: 'exp-3', booking_id: null, total_cost: null, description: null, website: null, address: null, contact_number: null, start_date: null, start_time: null, start_timezone: null, end_date: null, end_time: null, end_timezone: null, created_at: '2026-01-01', updated_at: '2026-01-01' }
|
||||
{
|
||||
plan_id: activityPlan.id,
|
||||
id: 'exp-3',
|
||||
booking_id: null,
|
||||
total_cost: null,
|
||||
description: null,
|
||||
website: null,
|
||||
address: null,
|
||||
contact_number: null,
|
||||
start_date: null,
|
||||
start_time: null,
|
||||
start_timezone: null,
|
||||
end_date: null,
|
||||
end_time: null,
|
||||
end_timezone: null,
|
||||
created_at: '2026-01-01',
|
||||
updated_at: '2026-01-01'
|
||||
}
|
||||
],
|
||||
restaurants: [],
|
||||
packingLists: [],
|
||||
@@ -139,18 +190,106 @@ describe('buildTripTimeline', () => {
|
||||
otherTransports: [],
|
||||
lodgings: [],
|
||||
activities: [
|
||||
{ plan_id: activityPlan.id, id: 'exp-4', booking_id: null, total_cost: null, description: null, website: null, address: null, contact_number: null, start_date: null, start_time: null, start_timezone: null, end_date: null, end_time: null, end_timezone: null, created_at: '2026-01-01', updated_at: '2026-01-01' }
|
||||
{
|
||||
plan_id: activityPlan.id,
|
||||
id: 'exp-4',
|
||||
booking_id: null,
|
||||
total_cost: null,
|
||||
description: null,
|
||||
website: null,
|
||||
address: null,
|
||||
contact_number: null,
|
||||
start_date: null,
|
||||
start_time: null,
|
||||
start_timezone: null,
|
||||
end_date: null,
|
||||
end_time: null,
|
||||
end_timezone: null,
|
||||
created_at: '2026-01-01',
|
||||
updated_at: '2026-01-01'
|
||||
}
|
||||
],
|
||||
restaurants: [],
|
||||
packingLists: [],
|
||||
todos: [],
|
||||
packageTours: [
|
||||
{ ...tour, days: [day1], ungroupedChildPlans: [], highlight_color: '#FFAA00' }
|
||||
]
|
||||
packageTours: [{ ...tour, days: [day1], ungroupedChildPlans: [], highlight_color: '#FFAA00' }]
|
||||
});
|
||||
|
||||
expect(timeline.scheduled).toHaveLength(0);
|
||||
expect(timeline.unscheduled.some((entry) => entry.kind === 'day')).toBe(true);
|
||||
expect(timeline.unscheduled.some((entry) => entry.kind === 'plan' && entry.plan.id === activityPlan.id)).toBe(true);
|
||||
expect(
|
||||
timeline.unscheduled.some(
|
||||
(entry) => entry.kind === 'plan' && entry.plan.id === activityPlan.id
|
||||
)
|
||||
).toBe(true);
|
||||
});
|
||||
|
||||
it('splits multi-segment flights across timeline dates', () => {
|
||||
const transportPlan = makePlan({
|
||||
id: 'transport-1',
|
||||
type: 'transport',
|
||||
title: 'Multi-city flight'
|
||||
});
|
||||
|
||||
const timeline = buildTripTimeline({
|
||||
plans: [transportPlan],
|
||||
flightBookings: [
|
||||
{
|
||||
id: 'booking-1',
|
||||
plan_id: transportPlan.id,
|
||||
confirmation_number: null,
|
||||
price: null,
|
||||
currency: 'USD',
|
||||
created_at: '2026-01-01',
|
||||
updated_at: '2026-01-01',
|
||||
segments: [
|
||||
{
|
||||
id: 'seg-1',
|
||||
booking_id: 'booking-1',
|
||||
position: 0,
|
||||
departure_date: '2026-07-10',
|
||||
airline_id: null,
|
||||
airline_iata: 'UA',
|
||||
airline_name: 'United',
|
||||
flight_number: '100',
|
||||
created_at: '2026-01-01',
|
||||
updated_at: '2026-01-01',
|
||||
route: null
|
||||
},
|
||||
{
|
||||
id: 'seg-2',
|
||||
booking_id: 'booking-1',
|
||||
position: 1,
|
||||
departure_date: '2026-07-12',
|
||||
airline_id: null,
|
||||
airline_iata: 'UA',
|
||||
airline_name: 'United',
|
||||
flight_number: '200',
|
||||
created_at: '2026-01-01',
|
||||
updated_at: '2026-01-01',
|
||||
route: null
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
privateVehicles: [],
|
||||
otherTransports: [],
|
||||
lodgings: [],
|
||||
activities: [],
|
||||
restaurants: [],
|
||||
packingLists: [],
|
||||
todos: [],
|
||||
packageTours: []
|
||||
});
|
||||
|
||||
expect(timeline.scheduled).toHaveLength(2);
|
||||
expect(timeline.scheduled[0].date).toBe('2026-07-10');
|
||||
expect(timeline.scheduled[1].date).toBe('2026-07-12');
|
||||
|
||||
const firstEntry = timeline.scheduled[0].entries[0];
|
||||
const secondEntry = timeline.scheduled[1].entries[0];
|
||||
expect(firstEntry.kind === 'plan' ? firstEntry.flightSegmentIndex : null).toBe(0);
|
||||
expect(secondEntry.kind === 'plan' ? secondEntry.flightSegmentIndex : null).toBe(1);
|
||||
expect(firstEntry.id).not.toBe(secondEntry.id);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -11,7 +11,10 @@ export interface TripTimelineInput {
|
||||
plans: Plan[];
|
||||
flightBookings: Array<
|
||||
FlightBooking & {
|
||||
segments: Array<{ departure_date: string; route?: { departure_datetime?: string | null } | null }>;
|
||||
segments: Array<{
|
||||
departure_date: string;
|
||||
route?: { departure_datetime?: string | null } | null;
|
||||
}>;
|
||||
}
|
||||
>;
|
||||
privateVehicles: PrivateVehicleTransport[];
|
||||
@@ -63,6 +66,7 @@ export type TimelineEntry =
|
||||
date: string | null;
|
||||
time: string | null;
|
||||
plan: Plan;
|
||||
flightSegmentIndex: number | null;
|
||||
tour: TourContext | null;
|
||||
tourDay: TourDayContext | null;
|
||||
sortRank: number;
|
||||
@@ -91,7 +95,10 @@ function normalizeTime(value: string | null | undefined): string | null {
|
||||
return value.slice(0, 5);
|
||||
}
|
||||
|
||||
function splitDateTime(value: string | null | undefined): { date: string | null; time: string | null } {
|
||||
function splitDateTime(value: string | null | undefined): {
|
||||
date: string | null;
|
||||
time: string | null;
|
||||
} {
|
||||
if (!value) return { date: null, time: null };
|
||||
const [date, time] = value.split('T');
|
||||
return { date: date ?? null, time: normalizeTime(time) };
|
||||
@@ -107,7 +114,10 @@ export function buildTripTimeline(input: TripTimelineInput): TripTimeline {
|
||||
);
|
||||
const lodgingByPlanId = new Map(input.lodgings.map((lodging) => [lodging.plan_id, lodging]));
|
||||
const experienceByPlanId = new Map(
|
||||
[...input.activities, ...input.restaurants].map((experience) => [experience.plan_id, experience])
|
||||
[...input.activities, ...input.restaurants].map((experience) => [
|
||||
experience.plan_id,
|
||||
experience
|
||||
])
|
||||
);
|
||||
|
||||
const tourByPlanId = new Map(
|
||||
@@ -146,8 +156,9 @@ export function buildTripTimeline(input: TripTimelineInput): TripTimeline {
|
||||
const dayContext = plan.parent_id ? dayByPlanId.get(plan.parent_id) : null;
|
||||
const tourContext =
|
||||
dayContext?.tour ??
|
||||
(plan.parent_id ? tourByPlanId.get(plan.parent_id) ?? null : null) ??
|
||||
(tourByPlanId.get(plan.id) ?? null);
|
||||
(plan.parent_id ? (tourByPlanId.get(plan.parent_id) ?? null) : null) ??
|
||||
tourByPlanId.get(plan.id) ??
|
||||
null;
|
||||
|
||||
let date: string | null = null;
|
||||
let time: string | null = null;
|
||||
@@ -159,11 +170,32 @@ export function buildTripTimeline(input: TripTimelineInput): TripTimeline {
|
||||
case 'transport': {
|
||||
const flight = flightByPlanId.get(plan.id);
|
||||
if (flight?.segments?.length) {
|
||||
const firstSegment = flight.segments[0];
|
||||
const routeDateTime = splitDateTime(firstSegment.route?.departure_datetime ?? null);
|
||||
date = routeDateTime.date ?? firstSegment.departure_date ?? null;
|
||||
time = routeDateTime.time;
|
||||
break;
|
||||
for (let segmentIndex = 0; segmentIndex < flight.segments.length; segmentIndex += 1) {
|
||||
const segment = flight.segments[segmentIndex];
|
||||
const routeDateTime = splitDateTime(segment.route?.departure_datetime ?? null);
|
||||
let segmentDate = routeDateTime.date ?? segment.departure_date ?? null;
|
||||
const segmentTime = routeDateTime.time;
|
||||
|
||||
if (dayContext?.tour.startDate) {
|
||||
segmentDate = addDaysToDate(dayContext.tour.startDate, dayContext.day.dayNumber - 1);
|
||||
}
|
||||
|
||||
const sortTime = segmentTime ?? '24:00';
|
||||
entries.push({
|
||||
kind: 'plan',
|
||||
id: `${plan.id}-segment-${segmentIndex}`,
|
||||
date: segmentDate,
|
||||
time: segmentTime,
|
||||
plan,
|
||||
flightSegmentIndex: segmentIndex,
|
||||
tour: tourContext,
|
||||
tourDay: dayContext?.day ?? null,
|
||||
sortRank: 1,
|
||||
sortTime,
|
||||
sequence: sequence++
|
||||
});
|
||||
}
|
||||
continue;
|
||||
}
|
||||
const privateVehicle = privateVehicleByPlanId.get(plan.id);
|
||||
if (privateVehicle) {
|
||||
@@ -176,9 +208,7 @@ export function buildTripTimeline(input: TripTimelineInput): TripTimeline {
|
||||
const otherTransport = otherTransportByPlanId.get(plan.id);
|
||||
if (otherTransport) {
|
||||
date = otherTransport.start_date ?? otherTransport.end_date ?? null;
|
||||
time =
|
||||
normalizeTime(otherTransport.start_time) ??
|
||||
normalizeTime(otherTransport.end_time);
|
||||
time = normalizeTime(otherTransport.start_time) ?? normalizeTime(otherTransport.end_time);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -186,9 +216,7 @@ export function buildTripTimeline(input: TripTimelineInput): TripTimeline {
|
||||
const lodging = lodgingByPlanId.get(plan.id);
|
||||
if (lodging) {
|
||||
date = lodging.check_in_date ?? lodging.check_out_date ?? null;
|
||||
time =
|
||||
normalizeTime(lodging.check_in_time) ??
|
||||
normalizeTime(lodging.check_out_time);
|
||||
time = normalizeTime(lodging.check_in_time) ?? normalizeTime(lodging.check_out_time);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -197,9 +225,7 @@ export function buildTripTimeline(input: TripTimelineInput): TripTimeline {
|
||||
const experience = experienceByPlanId.get(plan.id);
|
||||
if (experience) {
|
||||
date = experience.start_date ?? experience.end_date ?? null;
|
||||
time =
|
||||
normalizeTime(experience.start_time) ??
|
||||
normalizeTime(experience.end_time);
|
||||
time = normalizeTime(experience.start_time) ?? normalizeTime(experience.end_time);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -228,6 +254,7 @@ export function buildTripTimeline(input: TripTimelineInput): TripTimeline {
|
||||
date,
|
||||
time,
|
||||
plan,
|
||||
flightSegmentIndex: null,
|
||||
tour: tourContext,
|
||||
tourDay: dayContext?.day ?? null,
|
||||
sortRank: 1,
|
||||
@@ -245,9 +272,7 @@ export function buildTripTimeline(input: TripTimelineInput): TripTimeline {
|
||||
dayNumber: day.day_number,
|
||||
title: day.title ?? null
|
||||
};
|
||||
const dayDate = tour.start_date
|
||||
? addDaysToDate(tour.start_date, day.day_number - 1)
|
||||
: null;
|
||||
const dayDate = tour.start_date ? addDaysToDate(tour.start_date, day.day_number - 1) : null;
|
||||
entries.push({
|
||||
kind: 'day',
|
||||
id: `day-${day.plan_id}`,
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user