"use client"; import Link from "next/link"; import { useEffect, useMemo, useState } from "react"; import BlogPanel from "@/components/catalog/BlogPanel"; import PortfoliosPanel from "@/components/catalog/PortfoliosPanel"; import ProductsPanel from "@/components/catalog/ProductsPanel"; import { toPlainText } from "@/components/catalog/utils"; import { openBusinessDashboardAsAdmin } from "@/lib/session-handoff"; import { getMarketplaceBusiness } from "@/services/marketplace"; import { getBusinessProfile, getMeshkeeBusiness, type BusinessAddress, type BusinessPhoneNumber, } from "@/services/meshkee-businesses"; import { listMeshkeeBlogs, listMeshkeePortfolios, listMeshkeeProducts, } from "@/services/meshkee-content"; import styles from "./BusinessDetailsPage.module.css"; type TabId = "products" | "contact" | "blog" | "portfolios"; const TAB_LABELS: Record = { products: "Products", contact: "Contact info", blog: "Blog", portfolios: "Portfolios", }; const SOCIAL_ICONS: Record = { instagram: "/images/icons/instagram.png", telegram: "/images/icons/telegram.png", facebook: "/images/icons/facebook.png", whatsapp: "/images/icons/telegram.png", linkedin: "/images/icons/facebook.png", youtube: "/images/icons/facebook.png", aparat: "/images/icons/facebook.png", }; function hasContactData(input: { addresses: BusinessAddress[]; phones: BusinessPhoneNumber[]; emails: string[]; socials: { network: string; handle: string }[]; }) { return ( input.addresses.some( (item) => item.address.trim() || item.city.trim() || item.province.trim() || (item.landline ?? "").trim(), ) || input.phones.some((item) => item.number.trim()) || input.emails.some((item) => item.trim()) || input.socials.length > 0 ); } export default function BusinessDetailsPage({ listingId, }: { listingId: string; }) { const [loading, setLoading] = useState(true); const [error, setError] = useState(""); const [meshkeeId, setMeshkeeId] = useState(""); const [tab, setTab] = useState("products"); const [name, setName] = useState(""); const [slug, setSlug] = useState(""); const [categoryName, setCategoryName] = useState(""); const [logoUrl, setLogoUrl] = useState(null); const [bannerUrl, setBannerUrl] = useState(null); const [about, setAbout] = useState(""); const [vision, setVision] = useState(""); const [sinceMonth, setSinceMonth] = useState(""); const [sinceYear, setSinceYear] = useState(""); const [province, setProvince] = useState(""); const [telephone, setTelephone] = useState(""); const [productTotal, setProductTotal] = useState(0); const [blogTotal, setBlogTotal] = useState(0); const [portfolioTotal, setPortfolioTotal] = useState(0); const [addresses, setAddresses] = useState([]); const [phones, setPhones] = useState([]); const [emails, setEmails] = useState([]); const [socials, setSocials] = useState< { network: string; handle: string; icon: string }[] >([]); useEffect(() => { let cancelled = false; void (async () => { setLoading(true); setError(""); try { const listing = await getMarketplaceBusiness(listingId); const id = String(listing.meshkeeBusinessId); const [ meshkee, profile, productsRes, blogsRes, portfoliosRes, ] = await Promise.all([ getMeshkeeBusiness(id), getBusinessProfile(id), listMeshkeeProducts(id, { page: 1, pageSize: 1 }).catch(() => ({ total: 0, })), listMeshkeeBlogs(id, { page: 1, pageSize: 1 }).catch(() => ({ total: 0, })), listMeshkeePortfolios(id, { page: 1, pageSize: 1 }).catch(() => ({ total: 0, })), ]); if (cancelled) return; const nextAddresses = profile.addresses ?? []; const nextPhones = profile.profile.phoneNumbers ?? []; const nextEmails = (profile.profile.emails ?? []).filter(Boolean); const socialMedia = profile.profile.socialMedia ?? {}; const nextSocials = Object.entries(socialMedia) .filter(([, handle]) => Boolean(handle?.trim())) .map(([network, handle]) => ({ network, handle: handle.trim(), icon: SOCIAL_ICONS[network] ?? "/images/icons/telegram.png", })); setMeshkeeId(id); setName(meshkee.name || listing.slug); setSlug(listing.slug); setCategoryName(meshkee.categories[0]?.name ?? ""); setLogoUrl(profile.profile.logoUrl ?? meshkee.logoUrl); setBannerUrl(profile.profile.bannerUrl ?? meshkee.bannerUrl); setAbout(profile.profile.about ?? ""); setVision(profile.profile.vision ?? ""); if (meshkee.createdAt) { const joined = new Date(meshkee.createdAt); setSinceMonth( joined.toLocaleDateString("en-US", { month: "long" }), ); setSinceYear(String(joined.getFullYear())); } else { setSinceMonth(""); setSinceYear(""); } setProvince(nextAddresses[0]?.province ?? ""); setTelephone( nextPhones.find((item) => item.number.trim())?.number ?? nextAddresses.find((item) => (item.landline ?? "").trim()) ?.landline ?? "", ); setProductTotal(productsRes.total ?? 0); setBlogTotal(blogsRes.total ?? 0); setPortfolioTotal(portfoliosRes.total ?? 0); setAddresses(nextAddresses); setPhones(nextPhones as BusinessPhoneNumber[]); setEmails(nextEmails); setSocials(nextSocials); } catch (err) { if (cancelled) return; setError( err instanceof Error ? err.message : "Could not load business details.", ); } finally { if (!cancelled) setLoading(false); } })(); return () => { cancelled = true; }; }, [listingId]); const contactReady = hasContactData({ addresses, phones, emails, socials, }); const availableTabs = useMemo(() => { const tabs: TabId[] = []; if (productTotal > 0) tabs.push("products"); if (contactReady) tabs.push("contact"); if (blogTotal > 0) tabs.push("blog"); // Gallery disabled until a dedicated gallery section exists (media library ≠ gallery). if (portfolioTotal > 0) tabs.push("portfolios"); return tabs; }, [productTotal, contactReady, blogTotal, portfolioTotal]); useEffect(() => { if (!availableTabs.length) return; if (!availableTabs.includes(tab)) setTab(availableTabs[0]); }, [availableTabs, tab]); const description = toPlainText(about) || toPlainText(vision); function openBusinessDashboard(nextPath: string) { if (!meshkeeId) return; openBusinessDashboardAsAdmin(meshkeeId, nextPath); } if (loading) { return
Loading business details…
; } if (error) { return (

Could not load details

{error}

Back to businesses
); } return (
Edit listing
{bannerUrl ? ( ) : (
)}
{logoUrl ? ( ) : ( {name.slice(0, 1).toUpperCase()} )}

{name}

{categoryName || `/${slug}`}

{sinceMonth && sinceYear ? (
since {sinceYear} {sinceMonth}
) : null} {province ? (
province {province}
) : null}
{portfolioTotal} active
{portfolioTotal === 1 ? "portfolio" : "portfolios"}
{telephone ? (
Telephone {telephone}
) : null}
{description ? (

{description}

) : null}
{availableTabs.length && meshkeeId ? ( <>
{tab === "products" ? ( openBusinessDashboard("/products")} /> ) : null} {tab === "contact" ? (
{addresses.map((address, index) => (
{address.name || "Address"}

{[address.address, address.city, address.province] .filter(Boolean) .join(", ")}

{address.postalCode ? (

Postal: {address.postalCode}

) : null} {address.landline ? (

Landline: {address.landline}

) : null}
))} {phones.length ? (
Phones

{phones .filter((item) => item.number.trim()) .map((item) => item.number) .join(" · ")}

) : null} {emails.length ? (
Email

{emails.join(" · ")}

) : null}
{socials.length ? (
{socials.map((social) => ( {social.network} {social.handle} ))}
) : null}
) : null} {tab === "blog" ? ( openBusinessDashboard("/blog")} /> ) : null} {tab === "portfolios" ? ( openBusinessDashboard("/portfolios")} /> ) : null}
) : (
No catalog tabs yet — products, blog, portfolios, or contact data will appear here when Meshkee has them.
)}
); }