first commit

This commit is contained in:
2026-07-08 19:17:05 +02:00
parent f001b0ca63
commit 786b161dae
19 changed files with 2492 additions and 79 deletions
+16
View File
@@ -0,0 +1,16 @@
import { drizzle } from 'drizzle-orm/postgres-js';
import postgres from 'postgres';
import * as schema from './schema';
const connectionString = process.env.DATABASE_URL!;
if (!connectionString) {
throw new Error('DATABASE_URL is required');
}
// For query client (server)
const client = postgres(connectionString);
export const db = drizzle(client, { schema });
export * from './schema';
+39
View File
@@ -0,0 +1,39 @@
import { pgTable, serial, text, timestamp, numeric, integer, uuid, jsonb } from 'drizzle-orm/pg-core';
export const trips = pgTable('trips', {
id: uuid('id').primaryKey().defaultRandom(),
destination: text('destination').notNull(),
lat: numeric('lat'),
lng: numeric('lng'),
startDate: timestamp('start_date', { withTimezone: true }),
numDays: integer('num_days').notNull(),
totalBudget: numeric('total_budget'),
currency: text('currency').default('EUR'),
preferences: jsonb('preferences').$type<string[]>().default([]),
experienceMode: text('experience_mode').default('balanced'),
estimatedTotalCost: numeric('estimated_total_cost'),
createdAt: timestamp('created_at', { withTimezone: true }).defaultNow(),
});
export const activities = pgTable('activities', {
id: serial('id').primaryKey(),
tripId: uuid('trip_id').references(() => trips.id, { onDelete: 'cascade' }),
dayNumber: integer('day_number').notNull(),
startTime: text('start_time'),
title: text('title').notNull(),
type: text('type').notNull(), // attraction | restaurant | bar | event | meal | other
estimatedCost: numeric('estimated_cost'),
address: text('address'),
lat: numeric('lat'),
lng: numeric('lng'),
rating: numeric('rating'),
source: text('source'),
sourceUrl: text('source_url'),
notes: text('notes'),
orderInDay: integer('order_in_day').default(0),
});
export type Trip = typeof trips.$inferSelect;
export type NewTrip = typeof trips.$inferInsert;
export type Activity = typeof activities.$inferSelect;
export type NewActivity = typeof activities.$inferInsert;
+40
View File
@@ -0,0 +1,40 @@
export const EXPERIENCE_MODES = [
{
id: 'balanced',
label: 'Balanced',
description: 'A good mix of everything',
icon: '⚖️',
},
{
id: 'cultural',
label: 'Cultural Explorer',
description: 'Museums, history, landmarks, heritage',
icon: '🏛️',
},
{
id: 'foodie',
label: 'Foodie',
description: 'Restaurants, local eats, markets, cafes',
icon: '🍽️',
},
{
id: 'adventurous',
label: 'Adventurous / Bold',
description: 'Unique spots, active, hidden gems, evening fun',
icon: '🧭',
},
{
id: 'relaxed',
label: 'Relaxed Local',
description: 'Slower pace, parks, free time, fewer stops',
icon: '🌳',
},
{
id: 'nightlife',
label: 'Nightlife & Vibes',
description: 'Bars, concerts, theater, late experiences',
icon: '🌙',
},
] as const;
export type ExperienceMode = typeof EXPERIENCE_MODES[number]['id'];