"use client"; import type { MediaKind, PortfolioAssetKind, PortfolioSectionType } from "@prisma/client"; import { ArrowDown, ArrowUp, Plus, Trash2 } from "lucide-react"; import { useState } from "react"; import { MediaFieldPicker, type MediaFieldState } from "@/components/root/media-field-picker"; import { AppCard } from "@/components/ui/app-card"; import { Button } from "@/components/ui/button"; import { CardContent, CardHeader, CardTitle } from "@/components/ui/card"; import { Input } from "@/components/ui/input"; import { Label } from "@/components/ui/label"; import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"; import { Textarea } from "@/components/ui/textarea"; import { moveArrayItem } from "@/lib/array"; import type { MediaOption } from "@/lib/media"; import type { PortfolioCategoryView, PortfolioProjectView } from "@/lib/portfolio"; 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: PortfolioAssetKind; filePath: string; fileFieldName: string; media: MediaFieldState; altAr: string; altEn: string; altDe: string; sortOrder: number; }; type PortfolioProjectFormProps = { action: (formData: FormData) => void | Promise; categories: PortfolioCategoryView[]; mediaOptions: MediaOption[]; project?: PortfolioProjectView | null; redirectPath: string; submitLabel: string; }; const sectionTypeOptions: PortfolioSectionType[] = [ "RICH_TEXT", "GALLERY", "STATS", "DELIVERABLES", "LINK", ]; const assetKindOptions: PortfolioAssetKind[] = ["IMAGE", "DOCUMENT"]; const localeFieldConfig = [ { key: "ar" as const, suffix: "Ar" as const, label: "AR" }, { key: "en" as const, suffix: "En" as const, label: "EN" }, { key: "de" as const, suffix: "De" as const, label: "DE" }, ]; function createMediaFieldState(params: { kind: MediaKind; assetId?: string | null; url?: string | null; label?: string | null; }): MediaFieldState { return { mode: params.assetId ? "library" : params.url ? "external" : "upload", assetId: params.assetId ?? "", url: params.url ?? "", label: params.label ?? "", kind: params.kind, }; } 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, }; } export function PortfolioProjectForm({ action, categories, mediaOptions, project, redirectPath, submitLabel, }: PortfolioProjectFormProps) { const [coverMedia, setCoverMedia] = useState( createMediaFieldState({ kind: "IMAGE", assetId: project?.coverMediaAssetId, url: project?.coverImagePath, label: project?.title.de ?? project?.title.en ?? project?.title.ar ?? "", }), ); const [sections, setSections] = useState( project?.sections.length ? project.sections.map((section, index) => ({ id: section.id, type: section.type, titleAr: section.title.ar, titleEn: section.title.en, titleDe: section.title.de, bodyAr: section.body.ar, bodyEn: section.body.en, bodyDe: section.body.de, imagePath: section.imagePath ?? "", media: createMediaFieldState({ kind: "IMAGE", assetId: section.mediaAssetId, url: section.imagePath, label: section.title.de || section.title.en || section.title.ar, }), linkUrl: section.linkUrl ?? "", sortOrder: index, })) : [createEmptySection(0)], ); const [assets, setAssets] = useState( project?.assets.length ? project.assets.map((asset, index) => ({ id: asset.id, kind: asset.kind, filePath: asset.filePath, fileFieldName: `asset-upload-${index}`, media: createMediaFieldState({ kind: asset.kind, assetId: asset.mediaAssetId, url: asset.filePath, label: asset.alt.de || asset.alt.en || asset.alt.ar, }), altAr: asset.alt.ar, altEn: asset.alt.en, altDe: asset.alt.de, sortOrder: index, })) : [], ); const sectionsPayload = JSON.stringify( sections.map((section, index) => ({ ...section, sortOrder: index, })), ); const assetsPayload = JSON.stringify( assets.map((asset, index) => ({ ...asset, sortOrder: index, })), ); return (
Project Basics
Localized Content {localeFieldConfig.map((locale) => ( {locale.label} ))} {localeFieldConfig.map((locale) => (
{locale.key === "ar" ? "Arabic content for the Arabic website." : locale.key === "en" ? "English content for the English website." : "German content for the German website."}