1. Authentication Library (src/lib/auth.ts)

2. Authentication Routes
3. Updated Data Store (`src/lib/db.ts`)
4. Updated API Routes
5. Updated Frontend Component (`src/components/BikeBuilderApp.tsx`)
This commit is contained in:
2026-05-19 16:07:57 +02:00
parent 9c212fbf43
commit cb0ff5feb7
15 changed files with 8127 additions and 7521 deletions
+19 -1
View File
@@ -8,6 +8,18 @@ datasource db {
url = env("DATABASE_URL")
}
model User {
id String @id @default(cuid())
email String @unique
passwordHash String
name String?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
builds BikeBuild[]
reviews RideReview[]
preference RiderPreference?
}
model Product {
id String @id
category String
@@ -36,6 +48,8 @@ model BikeBuild {
rearTireId String?
setup String
imagePath String?
userId String
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
reviews RideReview[]
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
@@ -45,6 +59,8 @@ model RideReview {
id String @id @default(cuid())
buildId String
build BikeBuild @relation(fields: [buildId], references: [id], onDelete: Cascade)
userId String
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
suspFeel Int
frontGrip Int
rearGrip Int
@@ -60,7 +76,9 @@ model RideReview {
}
model RiderPreference {
id String @id @default("default")
id String @id @default(cuid())
userId String @unique
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
harshTendency Int @default(0)
softTendency Int @default(0)
gripPreference Int @default(0)
+29 -15
View File
@@ -4,21 +4,35 @@ import { frames, forks, shocks, tires } from "../src/lib/catalog";
const prisma = new PrismaClient();
async function main() {
const products = [...frames, ...forks, ...shocks, ...tires];
for (const product of products) {
const { id, category, brand, model, imagePath, sources } = product;
const position = "position" in product ? product.position : null;
await prisma.product.upsert({
where: { id },
update: { category, position, brand, model, imagePath, specs: JSON.stringify(product), setup: JSON.stringify(product), sources: JSON.stringify(sources) },
create: { id, category, position, brand, model, imagePath, specs: JSON.stringify(product), setup: JSON.stringify(product), sources: JSON.stringify(sources) },
});
}
await prisma.riderPreference.upsert({
where: { id: "default" },
update: {},
create: { id: "default" },
});
const products = [...frames, ...forks, ...shocks, ...tires];
for (const product of products) {
const { id, category, brand, model, imagePath, sources } = product;
const position = "position" in product ? product.position : null;
await prisma.product.upsert({
where: { id },
update: {
category,
position,
brand,
model,
imagePath,
specs: JSON.stringify(product),
setup: JSON.stringify(product),
sources: JSON.stringify(sources),
},
create: {
id,
category,
position,
brand,
model,
imagePath,
specs: JSON.stringify(product),
setup: JSON.stringify(product),
sources: JSON.stringify(sources),
},
});
}
}
main().finally(async () => prisma.$disconnect());