"use client"; import type { PortfolioProjectViewMode, PortfolioSectionType } from "@prisma/client"; import { ArrowDown, ArrowUp, CalendarDays, FolderTree, Layers3, Link2, Plus, Text, Trash2, UserRound, } from "lucide-react"; import { type ReactNode, useEffect, useRef, useState } from "react"; import { MediaFieldPicker, type MediaFieldState } from "@/components/root/media-field-picker"; import { AppCard } from "@/components/ui/app-card"; import { Badge } from "@/components/ui/badge"; import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; import { Label } from "@/components/ui/label"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from "@/components/ui/select"; import { Textarea } from "@/components/ui/textarea"; import { moveArrayItem } from "@/lib/array"; import type { MediaOption } from "@/lib/media"; import type { PortfolioCategoryView, PortfolioProjectView } from "@/lib/portfolio"; import { cn } from "@/lib/utils"; type SectionFormValue = { id?: string; type: PortfolioSectionType; titleAr: string; titleEn: string; titleDe: string; bodyAr: string; bodyEn: string; bodyDe: string; imagePath: string; media: MediaFieldState; linkUrl: string; sortOrder: number; }; type AssetFormValue = { id?: string; kind: "IMAGE"; filePath: string; fileFieldName: string; media: MediaFieldState; altAr: string; altEn: string; altDe: string; sortOrder: number; }; type ProjectFormState = { categoryId: string; slug: string; clientName: string; projectYear: string; previewUrl: string; sortOrder: string; viewMode: PortfolioProjectViewMode; isFeatured: boolean; isPublished: boolean; titleAr: string; titleEn: string; titleDe: string; serviceLabelAr: string; serviceLabelEn: string; serviceLabelDe: string; summaryAr: string; summaryEn: string; summaryDe: string; }; type PortfolioProjectFormProps = { action: (formData: FormData) => void | Promise; categories: PortfolioCategoryView[]; mediaOptions: MediaOption[]; project?: PortfolioProjectView | null; formId: string; redirectPath: string; }; const locales = [ { suffix: "Ar" as const, label: "Arabic" }, { suffix: "En" as const, label: "English" }, { suffix: "De" as const, label: "German" }, ] as const; const sectionTypeOptions: PortfolioSectionType[] = [ "RICH_TEXT", "GALLERY", "STATS", "DELIVERABLES", "LINK", ]; const viewModeOptions: Array<{ value: PortfolioProjectViewMode; label: string; description: string; }> = [ { value: "GRID", label: "Grid", description: "Balanced modular layout." }, { value: "STORY", label: "Story", description: "Narrative section flow." }, { value: "CASE_STUDY", label: "Case Study", description: "Structured challenge and result view." }, ]; function createMediaFieldState(params: { kind: "IMAGE"; assetId?: string | null; url?: string | null; label?: string | null; }): MediaFieldState { return { mode: params.assetId ? "library" : "upload", assetId: params.assetId ?? "", url: params.url ?? "", label: params.label ?? "", kind: params.kind, }; } function createInitialState( project: PortfolioProjectView | null | undefined, categories: PortfolioCategoryView[], ): ProjectFormState { return { categoryId: project?.category.id ?? categories[0]?.id ?? "", slug: project?.slug ?? "", clientName: project?.clientName ?? "", projectYear: String(project?.projectYear ?? new Date().getFullYear()), previewUrl: project?.previewUrl ?? "", sortOrder: String(project?.sortOrder ?? 0), viewMode: project?.viewMode ?? "GRID", isFeatured: project?.isFeatured ?? false, isPublished: project?.isPublished ?? false, titleAr: project?.title.ar ?? "", titleEn: project?.title.en ?? "", titleDe: project?.title.de ?? "", serviceLabelAr: project?.serviceLabel.ar ?? "", serviceLabelEn: project?.serviceLabel.en ?? "", serviceLabelDe: project?.serviceLabel.de ?? "", summaryAr: project?.summary.ar ?? "", summaryEn: project?.summary.en ?? "", summaryDe: project?.summary.de ?? "", }; } function createEmptySection(index: number): SectionFormValue { return { type: "RICH_TEXT", titleAr: "", titleEn: "", titleDe: "", bodyAr: "", bodyEn: "", bodyDe: "", imagePath: "", media: createMediaFieldState({ kind: "IMAGE" }), linkUrl: "", sortOrder: index, }; } function createEmptyAsset(index: number): AssetFormValue { return { kind: "IMAGE", filePath: "", fileFieldName: `asset-upload-${index}`, media: createMediaFieldState({ kind: "IMAGE" }), altAr: "", altEn: "", altDe: "", sortOrder: index, }; } function hasText(value: string) { return value.trim().length > 0; } function sectionReady(section: SectionFormValue) { if (!hasText(section.titleAr) || !hasText(section.titleEn) || !hasText(section.titleDe)) { return false; } if (section.type === "GALLERY") { return hasText(section.media.assetId); } if (section.type === "LINK") { return hasText(section.linkUrl); } return hasText(section.bodyAr) && hasText(section.bodyEn) && hasText(section.bodyDe); } function assetReady(asset: AssetFormValue) { return hasText(asset.media.assetId) && hasText(asset.altAr) && hasText(asset.altEn) && hasText(asset.altDe); } function LocaleInputs({ title, namePrefix, values, onChange, multiline = false, }: { title: string; namePrefix?: string; values: { Ar: string; En: string; De: string }; onChange: (key: "Ar" | "En" | "De", value: string) => void; multiline?: boolean; }) { return (

{title}

{locales.map((locale) => (

{locale.label}

{multiline ? (