d8a4e43bcc
- Top header bar + narrow sidebar layout - Dashboard: calendar-style schedule with timeline cards - Clients: card-based layout with avatar initials and pet count - Services: grid cards with emoji indicators and pricing - Bookings: timeline cards with time slots, status chips, inline actions - Invoices: cards with status badges, action buttons - All pages: search bars, empty states, modal forms - Consistent color system: indigo primary, amber alerts, gray hierarchy
172 lines
4.2 KiB
Plaintext
172 lines
4.2 KiB
Plaintext
datasource db {
|
|
provider = "postgresql"
|
|
url = env("DATABASE_URL")
|
|
}
|
|
|
|
generator client {
|
|
provider = "prisma-client-js"
|
|
}
|
|
|
|
model Client {
|
|
id String @id @default(cuid())
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
firstName String
|
|
lastName String
|
|
email String @unique
|
|
phone String?
|
|
address String?
|
|
notes String? @default("")
|
|
customFields Json?
|
|
isActive Boolean @default(true)
|
|
|
|
pets Pet[]
|
|
bookings Booking[]
|
|
invoices Invoice[]
|
|
messages Message[] @relation("ClientMessages")
|
|
pricing ClientPricing[]
|
|
|
|
@@map("clients")
|
|
}
|
|
|
|
model Pet {
|
|
id String @id @default(cuid())
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
name String
|
|
species String
|
|
breed String?
|
|
age Int?
|
|
weight String?
|
|
color String?
|
|
tags String[] @default([])
|
|
notes String? @default("")
|
|
customFields Json?
|
|
clientId String
|
|
client Client @relation(fields: [clientId], references: [id], onDelete: Cascade)
|
|
bookings Booking[] @relation("PetBookings")
|
|
|
|
@@map("pets")
|
|
}
|
|
|
|
model Service {
|
|
id String @id @default(cuid())
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
name String
|
|
description String @default("")
|
|
duration Int
|
|
basePrice Float
|
|
|
|
perClientPricing ClientPricing[]
|
|
bookings Booking[]
|
|
|
|
@@map("services")
|
|
}
|
|
|
|
model ClientPricing {
|
|
id String @id @default(cuid())
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
price Float
|
|
discountType String @default("none")
|
|
discountValue Float @default(0)
|
|
|
|
serviceId String
|
|
service Service @relation(fields: [serviceId], references: [id], onDelete: Cascade)
|
|
clientId String
|
|
client Client @relation(fields: [clientId], references: [id], onDelete: Cascade)
|
|
|
|
@@unique([serviceId, clientId])
|
|
@@map("client_pricing")
|
|
}
|
|
|
|
model Booking {
|
|
id String @id @default(cuid())
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
startAt DateTime
|
|
endAt DateTime
|
|
status BookingStatus @default(scheduled)
|
|
notes String? @default("")
|
|
customFields Json?
|
|
clientId String
|
|
client Client @relation(fields: [clientId], references: [id])
|
|
serviceId String
|
|
service Service @relation(fields: [serviceId], references: [id])
|
|
assignedStaff String?
|
|
priceOverride Float?
|
|
petId String?
|
|
pet Pet? @relation("PetBookings", fields: [petId], references: [id])
|
|
invoice Invoice? @relation()
|
|
recurringRule Json?
|
|
|
|
@@map("bookings")
|
|
}
|
|
|
|
enum BookingStatus {
|
|
scheduled
|
|
confirmed
|
|
in_progress
|
|
completed
|
|
cancelled
|
|
}
|
|
|
|
model Invoice {
|
|
id String @id @default(cuid())
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
invoiceNumber String @unique
|
|
dueDate DateTime
|
|
status InvoiceStatus @default(draft)
|
|
stripePaymentIntentId String?
|
|
subtotal Float @default(0)
|
|
tax Float @default(0)
|
|
total Float @default(0)
|
|
notes String? @default("")
|
|
|
|
clientId String
|
|
client Client @relation(fields: [clientId], references: [id])
|
|
bookingId String? @unique
|
|
booking Booking? @relation(fields: [bookingId], references: [id])
|
|
invoiceItems InvoiceItem[]
|
|
|
|
@@map("invoices")
|
|
}
|
|
|
|
enum InvoiceStatus {
|
|
draft
|
|
sent
|
|
paid
|
|
overdue
|
|
cancelled
|
|
}
|
|
|
|
model InvoiceItem {
|
|
id String @id @default(cuid())
|
|
createdAt DateTime @default(now())
|
|
description String
|
|
quantity Int @default(1)
|
|
unitPrice Float
|
|
amount Float
|
|
|
|
invoiceId String
|
|
invoice Invoice @relation(fields: [invoiceId], references: [id], onDelete: Cascade)
|
|
|
|
@@map("invoice_items")
|
|
}
|
|
|
|
model Message {
|
|
id String @id @default(cuid())
|
|
createdAt DateTime @default(now())
|
|
readAt DateTime?
|
|
content String
|
|
isFromStaff Boolean @default(false)
|
|
|
|
clientId String
|
|
client Client @relation("ClientMessages", fields: [clientId], references: [id])
|
|
staffId String
|
|
|
|
@@map("messages")
|
|
}
|