admin/features/events/edit/syncEventExtras.ts
alisaza e1eaf5eff5 feat: initial ghabilee-admin backoffice app
Extract admin dashboard from ghabilee-frontend2 into a dedicated Next.js
app for backoffice.ghabilee.ir (no SEO indexing / Clarity).
2026-09-05 13:12:59 +03:30

92 lines
3.2 KiB
TypeScript

import type { FaqItem, StagedMediaItem } from '@/components/events/create/types'
import type { EventFaq, EventMedia } from '@/services/eventDetail'
import { createEventFaq, createEventMedia, deleteEventFaq, deleteEventMedia, updateEventFaq, updateEventMedia } from '@/services/events'
/**
* Diff staged wizard media against the loaded server set and apply create/
* update/delete. Poster creates run first so former posters can be deleted.
*/
export async function syncEventMedia(eventId: string, initial: EventMedia[], current: StagedMediaItem[]): Promise<void> {
const initialById = new Map(initial.map((item) => [item.id, item]))
const currentIds = new Set(current.map((item) => item.id))
const toCreate = current.filter((item) => !initialById.has(item.id))
const toUpdate = current.filter((item) => {
const existing = initialById.get(item.id)
if (!existing) return false
return (
existing.url !== item.url ||
Boolean(existing.isPoster) !== item.isPoster ||
Boolean(existing.isSquarePoster) !== item.isSquarePoster ||
(existing.sortOrder ?? 0) !== item.sortOrder
)
})
const toDelete = initial.filter((item) => !currentIds.has(item.id))
// پوسترهای جدید اول ساخته می‌شوند تا پرچم پوستر از آیتم‌های قدیمی برداشته شود
const createPosterFirst = [...toCreate].sort((a, b) => Number(b.isPoster || b.isSquarePoster) - Number(a.isPoster || a.isSquarePoster))
for (const item of createPosterFirst) {
await createEventMedia(eventId, {
mediaType: 'image',
url: item.url,
sortOrder: item.sortOrder,
isPoster: item.isPoster,
isSquarePoster: item.isSquarePoster,
})
}
for (const item of toUpdate) {
await updateEventMedia(eventId, item.id, {
url: item.url,
sortOrder: item.sortOrder,
isPoster: item.isPoster,
isSquarePoster: item.isSquarePoster,
})
}
// حذف بعد از create/update تا محدودیت «پوستر قابل حذف نیست» نقض نشود
for (const item of toDelete) {
await deleteEventMedia(eventId, item.id)
}
}
/**
* Diff staged FAQs against the loaded server set. FaqEditor only supports
* add/remove (not in-place edit), so updates cover sortOrder if ids persist.
*/
export async function syncEventFaqs(eventId: string, initial: EventFaq[], current: FaqItem[]): Promise<void> {
const initialById = new Map(initial.map((item) => [item.id, item]))
const currentIds = new Set(current.map((item) => item.id))
for (let index = 0; index < current.length; index += 1) {
const faq = current[index]
const existing = initialById.get(faq.id)
if (!existing) {
await createEventFaq(eventId, {
question: faq.question,
answer: faq.answer,
sortOrder: index,
})
continue
}
if (existing.question !== faq.question || existing.answer !== faq.answer || (existing.sortOrder ?? 0) !== index) {
await updateEventFaq(eventId, faq.id, {
question: faq.question,
answer: faq.answer,
sortOrder: index,
})
}
}
for (const item of initial) {
if (!currentIds.has(item.id)) {
await deleteEventFaq(eventId, item.id)
}
}
}