TorbatYar/frontend/modules/communication/components/CommunicationFeatureLock.tsx
Mortezakoohjani 0d424c500a feat(platform): complete commercial runtime consolidation
Unify commercial runtime ownership across backend and frontend so platform, experience, and hospitality modules use the shared commercial source of truth.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-29 11:11:53 +03:30

115 lines
4.7 KiB
TypeScript
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"use client";
import Link from "next/link";
import { Lock, Rocket, Sparkles } from "lucide-react";
import { Button, Card, CardContent, Badge } from "@/components/ds";
import { CommunicationBreadcrumbs } from "@/modules/communication/components/CommunicationBreadcrumbs";
import {
useCommunicationCapabilities,
isFeatureEnabled,
} from "@/modules/communication/hooks/useCommunicationCapabilities";
import { CommunicationPageLoader, CommunicationPageError } from "@/modules/communication/pages/shared";
import { FeatureLock } from "@/modules/commercial/components";
import { useTenantId } from "@/hooks/useTenantId";
import type { FeatureLockConfig } from "@/modules/communication/types";
/**
* L2 capability gate + Commercial Runtime entitlement.
* UI copy only (title/description/phase) — no commercial catalogs.
*/
export function CommunicationFeatureLock({
config,
children,
}: {
config: FeatureLockConfig;
children?: React.ReactNode;
}) {
const caps = useCommunicationCapabilities();
const { tenantId } = useTenantId();
if (caps.isLoading) return <CommunicationPageLoader label="بررسی قابلیت…" />;
if (caps.error) return <CommunicationPageError error={caps.error} onRetry={() => caps.refetch()} />;
const enabled = isFeatureEnabled(caps.data?.features, config.feature);
if (enabled && children) {
if (!tenantId) return <>{children}</>;
const commercialKey = config.feature.startsWith("communication.")
? config.feature
: `communication.${config.feature}`;
return (
<FeatureLock featureKey={commercialKey} tenantId={tenantId} requiredCapability={commercialKey}>
{children}
</FeatureLock>
);
}
return (
<div className="space-y-6">
<CommunicationBreadcrumbs current={config.title} />
<Card className="overflow-hidden border-[var(--communication-accent)]/20">
<CardContent className="p-0">
<div className="bg-gradient-to-br from-[var(--communication-accent-soft)] to-transparent p-8">
<div className="mb-4 flex items-center gap-3">
<div className="rounded-2xl bg-[var(--communication-accent)]/15 p-3">
<Lock className="h-8 w-8 text-[var(--communication-accent)]" />
</div>
<div className="text-right">
<Badge tone="warning" className="mb-1">
بهزودی
</Badge>
<h2 className="text-xl font-bold text-secondary">{config.title}</h2>
</div>
</div>
<p className="text-sm leading-relaxed text-[var(--muted)]">{config.description}</p>
{config.phase ? (
<p className="mt-3 text-xs text-[var(--muted)]">
<Rocket className="mr-1 inline h-3.5 w-3.5" />
فاز برنامهریزی: {config.phase}
</p>
) : null}
</div>
<div className="space-y-4 border-t border-[var(--border)] p-6">
<div className="flex items-center gap-2 text-sm text-[var(--muted)]">
<Sparkles className="h-4 w-4 text-[var(--communication-accent)]" />
entitlement و قابلیتها فقط از Commercial Runtime / L2 capabilities.
</div>
<p className="text-xs text-[var(--muted)]">
باز شدن: وقتی{" "}
<code className="rounded bg-[var(--surface-muted)] px-1">/capabilities</code> ویژگی{" "}
<code className="font-mono">{config.feature}</code> را فعال کند و Commercial Runtime مجوز
دهد.
</p>
<div className="flex flex-wrap gap-2">
<Link href="/communication/capabilities">
<Button variant="outline">مشاهده قابلیتها</Button>
</Link>
<Link href="/admin/commercial/capabilities">
<Button variant="outline">Commercial Capabilities</Button>
</Link>
<Link href="/communication">
<Button>بازگشت به داشبورد</Button>
</Link>
</div>
</div>
</CardContent>
</Card>
</div>
);
}
export function createCommunicationLockedPage(config: FeatureLockConfig) {
return function CommunicationLockedPage() {
return <CommunicationFeatureLock config={config} />;
};
}
export function createCommunicationFeatureGate(config: FeatureLockConfig, Page: React.ComponentType) {
return function CommunicationGatedPage() {
return (
<CommunicationFeatureLock config={config}>
<Page />
</CommunicationFeatureLock>
);
};
}