mirror of
https://github.com/mauriceboe/TREK.git
synced 2026-10-19 05:26:47 +00:00
7ee8333aeb
Thirteen interfaces nobody imported are gone. Trip is now the selectable row of the generated TripsTable, so currency, is_archived and reminder_days read as the nullable columns they are and feed_token and reminder_sent_for exist.
345 lines
9.7 KiB
TypeScript
345 lines
9.7 KiB
TypeScript
import type { Selectable } from 'kysely';
|
|
|
|
import type { TripsTable } from './db/kysely/Trips.table';
|
|
|
|
export interface User {
|
|
id: number;
|
|
username: string;
|
|
email: string;
|
|
role: 'admin' | 'user';
|
|
password_hash?: string;
|
|
maps_api_key?: string | null;
|
|
unsplash_api_key?: string | null;
|
|
/** Amap (高德) web-service key — the per-user fallback for the Amap provider. */
|
|
amap_api_key?: string | null;
|
|
openweather_api_key?: string | null;
|
|
avatar?: string | null;
|
|
oidc_sub?: string | null;
|
|
oidc_issuer?: string | null;
|
|
last_login?: string | null;
|
|
mfa_enabled?: number | boolean;
|
|
mfa_secret?: string | null;
|
|
mfa_backup_codes?: string | null;
|
|
must_change_password?: number | boolean;
|
|
first_seen_version?: string;
|
|
login_count?: number;
|
|
// Guest members (#1362): accountless trip participants. Flagged guests must never
|
|
// authenticate or appear in the global user directory.
|
|
is_guest?: number | boolean;
|
|
created_at?: string;
|
|
updated_at?: string;
|
|
}
|
|
|
|
/**
|
|
* A trips row as the database holds it, derived from the generated table type
|
|
* so it cannot drift from the schema (currency, is_archived and reminder_days
|
|
* are nullable columns, and feed_token and reminder_sent_for exist).
|
|
*/
|
|
export type Trip = Selectable<TripsTable>;
|
|
|
|
export interface Day {
|
|
id: number;
|
|
trip_id: number;
|
|
day_number: number;
|
|
date?: string | null;
|
|
notes?: string | null;
|
|
title?: string | null;
|
|
default_transport_mode?: string | null;
|
|
}
|
|
|
|
export interface Place {
|
|
id: number;
|
|
trip_id: number;
|
|
name: string;
|
|
description?: string | null;
|
|
lat?: number | null;
|
|
lng?: number | null;
|
|
address?: string | null;
|
|
category_id?: number | null;
|
|
price?: number | null;
|
|
currency?: string | null;
|
|
reservation_status?: string;
|
|
reservation_notes?: string | null;
|
|
reservation_datetime?: string | null;
|
|
place_time?: string | null;
|
|
end_time?: string | null;
|
|
duration_minutes?: number;
|
|
notes?: string | null;
|
|
image_url?: string | null;
|
|
google_place_id?: string | null;
|
|
google_ftid?: string | null;
|
|
osm_id?: string | null;
|
|
amap_poi_id?: string | null;
|
|
route_geometry?: string | null;
|
|
route_color?: string | null;
|
|
website?: string | null;
|
|
phone?: string | null;
|
|
/** Typed in by hand (#2472). */
|
|
email?: string | null;
|
|
/** Hand-kept opening hours as JSON text, seven days Monday first (#2472). */
|
|
opening_hours?: string | null;
|
|
transport_mode?: string;
|
|
/** What kind of stop this is on a drive (#1797); null for an ordinary place. */
|
|
stop_type?: string | null;
|
|
/** How full this stop fills the tank, 1-100; null follows the traveller's own setting. */
|
|
fill_percent?: number | null;
|
|
created_at?: string;
|
|
updated_at?: string;
|
|
}
|
|
|
|
export interface Tag {
|
|
id: number;
|
|
user_id: number;
|
|
name: string;
|
|
color: string;
|
|
created_at?: string;
|
|
}
|
|
|
|
export interface BudgetItemReceipt {
|
|
id: number;
|
|
filename: string;
|
|
original_name: string;
|
|
file_size?: number | null;
|
|
mime_type?: string | null;
|
|
url: string;
|
|
}
|
|
|
|
export interface BudgetItem {
|
|
id: number;
|
|
trip_id: number;
|
|
category: string;
|
|
name: string;
|
|
total_price: number;
|
|
currency?: string | null;
|
|
exchange_rate?: number;
|
|
persons?: number | null;
|
|
days?: number | null;
|
|
note?: string | null;
|
|
/** Itemized receipt for a per-item split, as JSON. Its own column since #1658. */
|
|
ticket_json?: string | null;
|
|
reservation_id?: number | null;
|
|
/** Set when the expense was created from a place (#1298) — the other side of
|
|
* the same link reservation_id is for a booking. */
|
|
place_id?: number | null;
|
|
paid_by_user_id?: number | null;
|
|
expense_date?: string | null;
|
|
sort_order: number;
|
|
created_at?: string;
|
|
members?: BudgetItemMember[];
|
|
payers?: BudgetItemPayer[];
|
|
receipts?: BudgetItemReceipt[];
|
|
}
|
|
|
|
export interface BudgetItemMember {
|
|
user_id: number;
|
|
paid: number;
|
|
username: string;
|
|
avatar_url?: string | null;
|
|
avatar?: string | null;
|
|
budget_item_id?: number;
|
|
amount?: number | null;
|
|
}
|
|
|
|
export interface BudgetItemPayer {
|
|
user_id: number;
|
|
amount: number;
|
|
username?: string;
|
|
avatar_url?: string | null;
|
|
avatar?: string | null;
|
|
budget_item_id?: number;
|
|
}
|
|
|
|
interface ReservationEndpoint {
|
|
id: number;
|
|
reservation_id: number;
|
|
role: 'from' | 'to' | 'stop';
|
|
sequence: number;
|
|
name: string;
|
|
code: string | null;
|
|
lat: number;
|
|
lng: number;
|
|
timezone: string | null;
|
|
local_time: string | null;
|
|
local_date: string | null;
|
|
}
|
|
|
|
export interface Reservation {
|
|
id: number;
|
|
trip_id: number;
|
|
day_id?: number | null;
|
|
end_day_id?: number | null;
|
|
place_id?: number | null;
|
|
assignment_id?: number | null;
|
|
title: string;
|
|
reservation_time?: string | null;
|
|
reservation_end_time?: string | null;
|
|
location?: string | null;
|
|
confirmation_number?: string | null;
|
|
notes?: string | null;
|
|
status: string;
|
|
type: string;
|
|
/**
|
|
* TEXT at the DB, not INTEGER (Plan 3d inventory §18.1 — no FK, some rows
|
|
* read back as `"14.0"`): every reader normalises it, so this stays a
|
|
* string here rather than the genuine INTEGER shape of
|
|
* `day_assignments.accommodation_id`. Do not "fix" this to `number`: that
|
|
* is a different column on a different table.
|
|
*/
|
|
accommodation_id?: string | null;
|
|
metadata?: string | null;
|
|
needs_review?: number;
|
|
endpoints?: ReservationEndpoint[];
|
|
created_at?: string;
|
|
day_number?: number;
|
|
place_name?: string;
|
|
}
|
|
|
|
export interface DayNote {
|
|
id: number;
|
|
day_id: number;
|
|
trip_id: number;
|
|
text: string;
|
|
time?: string | null;
|
|
icon: string;
|
|
/** One of NOTE_COLORS, or null for the neutral card (#1629). */
|
|
color?: string | null;
|
|
sort_order: number;
|
|
created_at?: string;
|
|
}
|
|
|
|
export interface Participant {
|
|
user_id: number;
|
|
username: string;
|
|
avatar?: string | null;
|
|
}
|
|
|
|
// ── Journey addon ─────────────────────────────────────────────────────────
|
|
|
|
export interface Journey {
|
|
id: number;
|
|
user_id: number;
|
|
title: string;
|
|
subtitle?: string | null;
|
|
cover_gradient?: string | null;
|
|
cover_image?: string | null;
|
|
status: 'draft' | 'active' | 'completed' | 'archived';
|
|
/** Draw the linked trips' GPX tracks on this journey's map (#2194). 0 by default. */
|
|
show_trip_tracks?: number;
|
|
/** The state the owner set by hand (#762); null follows the trip dates. */
|
|
status_override?: 'draft' | 'live' | 'completed' | null;
|
|
/** Entries without a place take the spot of their first geotagged photo (#1003). 0 by default. */
|
|
photo_location?: number;
|
|
created_at: number;
|
|
updated_at: number;
|
|
}
|
|
|
|
export interface JourneyEntry {
|
|
id: number;
|
|
journey_id: number;
|
|
source_trip_id?: number | null;
|
|
source_place_id?: number | null;
|
|
/**
|
|
* The `day_assignments` row this entry was derived from (#2329). A place standing
|
|
* on two days is two entries, and only this tells them apart. May dangle: an
|
|
* unassigned stop keeps the id so reconciliation can see the assignment is gone.
|
|
*/
|
|
source_assignment_id?: number | null;
|
|
author_id: number;
|
|
type: 'entry' | 'checkin' | 'skeleton';
|
|
title?: string | null;
|
|
story?: string | null;
|
|
entry_date: string;
|
|
entry_time?: string | null;
|
|
location_name?: string | null;
|
|
location_lat?: number | null;
|
|
location_lng?: number | null;
|
|
mood?: string | null;
|
|
weather?: string | null;
|
|
tags?: string | null;
|
|
pros_cons?: string | null;
|
|
visibility: 'private' | 'shared' | 'public';
|
|
sort_order: number;
|
|
/** ISO 3166-1 alpha-2, resolved from the coordinates when the entry was written. */
|
|
country_code?: string | null;
|
|
/**
|
|
* 0/1 as the row holds it. A suggestion the traveller waved away: the row stays,
|
|
* so the trip sync does not create it again, and every read leaves it out.
|
|
*/
|
|
dismissed: number;
|
|
/**
|
|
* 0/1 as the row holds it. Switched on, the entry stays in the journal but
|
|
* is left out of the route and the figures Studio prints (discussion #2064).
|
|
* The wire carries a boolean; journey-entry-row.ts is where the two meet.
|
|
*/
|
|
stats_excluded: number;
|
|
/** 1 while the entry is a draft (#696), kept off the public share page. */
|
|
is_draft?: number;
|
|
created_at: number;
|
|
updated_at: number;
|
|
}
|
|
|
|
export interface TrekPhoto {
|
|
id: number;
|
|
provider: string;
|
|
asset_id?: string | null;
|
|
owner_id?: number | null;
|
|
file_path?: string | null;
|
|
thumbnail_path?: string | null;
|
|
width?: number | null;
|
|
height?: number | null;
|
|
passphrase?: string | null;
|
|
/** 'image' (default) or 'video' — discriminates how the asset is served/played (#823). */
|
|
media_type?: string | null;
|
|
/** Optional video duration in milliseconds. */
|
|
duration_ms?: number | null;
|
|
/** When the picture was taken, as the provider or its EXIF reported it (#1614). */
|
|
taken_at?: string | null;
|
|
/** Capture coordinates. Stored as a pair or not at all. */
|
|
lat?: number | null;
|
|
lng?: number | null;
|
|
created_at: string;
|
|
}
|
|
|
|
export interface JourneyPhoto {
|
|
id: number;
|
|
entry_id: number;
|
|
photo_id: number;
|
|
caption?: string | null;
|
|
sort_order: number;
|
|
shared: number;
|
|
created_at: number;
|
|
// Joined from trek_photos for API responses
|
|
provider?: string;
|
|
asset_id?: string | null;
|
|
owner_id?: number | null;
|
|
file_path?: string | null;
|
|
thumbnail_path?: string | null;
|
|
width?: number | null;
|
|
height?: number | null;
|
|
}
|
|
|
|
export interface GalleryPhoto {
|
|
id: number;
|
|
journey_id: number;
|
|
photo_id: number;
|
|
caption?: string | null;
|
|
shared: number;
|
|
sort_order: number;
|
|
created_at: number;
|
|
// Joined from trek_photos for API responses
|
|
provider?: string;
|
|
asset_id?: string | null;
|
|
owner_id?: number | null;
|
|
file_path?: string | null;
|
|
thumbnail_path?: string | null;
|
|
width?: number | null;
|
|
height?: number | null;
|
|
}
|
|
|
|
export interface JourneyContributor {
|
|
journey_id: number;
|
|
user_id: number;
|
|
role: 'owner' | 'editor' | 'viewer';
|
|
added_at: number;
|
|
}
|