A whole bunch of stuff agian lol I promise to track more closely when we get to more stable state - like end of feb

This commit is contained in:
2026-02-19 09:41:27 -07:00
parent 1a1f12c45b
commit 435fb8150c
71 changed files with 8498 additions and 652 deletions

View File

@@ -0,0 +1,2 @@
-- AlterEnum
ALTER TYPE "UserCreatedVia" ADD VALUE IF NOT EXISTS 'QUICK_JOIN_INVITE';

View File

@@ -33,6 +33,7 @@ enum UserCreatedVia {
PUBLIC_SHIFT_SIGNUP
STANDARD
SELF_REGISTRATION
QUICK_JOIN_INVITE
}
model User {
@@ -134,6 +135,11 @@ model User {
notifications Notification[] @relation("UserNotifications")
notificationPreferences NotificationPreferences? @relation("NotificationPreferences")
// Photo gallery relations
photosUploaded Photo[] @relation("PhotoUploader")
albumsCreated PhotoAlbum[] @relation("AlbumCreator")
photoComments PhotoComment[] @relation("PhotoCommentUser")
@@map("users")
}
@@ -1616,6 +1622,11 @@ model Session {
adClicks AdClick[]
userFinishes UserFinish[]
// Photo gallery relations
photoUpvotes PhotoUpvote[] @relation("SessionPhotoUpvotes")
photoComments PhotoComment[] @relation("SessionPhotoComments")
photoReactions PhotoReaction[] @relation("SessionPhotoReactions")
@@index([userId], map: "idx_sessions_user_id")
@@index([country], map: "idx_sessions_country")
@@map("sessions")
@@ -3473,3 +3484,188 @@ model DocsPageView {
@@index([path, createdAt])
@@map("docs_page_views")
}
// ============================================================================
// PHOTO GALLERY
// ============================================================================
model Photo {
id Int @id @default(autoincrement())
path String @unique // Full path to original file
filename String // UUID filename on disk
originalFilename String? @map("original_filename") // Original upload filename
title String?
description String? @db.Text
producer String?
creator String?
tags Json? // String array
// Image metadata (from sharp)
width Int?
height Int?
orientation String? // H / V / S (horizontal/vertical/square)
fileSize BigInt? @map("file_size")
format String? // jpeg, png, webp, avif, gif, tiff, heic
colorSpace String? @map("color_space") // srgb, display-p3, etc.
hasAlpha Boolean? @default(false) @map("has_alpha")
dpi Int?
// EXIF data
cameraMake String? @map("camera_make")
cameraModel String? @map("camera_model")
focalLength String? @map("focal_length")
aperture String?
shutterSpeed String? @map("shutter_speed")
iso Int?
takenAt DateTime? @map("taken_at")
gpsLatitude Float? @map("gps_latitude") @db.Real
gpsLongitude Float? @map("gps_longitude") @db.Real
// Processed variants
thumbnailPath String? @map("thumbnail_path")
mediumPath String? @map("medium_path")
largePath String? @map("large_path")
webpPath String? @map("webp_path")
// Publishing (mirrors Video)
isPublished Boolean @default(false) @map("is_published")
publishedAt DateTime? @map("published_at")
category String?
accessLevel String @default("free") @map("access_level")
position Int? @default(0)
isLocked Boolean @default(false) @map("is_locked")
scheduledPublishAt DateTime? @map("scheduled_publish_at")
scheduledUnpublishAt DateTime? @map("scheduled_unpublish_at")
// Engagement counters
viewCount Int @default(0) @map("view_count")
upvoteCount Int @default(0) @map("upvote_count")
commentCount Int @default(0) @map("comment_count")
// Album membership
albumId Int? @map("album_id")
albumPosition Int? @default(0) @map("album_position")
// Tracking
uploaderId String? @map("uploader_id")
createdAt DateTime @default(now()) @map("created_at")
// Relations
album PhotoAlbum? @relation("AlbumPhotos", fields: [albumId], references: [id], onDelete: SetNull)
uploader User? @relation("PhotoUploader", fields: [uploaderId], references: [id])
upvotes PhotoUpvote[]
comments PhotoComment[]
views PhotoView[]
reactions PhotoReaction[]
coverForAlbum PhotoAlbum? @relation("AlbumCover")
@@index([orientation], map: "idx_photos_orientation")
@@index([producer], map: "idx_photos_producer")
@@index([isPublished, isLocked], map: "idx_photos_published_locked")
@@index([category, isPublished], map: "idx_photos_category_published")
@@index([albumId, albumPosition], map: "idx_photos_album_position")
@@index([createdAt], map: "idx_photos_created_at")
@@index([uploaderId], map: "idx_photos_uploader")
@@map("photos")
}
model PhotoAlbum {
id Int @id @default(autoincrement())
title String
description String? @db.Text
coverPhotoId Int? @unique @map("cover_photo_id")
// Publishing
isPublished Boolean @default(false) @map("is_published")
publishedAt DateTime? @map("published_at")
category String?
accessLevel String @default("free") @map("access_level")
position Int? @default(0)
isLocked Boolean @default(false) @map("is_locked")
// Aggregate counters
viewCount Int @default(0) @map("view_count")
upvoteCount Int @default(0) @map("upvote_count")
photoCount Int @default(0) @map("photo_count")
// Scheduling
scheduledPublishAt DateTime? @map("scheduled_publish_at")
scheduledUnpublishAt DateTime? @map("scheduled_unpublish_at")
// Tracking
creatorId String? @map("creator_id")
createdAt DateTime @default(now()) @map("created_at")
updatedAt DateTime @updatedAt @map("updated_at")
// Relations
photos Photo[] @relation("AlbumPhotos")
coverPhoto Photo? @relation("AlbumCover", fields: [coverPhotoId], references: [id], onDelete: SetNull)
creator User? @relation("AlbumCreator", fields: [creatorId], references: [id])
@@index([isPublished], map: "idx_photo_albums_published")
@@index([creatorId], map: "idx_photo_albums_creator")
@@map("photo_albums")
}
model PhotoUpvote {
id Int @id @default(autoincrement())
photoId Int @map("photo_id")
sessionId String @map("session_id")
createdAt DateTime @default(now()) @map("created_at")
photo Photo @relation(fields: [photoId], references: [id], onDelete: Cascade)
session Session @relation("SessionPhotoUpvotes", fields: [sessionId], references: [id])
@@unique([photoId, sessionId], map: "idx_photo_upvotes_unique")
@@index([photoId], map: "idx_photo_upvotes_photo")
@@map("photo_upvotes")
}
model PhotoComment {
id Int @id @default(autoincrement())
photoId Int @map("photo_id")
sessionId String @map("session_id")
userId String? @map("user_id")
content String @db.Text
createdAt DateTime @default(now()) @map("created_at")
safetyStatus String @default("approved") @map("safety_status")
isHidden Boolean @default(false) @map("is_hidden")
photo Photo @relation(fields: [photoId], references: [id], onDelete: Cascade)
session Session @relation("SessionPhotoComments", fields: [sessionId], references: [id])
user User? @relation("PhotoCommentUser", fields: [userId], references: [id])
@@index([photoId, createdAt], map: "idx_photo_comments_photo_date")
@@index([sessionId], map: "idx_photo_comments_session")
@@map("photo_comments")
}
model PhotoView {
id Int @id @default(autoincrement())
photoId Int @map("photo_id")
sessionId String? @map("session_id")
userId String? @map("user_id")
ipAddressHash String? @map("ip_address_hash")
viewedAt DateTime @default(now()) @map("viewed_at")
photo Photo @relation(fields: [photoId], references: [id], onDelete: Cascade)
@@index([photoId, viewedAt], map: "idx_photo_views_photo_date")
@@index([sessionId], map: "idx_photo_views_session")
@@map("photo_views")
}
model PhotoReaction {
id Int @id @default(autoincrement())
photoId Int @map("photo_id")
sessionId String @map("session_id")
reactionType String @map("reaction_type") // like, love, laugh, wow, sad, angry
createdAt DateTime @default(now()) @map("created_at")
photo Photo @relation(fields: [photoId], references: [id], onDelete: Cascade)
session Session @relation("SessionPhotoReactions", fields: [sessionId], references: [id])
@@unique([photoId, sessionId, reactionType], map: "idx_photo_reactions_unique")
@@index([photoId], map: "idx_photo_reactions_photo")
@@map("photo_reactions")
}