mirror of
https://github.com/mauriceboe/TREK.git
synced 2026-10-18 21:16:47 +00:00
feat(api): expose shortlisted places, detached bookings and the bucket list
Reading the surface back against real data turned up three things it dropped without saying so. Places with no day were invisible, because the payload only reached places through day_assignments. On a live instance that is half of them, and they are the ones carrying a coordinate and no claim about when — exactly what an integration can act on. They come back under `unplanned_places`, minus the hotel, which is already reported as an accommodation. Bookings with no day were dropped by the day filter. reservations.day_id is nullable and deleting a day detaches its bookings rather than removing them, so this is not a hypothetical. The bucket list had no endpoint at all. It hangs off the user rather than a trip, so it gets its own, and it answers whether or not the Atlas addon is switched on: the addon decides what TREK shows, not what a key can read. Also fixes ?include=notes returning the bare trip: places, notes and reservations are reported on days, so asking for one now implies days instead of quietly answering with nothing. The module stays a leaf. Reaching for AtlasService pulled AuthModule and the storage registry in behind it and broke the surface's own boot, so the one SELECT lives here like every other query in the file.
This commit is contained in:
@@ -106,6 +106,32 @@ export const publicApiTravellerSchema = z.object({
|
||||
});
|
||||
export type PublicApiTraveller = z.infer<typeof publicApiTravellerSchema>;
|
||||
|
||||
/**
|
||||
* An entry on the traveller's bucket list: somewhere they want to go, with no
|
||||
* trip attached yet.
|
||||
*
|
||||
* Lives on the user rather than on a trip, which is why it has its own endpoint
|
||||
* rather than an `include`. It is the one part of TREK that is explicitly about
|
||||
* places not yet visited, so a consumer that knows where someone actually went
|
||||
* can tell them they got there.
|
||||
*/
|
||||
export const publicApiBucketListItemSchema = z.object({
|
||||
name: z.string(),
|
||||
lat: z.number().nullable(),
|
||||
lng: z.number().nullable(),
|
||||
/** ISO 3166-1 alpha-2, when the entry is pinned to a country. */
|
||||
country_code: z.string().nullable(),
|
||||
notes: z.string().nullable(),
|
||||
/** An optional date the traveller is aiming for. Not a booking. */
|
||||
target_date: z.string().nullable(),
|
||||
});
|
||||
export type PublicApiBucketListItem = z.infer<typeof publicApiBucketListItemSchema>;
|
||||
|
||||
export const publicApiBucketListSchema = z.object({
|
||||
items: z.array(publicApiBucketListItemSchema),
|
||||
});
|
||||
export type PublicApiBucketList = z.infer<typeof publicApiBucketListSchema>;
|
||||
|
||||
/** Trip without its itinerary — what the list endpoint returns. */
|
||||
export const publicApiTripSummarySchema = z.object({
|
||||
id: z.number(),
|
||||
@@ -136,6 +162,24 @@ export const publicApiTripSchema = publicApiTripSummarySchema.extend({
|
||||
days: z.array(publicApiDaySchema).optional(),
|
||||
accommodations: z.array(publicApiAccommodationSchema).optional(),
|
||||
travellers: z.array(publicApiTravellerSchema).optional(),
|
||||
/**
|
||||
* Places on the trip that sit on no day yet — the shortlist a traveller
|
||||
* collects before deciding when to go where.
|
||||
*
|
||||
* Comes with `include=places`, because a section called "places" that silently
|
||||
* omitted half of them would be worse than one that did not exist. On a real
|
||||
* instance these are routinely half of a trip's places, and they carry the
|
||||
* coordinates that make them worth matching against.
|
||||
*/
|
||||
unplanned_places: z.array(publicApiPlaceSchema).optional(),
|
||||
/**
|
||||
* Bookings not pinned to a day. A reservation keeps its `day_id` as a nullable
|
||||
* reference, and deleting a day sets it null rather than deleting the booking,
|
||||
* so these exist in the wild and are not an edge case.
|
||||
*
|
||||
* Comes with `include=reservations`, for the same reason as above.
|
||||
*/
|
||||
unscheduled_reservations: z.array(publicApiReservationSchema).optional(),
|
||||
});
|
||||
export type PublicApiTrip = z.infer<typeof publicApiTripSchema>;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user