"use client"; import { useCallback, useEffect, useMemo, useState } from "react"; import Link from "next/link"; import { useRouter } from "next/navigation"; import { AuthGuard } from "@/components/AuthGuard"; import { Badge, Button, Container, SectionTitle } from "@/components/ui"; import { useAuth } from "@/hooks/useAuth"; import { useMe } from "@/hooks/useMe"; import { buildSetupChecklist, loadActivationPipeline, loadCommercialAssets, loadCommercialAutomationPacks, loadCommercialCapabilities, loadCommercialExtensions, loadCommercialInvoices, loadCommercialLicenses, loadCommercialNotifications, loadCommercialPolicies, loadCommercialProducts, loadSetupChecklistFromApi, loadTenantRecommendations, loadWorkspaceSnapshot, } from "../adapters"; import type { ActivationPipeline } from "../adapters/activation"; import type { CommercialInvoice, CommercialLicense, } from "../adapters/billing-ledger"; import type { TenantRecommendationFeed } from "../adapters/tenant-recommendations"; import type { AdapterResult, CommercialAsset, CommercialAutomationPack, CommercialCapability, CommercialExtension, CommercialNotification, CommercialPolicy, CommercialProduct, CommercialWorkspaceSnapshot, SetupChecklistItem, } from "../types"; import { CapabilityBadge, CommercialEmptyState, DomainPolicyPanel, PlanBadge, PlatformShell, ProductCard, RecommendationsPanel, RegistryBrowser, SetupChecklist, SubscriptionBanner, TrialBanner, UpgradePrompt, } from "../components"; import { loadAssessmentSession } from "../session"; function CommercialDashboardContent() { const router = useRouter(); const { user } = useAuth(); const { me, loading: meLoading, error: meError, reload: reloadMe } = useMe(); const [snap, setSnap] = useState | null>(null); const [products, setProducts] = useState | null>(null); const [caps, setCaps] = useState | null>(null); const [assets, setAssets] = useState | null>(null); const [extensions, setExtensions] = useState | null>(null); const [automation, setAutomation] = useState | null>(null); const [policies, setPolicies] = useState | null>(null); const [notifications, setNotifications] = useState | null>(null); const [recs, setRecs] = useState | null>(null); const [invoices, setInvoices] = useState | null>(null); const [licenses, setLicenses] = useState | null>(null); const [activation, setActivation] = useState | null>(null); const [checklist, setChecklist] = useState([]); const [checklistPct, setChecklistPct] = useState(null); const [upgradeOpen, setUpgradeOpen] = useState(false); const [upgradeHint, setUpgradeHint] = useState(); const load = useCallback(async () => { const [s, p, c, a, e, auto, pol, n] = await Promise.all([ loadWorkspaceSnapshot(), loadCommercialProducts(), loadCommercialCapabilities(), loadCommercialAssets(), loadCommercialExtensions(), loadCommercialAutomationPacks(), loadCommercialPolicies(), loadCommercialNotifications(), ]); setSnap(s); setProducts(p); setCaps(c); setAssets(a); setExtensions(e); setAutomation(auto); setPolicies(pol); setNotifications(n); const tenantId = s.data?.tenant_id; if (tenantId) { const [r, inv, lic, act, chk] = await Promise.all([ loadTenantRecommendations(tenantId), loadCommercialInvoices(tenantId), loadCommercialLicenses(tenantId), loadActivationPipeline(tenantId), loadSetupChecklistFromApi(tenantId), ]); setRecs(r); setInvoices(inv); setLicenses(lic); setActivation(act); if (chk.availability === "ready" && chk.data.length) { setChecklist(chk.data); setChecklistPct( (chk as AdapterResult & { completion_percent?: number }) .completion_percent ?? s.data?.checklist_completion_percent ?? null ); } else { const session = loadAssessmentSession(); setChecklist( buildSetupChecklist(p.data ?? [], { installedCodes: session.selected_product_codes }) ); setChecklistPct(s.data?.checklist_completion_percent ?? null); } } }, []); useEffect(() => { if (meLoading) return; if (!me) return; if (me.onboarding_required) { router.replace("/onboarding"); return; } void load(); }, [me, meLoading, router, load]); const productList = products?.data ?? []; const byCode = useMemo(() => { const m = new Map(); for (const p of productList) m.set(p.product_code, p); return m; }, [productList]); const pickProducts = (codes?: string[]) => (codes || []) .map((code) => byCode.get(code)) .filter((x): x is CommercialProduct => Boolean(x)); const ws = snap?.data; const pinned = pickProducts(ws?.pinned_product_codes); const recent = pickProducts(ws?.recent_product_codes); const quick = ws?.quick_actions ?? []; const locked = ws?.locked_features ?? []; const trialEnded = ws?.subscription_status === "expired" || (ws?.trial && !ws.trial.active && ws.subscription_status === "trialing" && (ws.trial.days_remaining ?? 1) <= 0); useEffect(() => { if (trialEnded) { setUpgradeHint("trial به پایان رسیده یا منقضی شده است."); setUpgradeOpen(true); } }, [trialEnded]); if (meLoading || (me && me.onboarding_required)) { return (

در حال بارگذاری...

); } return (
{(meError || snap?.message) && snap?.availability === "error" ? (

{meError || snap?.message}

) : null} {!ws ? (
) : (

{ws.tenant_name}

{ws.primary_domain || `${ws.slug}.torbatyar.ir`}

{ws.workspace_health ? (

سلامت workspace: {ws.workspace_health}

) : null}
{ws.status}
{activation?.data?.steps?.length ? (
    {activation.data.steps.map((step) => (
  1. {step.label || step.step_key}{" "} ({step.status || "pending"}) {step.href ? ( ادامه ) : null}
  2. ))}
) : null} {quick.length ? (
{quick.map((q) => q.href ? ( ) : ( ) )}
) : null}
{locked.length ? (
    {locked.map((f) => (
  • {f.feature_key}
  • ))}
) : null} {pinned.length ? (
{pinned.map((p) => ( ))}
) : null} {recent.length ? (
{recent.map((p) => ( ))}
) : null}
{products?.availability === "ready" && products.data.length ? (
{products.data.map((p) => ( ))}
) : ( )}
{caps?.availability === "ready" && caps.data.length ? (
{caps.data.slice(0, 40).map((c) => ( ))}
) : ( )}
{invoices?.availability === "ready" && invoices.data.length ? (
    {invoices.data.map((inv) => (
  • {inv.display_name || inv.invoice_code} · {inv.status || "—"}
  • ))}
) : ( )} {licenses?.availability === "ready" && licenses.data.length ? (
    {licenses.data.map((lic) => (
  • {lic.display_name || lic.license_code} · {lic.status || "—"}
  • ))}
) : ( )}
{notifications?.availability === "ready" && notifications.data.length ? (
    {notifications.data.map((n) => (
  • {n.title}

    {n.body ?

    {n.body}

    : null}
  • ))}
) : ( )}
{ws.trial?.quotas?.length ? (
    {ws.trial.quotas.map((q) => (
  • {q.label || q.key}: {q.used ?? "—"} / {q.limit ?? "∞"}
  • ))}
) : ( )}
)} setUpgradeOpen(false)} />
); } export function CommercialDashboardPage() { return ( ); }