68 lines
2.3 KiB
TypeScript
68 lines
2.3 KiB
TypeScript
"use client";
|
||
|
||
import { useEffect, useState } from "react";
|
||
import Link from "next/link";
|
||
import { Button } from "@/components/ui";
|
||
import { loadCommercialProducts } from "../adapters";
|
||
import type { CommercialProduct } from "../types";
|
||
import { resolveProductLaunchUrl } from "../types";
|
||
|
||
/** Dynamic sidebar — product launch URLs from registry metadata only. */
|
||
export function CommercialSidebar({ className = "" }: { className?: string }) {
|
||
const [products, setProducts] = useState<CommercialProduct[]>([]);
|
||
|
||
useEffect(() => {
|
||
void loadCommercialProducts().then((r) => {
|
||
if (r.availability === "ready") {
|
||
setProducts(
|
||
r.data
|
||
.filter((p) => p.visibility !== "hidden")
|
||
.filter((p) => resolveProductLaunchUrl(p))
|
||
);
|
||
}
|
||
});
|
||
}, []);
|
||
|
||
return (
|
||
<aside className={`rounded-2xl border border-gray-100 bg-white p-4 shadow-sm ${className}`}>
|
||
<p className="text-xs font-semibold uppercase tracking-wide text-gray-400">Apps</p>
|
||
<nav className="mt-3 flex flex-col gap-1">
|
||
<Link href="/dashboard" className="rounded-lg px-2 py-1.5 text-sm hover:bg-gray-50">
|
||
Workspace
|
||
</Link>
|
||
<Link href="/apps" className="rounded-lg px-2 py-1.5 text-sm hover:bg-gray-50">
|
||
Products
|
||
</Link>
|
||
<Link href="/billing" className="rounded-lg px-2 py-1.5 text-sm hover:bg-gray-50">
|
||
Billing
|
||
</Link>
|
||
<div className="my-2 border-t border-gray-100" />
|
||
{products.length ? (
|
||
products.map((p) => {
|
||
const href = resolveProductLaunchUrl(p) || "/apps";
|
||
return (
|
||
<Link
|
||
key={p.product_code}
|
||
href={href}
|
||
className="rounded-lg px-2 py-1.5 text-sm text-secondary hover:bg-gray-50"
|
||
>
|
||
{p.icon ? <span className="me-1">{p.icon}</span> : null}
|
||
{p.display_name}
|
||
</Link>
|
||
);
|
||
})
|
||
) : (
|
||
<p className="px-2 text-xs text-gray-400">محصولی کشف نشده</p>
|
||
)}
|
||
</nav>
|
||
<div className="mt-4">
|
||
<Link href="/">
|
||
<Button variant="ghost" size="sm" className="w-full">
|
||
ارزیابی مجدد
|
||
</Button>
|
||
</Link>
|
||
</div>
|
||
</aside>
|
||
);
|
||
}
|