diff --git a/Dockerfile b/Dockerfile index 36fe980..71c914b 100644 --- a/Dockerfile +++ b/Dockerfile @@ -10,8 +10,10 @@ RUN pnpm install --frozen-lockfile COPY . . -RUN pnpm build +ENV DATABASE_URL="postgresql://postgres:mysecretpassword@localhost:5432/postgres" -EXPOSE 3000 +RUN pnpm run build -CMD ["node", "build"] \ No newline at end of file +EXPOSE 5173 + +CMD ["pnpm", "run", "dev"] \ No newline at end of file diff --git a/src/app.html b/src/app.html index 81d786e..81d5500 100644 --- a/src/app.html +++ b/src/app.html @@ -4,7 +4,6 @@ - Better %sveltekit.head% diff --git a/src/components/global/Header.svelte b/src/components/global/Header.svelte index 16770ad..eea4ee0 100644 --- a/src/components/global/Header.svelte +++ b/src/components/global/Header.svelte @@ -1,8 +1,9 @@
- better. +
diff --git a/src/components/global/Logo.svelte b/src/components/global/Logo.svelte new file mode 100644 index 0000000..166fa87 --- /dev/null +++ b/src/components/global/Logo.svelte @@ -0,0 +1,10 @@ + + + + better + + + + diff --git a/src/lib/db/server/drizzle/0002_little_magus.sql b/src/lib/db/server/drizzle/0002_little_magus.sql new file mode 100644 index 0000000..0aec1f5 --- /dev/null +++ b/src/lib/db/server/drizzle/0002_little_magus.sql @@ -0,0 +1,30 @@ +CREATE TABLE IF NOT EXISTS "circuits" ( + "id" text PRIMARY KEY DEFAULT 'uuid_generate_v4()' NOT NULL, + "name" text NOT NULL, + "reps" integer DEFAULT 0, + "rest_exercice" integer DEFAULT 0, + "rest_circuit" integer DEFAULT 0 +); +--> statement-breakpoint +CREATE TABLE IF NOT EXISTS "exercises" ( + "id" text PRIMARY KEY DEFAULT 'uuid_generate_v4()' NOT NULL, + "name" text NOT NULL, + "reps" integer DEFAULT 0 NOT NULL, + "sets" integer DEFAULT 0, + "rest" integer DEFAULT 0 +); +--> statement-breakpoint +CREATE TABLE IF NOT EXISTS "trainings" ( + "id" text PRIMARY KEY DEFAULT 'uuid_generate_v4()' NOT NULL, + "user_id" text, + "name" text NOT NULL, + "is_archived" boolean DEFAULT false, + "duration" integer DEFAULT 0, + "link" text +); +--> statement-breakpoint +DO $$ BEGIN + ALTER TABLE "trainings" ADD CONSTRAINT "trainings_user_id_users_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."users"("id") ON DELETE cascade ON UPDATE no action; +EXCEPTION + WHEN duplicate_object THEN null; +END $$; diff --git a/src/lib/db/server/drizzle/meta/0002_snapshot.json b/src/lib/db/server/drizzle/meta/0002_snapshot.json new file mode 100644 index 0000000..5a13e92 --- /dev/null +++ b/src/lib/db/server/drizzle/meta/0002_snapshot.json @@ -0,0 +1,324 @@ +{ + "id": "226f59ee-7c0b-47d3-8a30-21480fe25be2", + "prevId": "61b3591e-599a-4288-907a-af71ae6f59ae", + "version": "7", + "dialect": "postgresql", + "tables": { + "public.circuits": { + "name": "circuits", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true, + "default": "'uuid_generate_v4()'" + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "reps": { + "name": "reps", + "type": "integer", + "primaryKey": false, + "notNull": false, + "default": 0 + }, + "rest_exercice": { + "name": "rest_exercice", + "type": "integer", + "primaryKey": false, + "notNull": false, + "default": 0 + }, + "rest_circuit": { + "name": "rest_circuit", + "type": "integer", + "primaryKey": false, + "notNull": false, + "default": 0 + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.days": { + "name": "days", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true, + "default": "'uuid_generate_v4()'" + }, + "date": { + "name": "date", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "habits": { + "name": "habits", + "type": "json", + "primaryKey": false, + "notNull": false, + "default": "'[]'::json" + }, + "habits_completed": { + "name": "habits_completed", + "type": "integer", + "primaryKey": false, + "notNull": false, + "default": 0 + }, + "habits_len": { + "name": "habits_len", + "type": "integer", + "primaryKey": false, + "notNull": false, + "default": 0 + }, + "percentage": { + "name": "percentage", + "type": "integer", + "primaryKey": false, + "notNull": false, + "default": 0 + } + }, + "indexes": {}, + "foreignKeys": { + "days_user_id_users_id_fk": { + "name": "days_user_id_users_id_fk", + "tableFrom": "days", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.exercises": { + "name": "exercises", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true, + "default": "'uuid_generate_v4()'" + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "reps": { + "name": "reps", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "sets": { + "name": "sets", + "type": "integer", + "primaryKey": false, + "notNull": false, + "default": 0 + }, + "rest": { + "name": "rest", + "type": "integer", + "primaryKey": false, + "notNull": false, + "default": 0 + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.habits": { + "name": "habits", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true, + "default": "'uuid_generate_v4()'" + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "is_completed": { + "name": "is_completed", + "type": "boolean", + "primaryKey": false, + "notNull": false, + "default": false + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "habits_user_id_users_id_fk": { + "name": "habits_user_id_users_id_fk", + "tableFrom": "habits", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.trainings": { + "name": "trainings", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true, + "default": "'uuid_generate_v4()'" + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "is_archived": { + "name": "is_archived", + "type": "boolean", + "primaryKey": false, + "notNull": false, + "default": false + }, + "duration": { + "name": "duration", + "type": "integer", + "primaryKey": false, + "notNull": false, + "default": 0 + }, + "link": { + "name": "link", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": { + "trainings_user_id_users_id_fk": { + "name": "trainings_user_id_users_id_fk", + "tableFrom": "trainings", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.users": { + "name": "users", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true, + "default": "'uuid_generate_v4()'" + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "password": { + "name": "password", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "is_admin": { + "name": "is_admin", + "type": "boolean", + "primaryKey": false, + "notNull": false, + "default": false + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + } + }, + "enums": {}, + "schemas": {}, + "sequences": {}, + "_meta": { + "columns": {}, + "schemas": {}, + "tables": {} + } +} \ No newline at end of file diff --git a/src/lib/db/server/drizzle/meta/_journal.json b/src/lib/db/server/drizzle/meta/_journal.json index 3d28fe3..84b7054 100644 --- a/src/lib/db/server/drizzle/meta/_journal.json +++ b/src/lib/db/server/drizzle/meta/_journal.json @@ -15,6 +15,13 @@ "when": 1727881189830, "tag": "0001_dry_lila_cheney", "breakpoints": true + }, + { + "idx": 2, + "version": "7", + "when": 1727967445882, + "tag": "0002_little_magus", + "breakpoints": true } ] } \ No newline at end of file diff --git a/src/lib/db/server/schema.ts b/src/lib/db/server/schema.ts index f94e17a..266f4d3 100644 --- a/src/lib/db/server/schema.ts +++ b/src/lib/db/server/schema.ts @@ -1,5 +1,6 @@ import { relations } from "drizzle-orm"; import { integer, text, pgTable, boolean, json } from "drizzle-orm/pg-core"; +import { link } from "fs"; export const usersTable = pgTable("users", { id: text("id").primaryKey().default("uuid_generate_v4()"), @@ -8,6 +9,11 @@ export const usersTable = pgTable("users", { isAdmin: boolean("is_admin").default(false) }); +export const usersRelations = relations(usersTable, ({ many }) => ({ + habits: many(habitsTable), + days: many(daysTable) +})); + export const habitsTable = pgTable("habits", { id: text("id").primaryKey().default("uuid_generate_v4()"), name: text("name").notNull(), @@ -17,6 +23,10 @@ export const habitsTable = pgTable("habits", { .notNull() }); +export const habitsRelations = relations(habitsTable, ({ one }) => ({ + user: one(usersTable) +})); + export const daysTable = pgTable("days", { id: text("id").primaryKey().default("uuid_generate_v4()"), date: text("date").notNull(), @@ -29,15 +39,46 @@ export const daysTable = pgTable("days", { percentage: integer("percentage").default(0) }); -export const usersRelations = relations(usersTable, ({ many }) => ({ - habits: many(habitsTable), - days: many(daysTable) +export const daysRelations = relations(daysTable, ({ one }) => ({ + user: one(usersTable) })); -export const habitsRelations = relations(habitsTable, ({ one }) => ({ - user: one(usersTable) +export const trainingsTable = pgTable("trainings", { + id: text("id").primaryKey().default("uuid_generate_v4()"), + userId: text("user_id").references(() => usersTable.id, { onDelete: "cascade" }), + name: text("name").notNull(), + isArchived: boolean("is_archived").default(false), + duration: integer("duration").default(0), + link: text("link") +}); + +export const trainingsRelations = relations(trainingsTable, ({ one, many }) => ({ + user: one(usersTable), + circuits: many(circuitsTable), + exercises: many(exercisesTable) })); -export const daysRelations = relations(daysTable, ({ one }) => ({ - user: one(usersTable) +export const circuitsTable = pgTable("circuits", { + id: text("id").primaryKey().default("uuid_generate_v4()"), + name: text("name").notNull(), + reps: integer("reps").default(0), + restExercice: integer("rest_exercice").default(0), + restCircuit: integer("rest_circuit").default(0) +}); + +export const circuitsRelations = relations(circuitsTable, ({ many }) => ({ + exercises: many(exercisesTable) +})); + +export const exercisesTable = pgTable("exercises", { + id: text("id").primaryKey().default("uuid_generate_v4()"), + name: text("name").notNull(), + reps: integer("reps").default(0).notNull(), + sets: integer("sets").default(0), + rest: integer("rest").default(0) +}); + +export const exercisesRelations = relations(exercisesTable, ({ one, many }) => ({ + circuit: one(circuitsTable), + training: many(trainingsTable) })); diff --git a/src/lib/db/server/seed.ts b/src/lib/db/server/seed.ts index ecd9903..94f4e95 100644 --- a/src/lib/db/server/seed.ts +++ b/src/lib/db/server/seed.ts @@ -2,7 +2,14 @@ import "dotenv/config"; import { drizzle } from "drizzle-orm/postgres-js"; import postgres from "postgres"; -import { habitsTable, usersTable } from "$lib/db/server/schema"; +import { + habitsTable, + usersTable, + trainingsTable, + exercisesTable, + circuitsTable +} from "$lib/db/server/schema"; +import { trainingsDataTest } from "$utils/constants"; const connectionUrl = process.env.DATABASE_URL; @@ -45,6 +52,63 @@ async function seed() { .returning(); console.log("Inserted habits:", insertedHabits); + for (const training of trainingsDataTest) { + const insertedTraining = await db + .insert(trainingsTable) + .values({ + id: training.id, + userId: "2e3ae305-0bae-4fc0-9b8b-890770cbbaf0", + name: training.name, + isArchived: training.isArchived, + duration: training.duration, + link: training.link + }) + .returning(); + console.log("Inserted training:", insertedTraining); + + if (training.circuits) { + for (const circuit of training.circuits) { + const insertedCircuit = await db + .insert(circuitsTable) + .values({ + id: circuit.id, + name: circuit.name, + reps: circuit.reps, + restExercice: circuit.restExercice, + restCircuit: circuit.restCircuit + }) + .returning(); + console.log("Inserted circuit:", insertedCircuit); + + for (const exercise of circuit.exercises) { + await db + .insert(exercisesTable) + .values({ + id: exercise.id, + name: exercise.name, + reps: exercise.reps, + sets: 1, + rest: 0 + }) + .returning(); + } + } + } + + for (const exercise of training.exercises) { + await db + .insert(exercisesTable) + .values({ + id: exercise.id, + name: exercise.name, + reps: exercise.reps, + sets: exercise.sets, + rest: exercise.rest + }) + .returning(); + } + } + console.log("Seeding completed successfully!"); } catch (error) { console.error("Error seeding database:", error); diff --git a/src/routes/api/users/+server.ts b/src/routes/api/users/+server.ts deleted file mode 100644 index 5b4647a..0000000 --- a/src/routes/api/users/+server.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { json } from "@sveltejs/kit"; -import type { RequestHandler, RequestEvent } from "./$types"; - -import { db } from "$lib/db/server/client"; - -export const GET: RequestHandler = async ({ request }: RequestEvent) => { - try { - const user = await db.query.usersTable.findFirst(); - - if (!user) return json({ message: "User not found" }, { status: 404 }); - - return new Response(JSON.stringify(user), { - status: 200, - headers: { - "Content-Type": "application/json" - } - }); - } catch (error: any) { - console.error("Error fetching users:", error); - return json({ message: "Internal Server Error" }, { status: 500 }); - } -}; diff --git a/static/favicon.png b/static/favicon.png new file mode 100644 index 0000000..0ce0985 Binary files /dev/null and b/static/favicon.png differ diff --git a/static/sprout.svg b/static/sprout.svg new file mode 100644 index 0000000..1202dff --- /dev/null +++ b/static/sprout.svg @@ -0,0 +1 @@ + \ No newline at end of file