## Bug Fixes ### Note Card Actions - Fix broken size change functionality (missing state declaration) - Implement React 19 useOptimistic for instant UI feedback - Add startTransition for non-blocking updates - Ensure smooth animations without page refresh - All note actions now work: pin, archive, color, size, checklist ### Markdown LaTeX Rendering - Add remark-math and rehype-katex plugins - Support inline equations with dollar sign syntax - Support block equations with double dollar sign syntax - Import KaTeX CSS for proper styling - Equations now render correctly instead of showing raw LaTeX ## Technical Details - Replace undefined currentNote references with optimistic state - Add optimistic updates before server actions for instant feedback - Use router.refresh() in transitions for smart cache invalidation - Install remark-math, rehype-katex, and katex packages ## Testing - Build passes successfully with no TypeScript errors - Dev server hot-reloads changes correctly
145 lines
4.8 KiB
Plaintext
145 lines
4.8 KiB
Plaintext
// This is your Prisma schema file,
|
|
// learn more about it in the docs: https://pris.ly/d/prisma-schema
|
|
|
|
generator client {
|
|
provider = "prisma-client-js"
|
|
output = "./client-generated"
|
|
}
|
|
|
|
datasource db {
|
|
provider = "sqlite"
|
|
url = env("DATABASE_URL")
|
|
}
|
|
|
|
model User {
|
|
id String @id @default(cuid())
|
|
name String?
|
|
email String @unique
|
|
emailVerified DateTime?
|
|
password String? // Hashed password
|
|
role String @default("USER") // "USER" or "ADMIN"
|
|
image String?
|
|
theme String @default("light")
|
|
resetToken String? @unique
|
|
resetTokenExpiry DateTime?
|
|
accounts Account[]
|
|
sessions Session[]
|
|
notes Note[]
|
|
labels Label[]
|
|
receivedShares NoteShare[] @relation("ReceivedShares")
|
|
sentShares NoteShare[] @relation("SentShares")
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
}
|
|
|
|
model Account {
|
|
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?
|
|
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
|
|
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
|
|
@@id([provider, providerAccountId])
|
|
}
|
|
|
|
model Session {
|
|
sessionToken String @unique
|
|
userId String
|
|
expires DateTime
|
|
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
}
|
|
|
|
model VerificationToken {
|
|
identifier String
|
|
token String
|
|
expires DateTime
|
|
|
|
@@id([identifier, token])
|
|
}
|
|
|
|
model Label {
|
|
id String @id @default(cuid())
|
|
name String
|
|
color String @default("gray")
|
|
userId String? // Made optional for migration, but logic will enforce it
|
|
user User? @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
|
|
@@unique([name, userId]) // Labels are unique per user
|
|
@@index([userId])
|
|
}
|
|
|
|
model Note {
|
|
id String @id @default(cuid())
|
|
title String?
|
|
content String
|
|
color String @default("default")
|
|
isPinned Boolean @default(false)
|
|
isArchived Boolean @default(false)
|
|
type String @default("text") // "text" or "checklist"
|
|
checkItems String? // For checklist items stored as JSON string
|
|
labels String? // Array of label names stored as JSON string
|
|
images String? // Array of image URLs stored as JSON string
|
|
links String? // Array of link metadata stored as JSON string
|
|
reminder DateTime? // Reminder date and time
|
|
isReminderDone Boolean @default(false)
|
|
reminderRecurrence String? // "none", "daily", "weekly", "monthly", "custom"
|
|
reminderLocation String? // Location for location-based reminders
|
|
isMarkdown Boolean @default(false) // Whether content uses Markdown
|
|
size String @default("small") // "small", "medium", "large"
|
|
embedding String? // Vector embeddings stored as JSON string for semantic search
|
|
sharedWith String? // Array of user IDs (collaborators) stored as JSON string
|
|
userId String? // Owner of the note
|
|
user User? @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
shares NoteShare[] // All share records for this note
|
|
order Int @default(0)
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
|
|
@@index([isPinned])
|
|
@@index([isArchived])
|
|
@@index([order])
|
|
@@index([reminder])
|
|
@@index([userId])
|
|
}
|
|
|
|
model NoteShare {
|
|
id String @id @default(cuid())
|
|
noteId String
|
|
note Note @relation(fields: [noteId], references: [id], onDelete: Cascade)
|
|
userId String
|
|
user User @relation("ReceivedShares", fields: [userId], references: [id], onDelete: Cascade)
|
|
sharedBy String // User ID who shared the note
|
|
sharer User @relation("SentShares", fields: [sharedBy], references: [id], onDelete: Cascade)
|
|
status String @default("pending") // "pending", "accepted", "declined", "removed"
|
|
permission String @default("view") // "view", "comment", "edit"
|
|
notifiedAt DateTime?
|
|
respondedAt DateTime?
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
|
|
@@unique([noteId, userId])
|
|
@@index([userId])
|
|
@@index([status])
|
|
@@index([sharedBy])
|
|
}
|
|
|
|
model SystemConfig {
|
|
key String @id
|
|
value String
|
|
} |