Files
spotlightcam/backend/prisma/schema.prisma
Radosław Gierwiało 48f9dfe1b4 feat: add social media links to user profile
- Add YouTube, Instagram, Facebook, and TikTok URL fields to User model
- Create database migration for social media link columns
- Add custom validators to ensure URLs contain correct domains
- Update profile page with social media input fields
- Include social media URLs in GET /api/users/me response
- Add icons for each social platform in the UI

Users can now add links to their social media profiles. Each field
validates that the URL contains the appropriate domain (e.g.,
instagram.com for Instagram, youtube.com/youtu.be for YouTube).
2025-11-13 20:47:57 +01:00

152 lines
5.5 KiB
Plaintext

// Prisma schema for spotlight.cam
// Database: PostgreSQL 15
generator client {
provider = "prisma-client-js"
binaryTargets = ["native", "linux-musl-openssl-3.0.x"]
}
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}
// Users table
model User {
id Int @id @default(autoincrement())
username String @unique @db.VarChar(50)
email String @unique @db.VarChar(255)
passwordHash String @map("password_hash") @db.VarChar(255)
// WSDC Integration (Phase 1.5)
firstName String? @map("first_name") @db.VarChar(100)
lastName String? @map("last_name") @db.VarChar(100)
wsdcId String? @unique @map("wsdc_id") @db.VarChar(20)
// Social Media Links
youtubeUrl String? @map("youtube_url") @db.VarChar(255)
instagramUrl String? @map("instagram_url") @db.VarChar(255)
facebookUrl String? @map("facebook_url") @db.VarChar(255)
tiktokUrl String? @map("tiktok_url") @db.VarChar(255)
// Email Verification (Phase 1.5)
emailVerified Boolean @default(false) @map("email_verified")
verificationToken String? @unique @map("verification_token") @db.VarChar(255)
verificationCode String? @map("verification_code") @db.VarChar(6)
verificationTokenExpiry DateTime? @map("verification_token_expiry")
// Password Reset (Phase 1.5)
resetToken String? @unique @map("reset_token") @db.VarChar(255)
resetTokenExpiry DateTime? @map("reset_token_expiry")
avatar String? @db.VarChar(255)
createdAt DateTime @default(now()) @map("created_at")
updatedAt DateTime @updatedAt @map("updated_at")
// Relations
messages Message[]
matchesAsUser1 Match[] @relation("MatchUser1")
matchesAsUser2 Match[] @relation("MatchUser2")
ratingsGiven Rating[] @relation("RaterRatings")
ratingsReceived Rating[] @relation("RatedRatings")
@@map("users")
}
// Events table (dance events from worldsdc.com)
model Event {
id Int @id @default(autoincrement())
name String @db.VarChar(255)
location String @db.VarChar(255)
startDate DateTime @map("start_date") @db.Date
endDate DateTime @map("end_date") @db.Date
worldsdcId String? @unique @map("worldsdc_id") @db.VarChar(100)
participantsCount Int @default(0) @map("participants_count")
description String? @db.Text
createdAt DateTime @default(now()) @map("created_at")
// Relations
chatRooms ChatRoom[]
matches Match[]
@@map("events")
}
// Chat rooms (event chat and private 1:1 chat)
model ChatRoom {
id Int @id @default(autoincrement())
eventId Int? @map("event_id")
type String @db.VarChar(20) // 'event' or 'private'
createdAt DateTime @default(now()) @map("created_at")
// Relations
event Event? @relation(fields: [eventId], references: [id])
messages Message[]
matches Match[]
@@map("chat_rooms")
}
// Messages (text messages and video links)
model Message {
id Int @id @default(autoincrement())
roomId Int @map("room_id")
userId Int @map("user_id")
content String @db.Text
type String @db.VarChar(20) // 'text', 'link', 'video'
createdAt DateTime @default(now()) @map("created_at")
// Relations
room ChatRoom @relation(fields: [roomId], references: [id], onDelete: Cascade)
user User @relation(fields: [userId], references: [id])
@@index([roomId])
@@index([createdAt])
@@map("messages")
}
// Matches (pairs of users for collaboration)
model Match {
id Int @id @default(autoincrement())
user1Id Int @map("user1_id")
user2Id Int @map("user2_id")
eventId Int @map("event_id")
roomId Int? @map("room_id")
status String @default("pending") @db.VarChar(20) // 'pending', 'accepted', 'completed'
createdAt DateTime @default(now()) @map("created_at")
// Relations
user1 User @relation("MatchUser1", fields: [user1Id], references: [id])
user2 User @relation("MatchUser2", fields: [user2Id], references: [id])
event Event @relation(fields: [eventId], references: [id])
room ChatRoom? @relation(fields: [roomId], references: [id])
ratings Rating[]
@@unique([user1Id, user2Id, eventId])
@@index([user1Id])
@@index([user2Id])
@@index([eventId])
@@map("matches")
}
// Ratings (user ratings after collaboration)
model Rating {
id Int @id @default(autoincrement())
matchId Int @map("match_id")
raterId Int @map("rater_id")
ratedId Int @map("rated_id")
score Int // 1-5
comment String? @db.Text
wouldCollaborateAgain Boolean @default(false) @map("would_collaborate_again")
createdAt DateTime @default(now()) @map("created_at")
// Relations
match Match @relation(fields: [matchId], references: [id])
rater User @relation("RaterRatings", fields: [raterId], references: [id])
rated User @relation("RatedRatings", fields: [ratedId], references: [id])
@@unique([matchId, raterId, ratedId])
@@index([ratedId])
@@map("ratings")
}