trips) adding initial commit

This commit is contained in:
2026-02-18 20:23:34 -05:00
commit 1068145261
67 changed files with 3602 additions and 0 deletions

124
src/lib/server/plans.ts Normal file
View File

@@ -0,0 +1,124 @@
import { db } from './db/index.js';
import { randomUUID } from 'crypto';
export type PlanType =
| 'destination'
| 'activity'
| 'transport'
| 'lodging'
| 'restaurant'
| 'tour'
| 'packing'
| 'todo';
export type PlanStatus = 'idea' | 'tentative' | 'confirmed';
export interface Plan {
id: string;
trip_id: string;
user_id: string;
type: PlanType;
status: PlanStatus;
parent_id: string | null;
title: string;
notes: string | null;
city_id: number | null;
city_name: string | null;
country: string | null;
country_code: string | null;
start_date: string | null;
end_date: string | null;
position: number;
created_at: string;
updated_at: string;
}
export interface City {
id: number;
name: string;
country: string;
country_code: string;
population: number | null;
}
export interface CreateDestinationInput {
tripId: string;
userId: string;
cityId?: number;
cityName: string;
country: string;
countryCode: string;
startDate?: string;
endDate?: string;
status?: PlanStatus;
notes?: string;
}
export function createDestination(input: CreateDestinationInput): Plan {
const id = randomUUID();
const maxPos = db.get<{ pos: number }>(
`SELECT COALESCE(MAX(position), -1) + 1 as pos FROM plans WHERE trip_id = ? AND user_id = ?`,
[input.tripId, input.userId]
);
const position = maxPos?.pos ?? 0;
db.run(
`INSERT INTO plans (id, trip_id, user_id, type, status, title, notes, city_id, city_name, country, country_code, start_date, end_date, position)
VALUES (?, ?, ?, 'destination', ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
[
id,
input.tripId,
input.userId,
input.status ?? 'idea',
input.cityName,
input.notes ?? null,
input.cityId ?? null,
input.cityName,
input.country,
input.countryCode,
input.startDate ?? null,
input.endDate ?? null,
position
]
);
return db.get<Plan>('SELECT * FROM plans WHERE id = ?', [id])!;
}
export function getPlansForTrip(tripId: string, userId: string): Plan[] {
return db.all<Plan>(
`SELECT * FROM plans WHERE trip_id = ? AND user_id = ? ORDER BY position ASC, created_at ASC`,
[tripId, userId]
);
}
export function getPlanCountForTrip(tripId: string, userId: string): number {
const row = db.get<{ count: number }>(
`SELECT COUNT(*) as count FROM plans WHERE trip_id = ? AND user_id = ?`,
[tripId, userId]
);
return row?.count ?? 0;
}
export function searchCities(query: string): City[] {
if (!query.trim()) return [];
const pattern = `%${query.trim()}%`;
return db.all<City>(
`SELECT id, name, country, country_code, population
FROM cities
WHERE name LIKE ? COLLATE NOCASE
ORDER BY
CASE WHEN name LIKE ? COLLATE NOCASE THEN 0 ELSE 1 END,
population DESC NULLS LAST
LIMIT 10`,
[pattern, `${query.trim()}%`]
);
}
export function deletePlan(planId: string, userId: string): void {
// Verify the plan belongs to the user
const plan = db.get<Plan>('SELECT * FROM plans WHERE id = ? AND user_id = ?', [planId, userId]);
if (!plan) {
throw new Error('Plan not found or not authorized');
}
db.run('DELETE FROM plans WHERE id = ?', [planId]);
}