"use client"; import { useEffect, useId, useMemo, useState } from "react"; import { listBusinesses } from "@/services/marketplace"; import { getSpecialBusinesses, newCarousel, saveSpecialBusinesses, slugFromTitle, type SpecialBusinessesConfig, type SpecialCarousel, } from "@/services/special-businesses"; import type { MarketplaceBusiness } from "@/types/business"; import { getBusinessProfile, getMeshkeeBusiness, } from "@/services/meshkee-businesses"; import styles from "./SpecialBusinessesPage.module.css"; type EnrichedBusiness = MarketplaceBusiness & { displayName: string; subtext: string; }; type CarouselFormMode = "create" | "edit"; async function enrichBusinesses( items: MarketplaceBusiness[], ): Promise { return Promise.all( items.map(async (item) => { try { const id = String(item.meshkeeBusinessId); const [meshkee, profile] = await Promise.all([ getMeshkeeBusiness(id), getBusinessProfile(id), ]); return { ...item, name: meshkee.name, displayName: profile.profile.nameEn || profile.profile.nameFa || meshkee.name || item.slug, subtext: (profile.profile.title || "").trim(), logoUrl: profile.profile.logoUrl ?? meshkee.logoUrl ?? undefined, }; } catch { return { ...item, displayName: item.name || item.slug, subtext: "", }; } }), ); } function BusinessIdentity({ item }: { item: EnrichedBusiness }) { return (
{item.logoUrl ? ( ) : ( {item.displayName.slice(0, 1).toUpperCase()} )}
{item.displayName} {item.subtext ? ( {item.subtext} ) : ( /{item.slug} )}
); } export default function SpecialBusinessesPage() { const [config, setConfig] = useState(null); const [activeId, setActiveId] = useState(""); const [allBusinesses, setAllBusinesses] = useState([]); const [query, setQuery] = useState(""); const [loading, setLoading] = useState(true); const [saving, setSaving] = useState(false); const [status, setStatus] = useState(""); const [error, setError] = useState(""); const [formMode, setFormMode] = useState(null); const [formName, setFormName] = useState(""); const [formSubtext, setFormSubtext] = useState(""); const [formError, setFormError] = useState(""); const formTitleId = useId(); useEffect(() => { let cancelled = false; void (async () => { setLoading(true); setError(""); try { const [special, listings] = await Promise.all([ getSpecialBusinesses(), listBusinesses({ status: "all", limit: 200 }), ]); const enriched = await enrichBusinesses(listings.items); if (cancelled) return; setConfig(special); setActiveId(special.carousels[0]?.id ?? ""); setAllBusinesses(enriched); } catch (err) { if (!cancelled) { setError( err instanceof Error ? err.message : "Could not load special businesses.", ); } } finally { if (!cancelled) setLoading(false); } })(); return () => { cancelled = true; }; }, []); const active = useMemo( () => config?.carousels.find((item) => item.id === activeId) ?? null, [config, activeId], ); const byId = useMemo(() => { const map = new Map(); for (const item of allBusinesses) map.set(item.id, item); return map; }, [allBusinesses]); const selectedBusinesses = useMemo(() => { if (!active) return []; return active.businessIds .map((id) => byId.get(id)) .filter(Boolean) as EnrichedBusiness[]; }, [active, byId]); const searchResults = useMemo(() => { if (!active) return []; const q = query.trim().toLowerCase(); if (q.length <= 2) return []; const selected = new Set(active.businessIds); return allBusinesses .filter((item) => !selected.has(item.id)) .filter( (item) => item.displayName.toLowerCase().includes(q) || item.subtext.toLowerCase().includes(q) || item.slug.toLowerCase().includes(q) || item.id.includes(q), ) .slice(0, 12); }, [active, allBusinesses, query]); function updateCarousel(id: string, patch: Partial) { setConfig((prev) => { if (!prev) return prev; return { carousels: prev.carousels.map((item) => item.id === id ? { ...item, ...patch } : item, ), }; }); setStatus(""); } function openCreateModal() { setFormMode("create"); setFormName(""); setFormSubtext(""); setFormError(""); } function openEditModal() { if (!active) return; setFormMode("edit"); setFormName(active.title); setFormSubtext(active.subtext || ""); setFormError(""); } function closeFormModal() { setFormMode(null); setFormError(""); } function submitFormModal() { const title = formName.trim(); if (!title) { setFormError("Name is required."); return; } const subtext = formSubtext.trim(); if (formMode === "create") { const next = newCarousel(title, subtext); setConfig((prev) => prev ? { carousels: [...prev.carousels, next] } : { carousels: [next] }, ); setActiveId(next.id); setStatus(""); closeFormModal(); return; } if (formMode === "edit" && active) { updateCarousel(active.id, { title, subtext, slug: slugFromTitle(title), }); closeFormModal(); } } function removeCarousel(id: string) { setConfig((prev) => { if (!prev || prev.carousels.length <= 1) return prev; const carousels = prev.carousels.filter((item) => item.id !== id); if (activeId === id) setActiveId(carousels[0]?.id ?? ""); return { carousels }; }); setStatus(""); closeFormModal(); } function addBusiness(businessId: string) { if (!active) return; if (active.businessIds.includes(businessId)) return; updateCarousel(active.id, { businessIds: [...active.businessIds, businessId], }); setQuery(""); } function removeBusiness(businessId: string) { if (!active) return; updateCarousel(active.id, { businessIds: active.businessIds.filter((id) => id !== businessId), }); } async function onSave() { if (!config) return; setSaving(true); setStatus(""); setError(""); try { const saved = await saveSpecialBusinesses(config); setConfig(saved); if (!saved.carousels.some((item) => item.id === activeId)) { setActiveId(saved.carousels[0]?.id ?? ""); } setStatus("Saved"); } catch (err) { setError(err instanceof Error ? err.message : "Could not save."); } finally { setSaving(false); } } if (loading) { return
Loading special businesses…
; } if (!config || !active) { return (
{error || "Could not load special businesses."}
); } return (

Carousels

Homepage carousels as tabs — each tab holds multiple businesses.

{status ? ( {status} ) : null} {error ? ( {error} ) : null}
{config.carousels.map((carousel) => ( ))}

{active.title}

{active.subtext ? (

{active.subtext}

) : null}
{query.trim().length > 2 ? ( searchResults.length ? (
{searchResults.map((item) => (
))}
) : (
No matching businesses to add.
) ) : null}

Businesses in this carousel

{selectedBusinesses.length}
{selectedBusinesses.length ? ( selectedBusinesses.map((item) => (
)) ) : (
No businesses in this carousel yet. Search above to add some.
)}
{formMode ? (
{ if (event.target === event.currentTarget) closeFormModal(); }} >

Carousels

{formMode === "create" ? "Add carousel" : "Edit carousel"}

{ event.preventDefault(); submitFormModal(); }} > {formError ? (

{formError}

) : null}
{formMode === "edit" && config.carousels.length > 1 ? ( ) : ( )}
) : null}
); }