import type { PortfolioProjectViewMode, PortfolioSectionType } from "@prisma/client"; export type PortfolioWizardStep = "basics" | "content" | "sections" | "assets"; export type PortfolioWizardStepState = { key: PortfolioWizardStep; complete: boolean; summary: string; }; type ProjectBasicsProgressInput = { categoryId: string; slug: string; clientName: string; projectYear: string; sortOrder: string; viewMode: PortfolioProjectViewMode; }; type ProjectContentProgressInput = { titleAr: string; titleEn: string; titleDe: string; serviceLabelAr: string; serviceLabelEn: string; serviceLabelDe: string; summaryAr: string; summaryEn: string; summaryDe: string; }; type ProjectSectionProgressInput = { type: PortfolioSectionType; titleAr: string; titleEn: string; titleDe: string; bodyAr: string; bodyEn: string; bodyDe: string; linkUrl: string; mediaAssetId: string; }; type ProjectAssetProgressInput = { mediaAssetId: string; altAr: string; altEn: string; altDe: string; }; type PortfolioWizardProgressInput = { basics: ProjectBasicsProgressInput; content: ProjectContentProgressInput; sections: ProjectSectionProgressInput[]; assets: ProjectAssetProgressInput[]; }; function hasText(value: string) { return value.trim().length > 0; } function isValidSlug(value: string) { return /^[a-z0-9]+(?:-[a-z0-9]+)*$/.test(value.trim()); } function isValidYear(value: string) { const year = Number(value); return Number.isInteger(year) && year >= 2000 && year <= 2100; } function isValidSortOrder(value: string) { const sortOrder = Number(value); return Number.isInteger(sortOrder) && sortOrder >= 0 && sortOrder <= 9999; } export function isPortfolioSectionReady(section: ProjectSectionProgressInput) { const hasTitles = hasText(section.titleAr) && hasText(section.titleEn) && hasText(section.titleDe); if (!hasTitles) { return false; } if (section.type === "GALLERY") { return hasText(section.mediaAssetId); } if (section.type === "LINK") { return hasText(section.linkUrl); } return hasText(section.bodyAr) && hasText(section.bodyEn) && hasText(section.bodyDe); } export function isPortfolioAssetReady(asset: ProjectAssetProgressInput) { return ( hasText(asset.mediaAssetId) && hasText(asset.altAr) && hasText(asset.altEn) && hasText(asset.altDe) ); } export function getPortfolioWizardProgress( input: PortfolioWizardProgressInput, ): PortfolioWizardStepState[] { const completedSections = input.sections.filter(isPortfolioSectionReady).length; const completedAssets = input.assets.filter(isPortfolioAssetReady).length; return [ { key: "basics", complete: hasText(input.basics.categoryId) && isValidSlug(input.basics.slug) && hasText(input.basics.clientName) && isValidYear(input.basics.projectYear) && isValidSortOrder(input.basics.sortOrder) && Boolean(input.basics.viewMode), summary: "Category, slug, client, year, and order are set.", }, { key: "content", complete: hasText(input.content.titleAr) && hasText(input.content.titleEn) && hasText(input.content.titleDe) && hasText(input.content.serviceLabelAr) && hasText(input.content.serviceLabelEn) && hasText(input.content.serviceLabelDe) && hasText(input.content.summaryAr) && hasText(input.content.summaryEn) && hasText(input.content.summaryDe), summary: "Title, service label, and summary exist in all locales.", }, { key: "sections", complete: input.sections.length > 0 && completedSections === input.sections.length, summary: `${completedSections}/${input.sections.length} sections ready.`, }, { key: "assets", complete: input.assets.length > 0 && completedAssets === input.assets.length, summary: `${completedAssets}/${input.assets.length} assets ready.`, }, ]; } export function getFirstIncompleteWizardStep( steps: PortfolioWizardStepState[], ): PortfolioWizardStep | null { return steps.find((step) => !step.complete)?.key ?? null; }