Latest updarte

This commit is contained in:
hubaceks
2026-05-18 23:04:50 +02:00
parent 889c84c553
commit 7d63addc7e
59 changed files with 10991 additions and 246 deletions

187
prisma/schema.prisma Normal file
View File

@@ -0,0 +1,187 @@
generator client {
provider = "prisma-client-js"
}
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}
// ─── Auth (NextAuth v5) ────────────────────────────────────────────────────
model User {
id String @id @default(cuid())
name String?
email String @unique
emailVerified DateTime?
image String?
role Role @default(CUSTOMER)
password String?
accounts Account[]
sessions Session[]
orders Order[]
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}
model Account {
id String @id @default(cuid())
userId String
type String
provider String
providerAccountId String
refresh_token String?
access_token String?
expires_at Int?
token_type String?
scope String?
id_token String?
session_state String?
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
@@unique([provider, providerAccountId])
}
model Session {
id String @id @default(cuid())
sessionToken String @unique
userId String
expires DateTime
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
}
model VerificationToken {
identifier String
token String
expires DateTime
@@unique([identifier, token])
}
enum Role {
CUSTOMER
ADMIN
}
// ─── Katalog ──────────────────────────────────────────────────────────────
model Category {
id String @id @default(cuid())
name String
slug String @unique
description String?
image String?
products Product[]
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}
model Product {
id String @id @default(cuid())
name String
slug String @unique
description String?
image String?
published Boolean @default(false)
categoryId String
category Category @relation(fields: [categoryId], references: [id])
variants ProductVariant[]
orderItems OrderItem[]
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}
model ProductVariant {
id String @id @default(cuid())
name String
price Int // cena v haléřích (CZK)
stock Int @default(0)
sku String? @unique
productId String
product Product @relation(fields: [productId], references: [id], onDelete: Cascade)
cartItems CartItem[]
orderItems OrderItem[]
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}
// ─── Košík ────────────────────────────────────────────────────────────────
model Cart {
id String @id @default(cuid())
sessionId String? @unique // pro guest uživatele
userId String? @unique // pro přihlášené
items CartItem[]
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}
model CartItem {
id String @id @default(cuid())
cartId String
variantId String
quantity Int
cart Cart @relation(fields: [cartId], references: [id], onDelete: Cascade)
variant ProductVariant @relation(fields: [variantId], references: [id])
@@unique([cartId, variantId])
}
// ─── Objednávky ───────────────────────────────────────────────────────────
model Order {
id String @id @default(cuid())
userId String?
guestEmail String?
status OrderStatus @default(PENDING)
totalAmount Int // v haléřích
stripeSessionId String? @unique
shippingName String
shippingEmail String
shippingPhone String?
shippingStreet String
shippingCity String
shippingZip String
shippingCountry String @default("CZ")
user User? @relation(fields: [userId], references: [id])
items OrderItem[]
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}
model OrderItem {
id String @id @default(cuid())
orderId String
productId String
variantId String
quantity Int
unitPrice Int // cena v době objednávky (snapshot)
order Order @relation(fields: [orderId], references: [id], onDelete: Cascade)
product Product @relation(fields: [productId], references: [id])
variant ProductVariant @relation(fields: [variantId], references: [id])
}
enum OrderStatus {
PENDING
PAID
PROCESSING
SHIPPED
DELIVERED
CANCELLED
REFUNDED
}

148
prisma/seed.ts Normal file
View File

@@ -0,0 +1,148 @@
import { PrismaClient } from "@prisma/client";
const db = new PrismaClient();
async function main() {
console.log("🌱 Seeding databáze...");
// Kategorie
const dorty = await db.category.upsert({
where: { slug: "dorty" },
update: {},
create: { name: "Dorty", slug: "dorty", description: "Celé dorty na objednávku i jako dárek" },
});
const zakusky = await db.category.upsert({
where: { slug: "zakusky" },
update: {},
create: { name: "Zákusky", slug: "zakusky", description: "Čerstvé zákusky pečené každý den" },
});
const pralinky = await db.category.upsert({
where: { slug: "pralinky" },
update: {},
create: { name: "Pralinky", slug: "pralinky", description: "Ručně vyráběné čokoládové pralinky" },
});
// Produkty
await db.product.upsert({
where: { slug: "cokoladovy-dort" },
update: {},
create: {
name: "Čokoládový dort",
slug: "cokoladovy-dort",
description: "Tříposchoďový dort z belgické čokolády s ganache polevou a čokoládovými hoblinami.",
published: true,
categoryId: dorty.id,
variants: {
create: [
{ name: "Malý (6 porcí)", price: 59000, stock: 5 },
{ name: "Střední (10 porcí)", price: 89000, stock: 3 },
{ name: "Velký (16 porcí)", price: 129000, stock: 2 },
],
},
},
});
await db.product.upsert({
where: { slug: "jahodovy-dort" },
update: {},
create: {
name: "Jahodový dort",
slug: "jahodovy-dort",
description: "Lehký piškotový dort s šlehačkou a čerstvými jahodami. Sezónní specialita.",
published: true,
categoryId: dorty.id,
variants: {
create: [
{ name: "Malý (6 porcí)", price: 65000, stock: 4 },
{ name: "Velký (12 porcí)", price: 119000, stock: 2 },
],
},
},
});
await db.product.upsert({
where: { slug: "kremovy-zakusek" },
update: {},
create: {
name: "Krémový zákusek",
slug: "kremovy-zakusek",
description: "Klasický kremrole s vanilkovým krémem a cukrovou polevou.",
published: true,
categoryId: zakusky.id,
variants: {
create: [
{ name: "1 kus", price: 4500, stock: 20 },
{ name: "Balení 6 kusů", price: 24000, stock: 10 },
],
},
},
});
await db.product.upsert({
where: { slug: "eclair-cokoladovy" },
update: {},
create: {
name: "Éclair čokoládový",
slug: "eclair-cokoladovy",
description: "Francouzský éclair z odpalovaného těsta s čokoládovým krémem.",
published: true,
categoryId: zakusky.id,
variants: {
create: [
{ name: "1 kus", price: 5500, stock: 15 },
{ name: "Balení 4 kusy", price: 20000, stock: 8 },
],
},
},
});
await db.product.upsert({
where: { slug: "pralinky-belgicke" },
update: {},
create: {
name: "Belgické pralinky",
slug: "pralinky-belgicke",
description: "Ručně vyráběné pralinky z hořké, mléčné a bílé belgické čokolády s různými náplněmi.",
published: true,
categoryId: pralinky.id,
variants: {
create: [
{ name: "Krabička 9 kusů", price: 29000, stock: 12 },
{ name: "Krabička 18 kusů", price: 55000, stock: 8 },
{ name: "Krabička 36 kusů", price: 99000, stock: 5 },
],
},
},
});
await db.product.upsert({
where: { slug: "makronky-mix" },
update: {},
create: {
name: "Makronky mix",
slug: "makronky-mix",
description: "Francouzské makronky v 6 příchutích: vanilka, malina, pistácie, citron, karamel, čokoláda.",
published: true,
categoryId: pralinky.id,
variants: {
create: [
{ name: "6 kusů (mix)", price: 22000, stock: 10 },
{ name: "12 kusů (mix)", price: 40000, stock: 6 },
],
},
},
});
console.log("✅ Seed dokončen!");
}
main()
.catch((e) => {
console.error(e);
process.exit(1);
})
.finally(async () => {
await db.$disconnect();
});