Files
marmarislocal/lib/mockDb.ts
T
2026-07-12 20:18:55 +03:00

676 lines
25 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { db } from './db'
export interface Category {
id: string
slug: string
nameTr: string
nameEn: string
nameRu: string
}
export interface Neighborhood {
id: string
slug: string
nameTr: string
nameEn: string
nameRu: string
}
export interface Gallery {
id: string
listingId: string
url: string
}
export interface Listing {
id: string
slug: string
categoryId: string
neighborhoodId: string
city: string
nameTr: string
nameEn: string
nameRu: string
descriptionTr: string
descriptionEn: string
descriptionRu: string
address: string
phone?: string | null
whatsapp?: string | null
website?: string | null
instagram?: string | null
priceRange: number
rating?: number | null
isLocalApproved: boolean
latitude?: number | null
longitude?: number | null
openingHours?: any | null
images: Gallery[]
category?: Category
neighborhood?: Neighborhood
createdAt: Date
updatedAt: Date
deletedAt?: Date | null
}
export interface BusinessSubmission {
id: string
businessName: string
categoryId: string
neighborhoodId: string
address: string
phone?: string | null
whatsapp?: string | null
description: string
contactName: string
contactEmail: string
imageUrl?: string | null
status: string
createdAt: Date
updatedAt: Date
}
export interface ContactMessage {
id: string
name: string
email: string
subject: string
message: string
isRead: boolean
createdAt: Date
updatedAt: Date
}
const globalForMockDb = globalThis as unknown as {
categories: Category[]
neighborhoods: Neighborhood[]
listings: Listing[]
submissions: BusinessSubmission[]
messages: ContactMessage[]
initialized: boolean
}
if (!globalForMockDb.initialized) {
globalForMockDb.categories = [
{ id: 'cat-1', slug: 'restoran', nameTr: 'Restoran', nameEn: 'Restaurant', nameRu: 'Ресторан' },
{ id: 'cat-2', slug: 'apart', nameTr: 'Apart', nameEn: 'Apart Hotel', nameRu: 'Апарт-отель' },
{ id: 'cat-3', slug: 'isletme', nameTr: 'İşletme & Hizmet', nameEn: 'Business & Service', nameRu: 'Бизнес и Услуги' }
]
globalForMockDb.neighborhoods = [
{ id: 'neigh-1', slug: 'yat-limani', nameTr: 'Yat Limanı', nameEn: 'Marina', nameRu: 'Марина' },
{ id: 'neigh-2', slug: 'icmeler', nameTr: 'İçmeler', nameEn: 'Icmeler', nameRu: 'Ичмелер' },
{ id: 'neigh-3', slug: 'armutalan', nameTr: 'Armutalan', nameEn: 'Armutalan', nameRu: 'Армуталан' },
{ id: 'neigh-4', slug: 'siteler', nameTr: 'Siteler', nameEn: 'Siteler', nameRu: 'Сителер' },
{ id: 'neigh-5', slug: 'turunc', nameTr: 'Turunç', nameEn: 'Turunc', nameRu: 'Турунч' }
]
globalForMockDb.submissions = []
globalForMockDb.messages = []
// Pre-populate with realistic Marmaris data
globalForMockDb.listings = [
{
id: 'list-1',
slug: 'iskele-balik-ocakbasi',
categoryId: 'cat-1',
neighborhoodId: 'neigh-1',
city: 'marmaris',
nameTr: 'İskele Balık Ocakbaşı',
nameEn: 'Iskele Fish & Grill',
nameRu: 'Рыбный Гриль Искеле',
descriptionTr: 'Yat Limanı\'nda taze Ege balıkları ve geleneksel meze çeşitleriyle yerel lezzet durağınız. Mükemmel körfez manzarası eşliğinde akşam yemeği.',
descriptionEn: 'Your local taste stop at the Marina with fresh Aegean fish and traditional appetizers. Dinner accompanied by excellent bay views.',
descriptionRu: 'Ваша местная гастрономическая остановка в Марине со свежей эгейской рыбой и традиционными закусками. Ужин в сопровождении великолепного вида на залив.',
address: 'Yat Limanı No:12, Marmaris',
phone: '+90 252 412 34 56',
whatsapp: '+90 532 123 45 67',
website: 'https://iskelemarmaris.com',
instagram: 'https://instagram.com/iskele_marmaris',
priceRange: 3,
rating: 4.8,
isLocalApproved: true,
latitude: 36.8524,
longitude: 28.2741,
openingHours: { all: '12:00 - 00:00' },
images: [
{ id: 'img-1-1', listingId: 'list-1', url: 'https://images.unsplash.com/photo-1519708227418-c8fd9a32b7a2?w=800&auto=format&fit=crop&q=80' },
{ id: 'img-1-2', listingId: 'list-1', url: 'https://images.unsplash.com/photo-1555396273-367ea4eb4db5?w=800&auto=format&fit=crop&q=80' }
],
createdAt: new Date(),
updatedAt: new Date()
},
{
id: 'list-2',
slug: 'mavi-beyaz-restoran',
categoryId: 'cat-1',
neighborhoodId: 'neigh-1',
city: 'marmaris',
nameTr: 'Mavi Beyaz Restoran',
nameEn: 'Blue White Restaurant',
nameRu: 'Ресторан Сине-Белый',
descriptionTr: 'Ege kıyılarının esintisini taşıyan, deniz ürünleri ağırlıklı menüsü ve gün batımı eşliğindeki eşsiz mezeleriyle ünlüdür.',
descriptionEn: 'Famous for its seafood-oriented menu carrying the breeze of the Aegean coasts and unique appetizers accompanied by sunset.',
descriptionRu: 'Славится своим меню из морепродуктов, несущим бриз Эгейского побережья, и уникальными закусками на фоне заката.',
address: 'Kordon Caddesi No:45, Yat Limanı, Marmaris',
phone: '+90 252 412 78 90',
whatsapp: '+90 533 987 65 43',
website: 'https://mavibeyazmarmaris.com',
instagram: 'https://instagram.com/mavibeyaz_marmaris',
priceRange: 2,
rating: 4.5,
isLocalApproved: true,
latitude: 36.8530,
longitude: 28.2725,
openingHours: { all: '11:00 - 23:30' },
images: [
{ id: 'img-2-1', listingId: 'list-2', url: 'https://images.unsplash.com/photo-1414235077428-338989a2e8c0?w=800&auto=format&fit=crop&q=80' }
],
createdAt: new Date(),
updatedAt: new Date()
},
{
id: 'list-3',
slug: 'dostlar-kebap',
categoryId: 'cat-1',
neighborhoodId: 'neigh-3',
city: 'marmaris',
nameTr: 'Dostlar Kebap',
nameEn: 'Dostlar Kebab House',
nameRu: 'Кебаб Хаус Достлар',
descriptionTr: 'Marmaris Armutalan\'da yıllardır değişmeyen lezzetiyle gerçek ocakbaşı ve kebap deneyimi sunan samimi bir mahalle restoranı.',
descriptionEn: 'A cozy neighborhood restaurant offering real grill and kebab experience with its unchanged taste for years in Armutalan, Marmaris.',
descriptionRu: 'Уютный районный ресторан, предлагающий настоящий гриль и кебаб с неизменным вкусом на протяжении многих лет в Армуталане, Мармарис.',
address: 'Vatan Caddesi No:18, Armutalan, Marmaris',
phone: '+90 252 413 11 22',
whatsapp: null,
website: null,
instagram: 'https://instagram.com/dostlarkebap_marmaris',
priceRange: 1,
rating: 4.7,
isLocalApproved: false,
latitude: 36.8488,
longitude: 28.2450,
openingHours: { all: '11:00 - 22:00' },
images: [
{ id: 'img-3-1', listingId: 'list-3', url: 'https://images.unsplash.com/photo-1544025162-d76694265947?w=800&auto=format&fit=crop&q=80' }
],
createdAt: new Date(),
updatedAt: new Date()
},
{
id: 'list-4',
slug: 'zeytin-bahcesi-apart',
categoryId: 'cat-2',
neighborhoodId: 'neigh-3',
city: 'marmaris',
nameTr: 'Zeytin Bahçesi Apart',
nameEn: 'Olive Garden Apart',
nameRu: 'Апарт Оливковый Сад',
descriptionTr: 'Zeytin ağaçları arasında, sakin ve huzurlu bir ortamda ailece tatil yapmak isteyenler için tasarlanmış geniş mutfaklı apart daireler.',
descriptionEn: 'Spacious apart apartments with kitchens designed for families who want to have a holiday in a quiet and peaceful environment among olive trees.',
descriptionRu: 'Просторные апартаменты с кухнями, предназначенные для семей, желающих отдохнуть в тихой и спокойной обстановке среди оливковых деревьев.',
address: 'Zeytinlik Sokak No:5, Armutalan, Marmaris',
phone: '+90 252 413 55 66',
whatsapp: '+90 535 555 66 77',
website: 'https://zeytinbahcesiapart.com',
instagram: null,
priceRange: 2,
rating: 4.6,
isLocalApproved: true,
latitude: 36.8510,
longitude: 28.2415,
openingHours: null,
images: [
{ id: 'img-4-1', listingId: 'list-4', url: 'https://images.unsplash.com/photo-1566073771259-6a8506099945?w=800&auto=format&fit=crop&q=80' },
{ id: 'img-4-2', listingId: 'list-4', url: 'https://images.unsplash.com/photo-1520250497591-112f2f40a3f4?w=800&auto=format&fit=crop&q=80' }
],
createdAt: new Date(),
updatedAt: new Date()
},
{
id: 'list-5',
slug: 'deniz-apart',
categoryId: 'cat-2',
neighborhoodId: 'neigh-4',
city: 'marmaris',
nameTr: 'Deniz Apart',
nameEn: 'Sea Apart Hotel',
nameRu: 'Апарт-отель Дениз',
descriptionTr: 'Denize sadece 100 metre mesafede, bütçe dostu fiyatları ve güler yüzlü yerel işletme sahibiyle Marmaris\'te sıcak konaklama.',
descriptionEn: 'Cozy accommodation in Marmaris, just 100 meters from the sea, with budget-friendly prices and a friendly local owner.',
descriptionRu: 'Уютное жилье в Мармарисе, всего в 100 метрах от моря, с доступными ценами и дружелюбным местным владельцем.',
address: 'Sahil Yolu Caddesi No:88, Siteler, Marmaris',
phone: '+90 252 417 88 99',
whatsapp: null,
website: null,
instagram: null,
priceRange: 1,
rating: 4.2,
isLocalApproved: false,
latitude: 36.8375,
longitude: 28.2580,
openingHours: null,
images: [
{ id: 'img-5-1', listingId: 'list-5', url: 'https://images.unsplash.com/photo-1582719478250-c89cae4dc85b?w=800&auto=format&fit=crop&q=80' }
],
createdAt: new Date(),
updatedAt: new Date()
},
{
id: 'list-6',
slug: 'marina-dalis-merkezi',
categoryId: 'cat-3',
neighborhoodId: 'neigh-2',
city: 'marmaris',
nameTr: 'Marina Dalış Merkezi',
nameEn: 'Marina Diving Center',
nameRu: 'Дайвинг-центр Марина',
descriptionTr: 'Marmaris\'in eşsiz koylarında profesyonel eğitmenler eşliğinde tüplü dalış deneyimi. Başlangıç seviyesinden PADI sertifikasyonuna kadar hizmet.',
descriptionEn: 'Scuba diving experience in unique bays of Marmaris accompanied by professional instructors. Service from discovery dive to PADI certification.',
descriptionRu: 'Опыт подводного плавания в уникальных бухтах Мармариса в сопровождении профессиональных инструкторов. Услуги от ознакомительного погружения до сертификации PADI.',
address: 'Liman Yolu No:32, İçmeler, Marmaris',
phone: '+90 252 455 22 33',
whatsapp: '+90 536 777 88 99',
website: 'https://marinadivingmarmaris.com',
instagram: 'https://instagram.com/marinadiving_marmaris',
priceRange: 3,
rating: 4.9,
isLocalApproved: true,
latitude: 36.8020,
longitude: 28.2320,
openingHours: { all: '08:30 - 19:30' },
images: [
{ id: 'img-6-1', listingId: 'list-6', url: 'https://images.unsplash.com/photo-1544551763-46a013bb70d5?w=800&auto=format&fit=crop&q=80' }
],
createdAt: new Date(),
updatedAt: new Date()
},
{
id: 'list-7',
slug: 'ege-ruzgari-tekne-kiralama',
categoryId: 'cat-3',
neighborhoodId: 'neigh-1',
city: 'marmaris',
nameTr: 'Ege Rüzgarı Tekne Kiralama',
nameEn: 'Aegean Wind Boat Rental',
nameRu: 'Аренда Лодок Эгейский Ветер',
descriptionTr: 'Kaptanlı veya kaptansız günlük ve haftalık özel tekne kiralama hizmeti. Marmaris koylarını kendi rotanızda özgürce keşfedin.',
descriptionEn: 'Daily and weekly private boat rental service with or without skipper. Discover Marmaris bays freely on your own route.',
descriptionRu: 'Ежедневная и еженедельная аренда частных лодок со шкипером или без. Откройте для себя бухты Мармариса свободно по собственному маршруту.',
address: 'Yat Limanı G İskelesi, Marmaris',
phone: '+90 532 999 88 77',
whatsapp: '+90 532 999 88 77',
website: 'https://egeruzgariboat.com',
instagram: 'https://instagram.com/egeruzgariboat',
priceRange: 3,
rating: 4.8,
isLocalApproved: true,
latitude: 36.8528,
longitude: 28.2755,
openingHours: { all: '08:00 - 21:00' },
images: [
{ id: 'img-7-1', listingId: 'list-7', url: 'https://images.unsplash.com/photo-1567899378494-47b22a2ae96a?w=800&auto=format&fit=crop&q=80' }
],
createdAt: new Date(),
updatedAt: new Date()
},
{
id: 'list-8',
slug: 'marmaris-transfer-tours',
categoryId: 'cat-3',
neighborhoodId: 'neigh-3',
city: 'marmaris',
nameTr: 'Marmaris VIP Transfer & Tur',
nameEn: 'Marmaris VIP Transfer & Tours',
nameRu: 'Marmaris VIP Трансфер и Туры',
descriptionTr: 'Dalaman Havalimanı transferleri ve Marmaris çevresindeki tarihi/doğal alanlara özel konforlu turlar. Güvenilir ve lüks taşımacılık.',
descriptionEn: 'Dalaman Airport transfers and comfortable private tours to historical/natural areas around Marmaris. Reliable and luxurious transportation.',
descriptionRu: 'Трансфер из аэропорта Даламан и комфортабельные частные туры по историческим и природным местам вокруг Мармариса. Надежный и роскошный транспорт.',
address: 'Atatürk Caddesi No:102, Armutalan, Marmaris',
phone: '+90 252 413 77 88',
whatsapp: '+90 541 333 44 55',
website: 'https://marmarisviptransfer.com',
instagram: null,
priceRange: 2,
rating: 4.6,
isLocalApproved: false,
latitude: 36.8495,
longitude: 28.2430,
openingHours: { all: '24 Hours Open' },
images: [
{ id: 'img-8-1', listingId: 'list-8', url: 'https://images.unsplash.com/photo-1549317661-bd32c8ce0db2?w=800&auto=format&fit=crop&q=80' }
],
createdAt: new Date(),
updatedAt: new Date()
}
]
globalForMockDb.initialized = true
}
export const mockDb = {
// Config helpers
isMock: () => process.env.USE_MOCK === 'true',
// Categories
async getCategories() {
if (this.isMock()) {
return globalForMockDb.categories
}
return db.category.findMany({ orderBy: { nameTr: 'asc' } })
},
async getCategoryBySlug(slug: string) {
if (this.isMock()) {
return globalForMockDb.categories.find(c => c.slug === slug) || null
}
return db.category.findUnique({ where: { slug } })
},
async createCategory(data: { slug: string; nameTr: string; nameEn: string; nameRu: string }) {
if (this.isMock()) {
const newCat = { id: `cat-${Date.now()}`, ...data }
globalForMockDb.categories.push(newCat)
return newCat
}
return db.category.create({ data })
},
async updateCategory(id: string, data: { slug: string; nameTr: string; nameEn: string; nameRu: string }) {
if (this.isMock()) {
const idx = globalForMockDb.categories.findIndex(c => c.id === id)
if (idx !== -1) {
globalForMockDb.categories[idx] = { ...globalForMockDb.categories[idx], ...data }
return globalForMockDb.categories[idx]
}
return null
}
return db.category.update({ where: { id }, data })
},
// Neighborhoods
async getNeighborhoods() {
if (this.isMock()) {
return globalForMockDb.neighborhoods
}
return db.neighborhood.findMany({ orderBy: { nameTr: 'asc' } })
},
async getNeighborhoodBySlug(slug: string) {
if (this.isMock()) {
return globalForMockDb.neighborhoods.find(n => n.slug === slug) || null
}
return db.neighborhood.findUnique({ where: { slug } })
},
async createNeighborhood(data: { slug: string; nameTr: string; nameEn: string; nameRu: string }) {
if (this.isMock()) {
const newNeigh = { id: `neigh-${Date.now()}`, ...data }
globalForMockDb.neighborhoods.push(newNeigh)
return newNeigh
}
return db.neighborhood.create({ data })
},
async updateNeighborhood(id: string, data: { slug: string; nameTr: string; nameEn: string; nameRu: string }) {
if (this.isMock()) {
const idx = globalForMockDb.neighborhoods.findIndex(n => n.id === id)
if (idx !== -1) {
globalForMockDb.neighborhoods[idx] = { ...globalForMockDb.neighborhoods[idx], ...data }
return globalForMockDb.neighborhoods[idx]
}
return null
}
return db.neighborhood.update({ where: { id }, data })
},
// Listings
async getListings(filters?: {
categoryId?: string
neighborhoodId?: string
priceRange?: number
isLocalApproved?: boolean
search?: string
}) {
if (this.isMock()) {
let result = globalForMockDb.listings.filter(l => !l.deletedAt)
if (filters) {
if (filters.categoryId) result = result.filter(l => l.categoryId === filters.categoryId)
if (filters.neighborhoodId) result = result.filter(l => l.neighborhoodId === filters.neighborhoodId)
if (filters.priceRange) result = result.filter(l => l.priceRange === filters.priceRange)
if (filters.isLocalApproved !== undefined) result = result.filter(l => l.isLocalApproved === filters.isLocalApproved)
if (filters.search) {
const s = filters.search.toLowerCase()
result = result.filter(l =>
l.nameTr.toLowerCase().includes(s) ||
l.nameEn.toLowerCase().includes(s) ||
l.nameRu.toLowerCase().includes(s) ||
l.address.toLowerCase().includes(s)
)
}
}
return result.map(l => ({
...l,
category: globalForMockDb.categories.find(c => c.id === l.categoryId),
neighborhood: globalForMockDb.neighborhoods.find(n => n.id === l.neighborhoodId)
}))
}
const where: any = { deletedAt: null }
if (filters) {
if (filters.categoryId) where.categoryId = filters.categoryId
if (filters.neighborhoodId) where.neighborhoodId = filters.neighborhoodId
if (filters.priceRange) where.priceRange = filters.priceRange
if (filters.isLocalApproved !== undefined) where.isLocalApproved = filters.isLocalApproved
if (filters.search) {
where.OR = [
{ nameTr: { contains: filters.search, mode: 'insensitive' } },
{ nameEn: { contains: filters.search, mode: 'insensitive' } },
{ nameRu: { contains: filters.search, mode: 'insensitive' } },
{ address: { contains: filters.search, mode: 'insensitive' } },
]
}
}
return db.listing.findMany({
where,
include: { category: true, neighborhood: true, images: true },
orderBy: { createdAt: 'desc' }
})
},
async getListingBySlug(slug: string) {
if (this.isMock()) {
const listing = globalForMockDb.listings.find(l => l.slug === slug && !l.deletedAt)
if (!listing) return null
return {
...listing,
category: globalForMockDb.categories.find(c => c.id === listing.categoryId),
neighborhood: globalForMockDb.neighborhoods.find(n => n.id === listing.neighborhoodId)
}
}
return db.listing.findUnique({
where: { slug },
include: { category: true, neighborhood: true, images: true }
})
},
async getListingById(id: string) {
if (this.isMock()) {
const listing = globalForMockDb.listings.find(l => l.id === id && !l.deletedAt)
if (!listing) return null
return {
...listing,
category: globalForMockDb.categories.find(c => c.id === listing.categoryId),
neighborhood: globalForMockDb.neighborhoods.find(n => n.id === listing.neighborhoodId)
}
}
return db.listing.findUnique({
where: { id },
include: { category: true, neighborhood: true, images: true }
})
},
async createListing(data: Omit<Listing, 'id' | 'images' | 'createdAt' | 'updatedAt'> & { images?: string[] }) {
const { images, category, neighborhood, ...rest } = data
if (this.isMock()) {
const newId = `list-${Date.now()}`
const gallery = (images || []).map((url, i) => ({ id: `img-${newId}-${i}`, listingId: newId, url }))
const newListing: Listing = {
id: newId,
...rest,
images: gallery,
createdAt: new Date(),
updatedAt: new Date()
}
globalForMockDb.listings.unshift(newListing)
return newListing
}
return db.listing.create({
data: {
...rest,
images: images ? { create: images.map(url => ({ url })) } : undefined
},
include: { images: true }
})
},
async updateListing(id: string, data: Partial<Omit<Listing, 'id' | 'images' | 'createdAt' | 'updatedAt'>> & { images?: string[] }) {
const { images, category, neighborhood, ...rest } = data
if (this.isMock()) {
const idx = globalForMockDb.listings.findIndex(l => l.id === id)
if (idx !== -1) {
const oldListing = globalForMockDb.listings[idx]
const updatedGallery = images
? images.map((url, i) => ({ id: `img-${id}-${i}`, listingId: id, url }))
: oldListing.images
const updated = {
...oldListing,
...rest,
images: updatedGallery,
updatedAt: new Date()
} as Listing
globalForMockDb.listings[idx] = updated
return updated
}
return null
}
if (images) {
await db.gallery.deleteMany({ where: { listingId: id } })
}
return db.listing.update({
where: { id },
data: {
...rest,
images: images ? { create: images.map(url => ({ url })) } : undefined
},
include: { images: true }
})
},
async deleteListing(id: string) {
if (this.isMock()) {
const idx = globalForMockDb.listings.findIndex(l => l.id === id)
if (idx !== -1) {
globalForMockDb.listings[idx].deletedAt = new Date()
return true
}
return false
}
await db.listing.update({
where: { id },
data: { deletedAt: new Date() }
})
return true
},
// Business Submissions
async getSubmissions() {
if (this.isMock()) {
return globalForMockDb.submissions.sort((a, b) => b.createdAt.getTime() - a.createdAt.getTime())
}
return db.businessSubmission.findMany({ orderBy: { createdAt: 'desc' } })
},
async createSubmission(data: Omit<BusinessSubmission, 'id' | 'status' | 'createdAt' | 'updatedAt'>) {
if (this.isMock()) {
const newSub: BusinessSubmission = {
id: `sub-${Date.now()}`,
...data,
status: 'PENDING',
createdAt: new Date(),
updatedAt: new Date()
}
globalForMockDb.submissions.push(newSub)
return newSub
}
return db.businessSubmission.create({ data: { ...data, status: 'PENDING' } })
},
async updateSubmissionStatus(id: string, status: 'APPROVED' | 'REJECTED') {
if (this.isMock()) {
const idx = globalForMockDb.submissions.findIndex(s => s.id === id)
if (idx !== -1) {
globalForMockDb.submissions[idx].status = status
globalForMockDb.submissions[idx].updatedAt = new Date()
return globalForMockDb.submissions[idx]
}
return null
}
return db.businessSubmission.update({
where: { id },
data: { status }
})
},
async getSubmissionById(id: string) {
if (this.isMock()) {
return globalForMockDb.submissions.find(s => s.id === id) || null
}
return db.businessSubmission.findUnique({ where: { id } })
},
// Contact Messages
async getMessages() {
if (this.isMock()) {
return globalForMockDb.messages.sort((a, b) => b.createdAt.getTime() - a.createdAt.getTime())
}
return db.contactMessage.findMany({ orderBy: { createdAt: 'desc' } })
},
async createMessage(data: Omit<ContactMessage, 'id' | 'isRead' | 'createdAt' | 'updatedAt'>) {
if (this.isMock()) {
const newMsg: ContactMessage = {
id: `msg-${Date.now()}`,
...data,
isRead: false,
createdAt: new Date(),
updatedAt: new Date()
}
globalForMockDb.messages.push(newMsg)
return newMsg
}
return db.contactMessage.create({ data: { ...data, isRead: false } })
},
async markMessageAsRead(id: string) {
if (this.isMock()) {
const idx = globalForMockDb.messages.findIndex(m => m.id === id)
if (idx !== -1) {
globalForMockDb.messages[idx].isRead = true
globalForMockDb.messages[idx].updatedAt = new Date()
return globalForMockDb.messages[idx]
}
return null
}
return db.contactMessage.update({
where: { id },
data: { isRead: true }
})
}
}