97 lines
3.2 KiB
TypeScript
97 lines
3.2 KiB
TypeScript
"use client";
|
|
|
|
import { useHospitalityCapabilities } from "@/modules/hospitality/hooks/useHospitalityCapabilities";
|
|
import { HospitalityPageLoader } from "@/modules/hospitality/pages/shared";
|
|
import { FeatureLock } from "@/modules/commercial/components";
|
|
import { useTenantId } from "@/hooks/useTenantId";
|
|
import { CapabilityUnavailable } from "@/modules/hospitality/components/CapabilityUnavailable";
|
|
|
|
/** Maps hospitality capability/feature keys → L2 bundle codes (service-owned). */
|
|
export const FEATURE_TO_BUNDLE: Record<string, string> = {
|
|
digital_menu: "digital_menu",
|
|
digital_menu_catalog: "digital_menu",
|
|
qr_menu: "qr_menu",
|
|
qr_ordering: "qr_ordering",
|
|
pos_lite: "pos_lite",
|
|
pos_pro: "pos_pro",
|
|
kitchen: "kitchen",
|
|
kitchen_engine: "kitchen",
|
|
reservation: "reservation",
|
|
table_service: "table_service",
|
|
delivery_integration: "delivery_connector",
|
|
delivery_connector: "delivery_connector",
|
|
accounting_integration: "accounting_connector",
|
|
accounting_connector: "accounting_connector",
|
|
crm_integration: "crm_connector",
|
|
crm_connector: "crm_connector",
|
|
loyalty_integration: "loyalty_connector",
|
|
loyalty_connector: "loyalty_connector",
|
|
communication_integration: "communication_connector",
|
|
communication_connector: "communication_connector",
|
|
website_integration: "website_connector",
|
|
website_connector: "website_connector",
|
|
analytics: "analytics",
|
|
};
|
|
|
|
/**
|
|
* Dual-layer gate:
|
|
* 1) Hospitality L2 `/capabilities` feature flag
|
|
* 2) Commercial entitlement (FeatureLock / UpgradePrompt)
|
|
*
|
|
* Never silently hides. Never uses fake unlock.
|
|
*/
|
|
export function HospitalityBundleGate({
|
|
feature,
|
|
capabilities,
|
|
children,
|
|
}: {
|
|
feature: string;
|
|
capabilities?: { features: Record<string, boolean> };
|
|
children: React.ReactNode;
|
|
}) {
|
|
const capsQ = useHospitalityCapabilities();
|
|
const { tenantId } = useTenantId();
|
|
const caps = capabilities ?? capsQ.data;
|
|
const bundle = FEATURE_TO_BUNDLE[feature] ?? feature;
|
|
const commercialKey = `hospitality.${bundle}`;
|
|
|
|
if (capsQ.isLoading && !capabilities) return <HospitalityPageLoader />;
|
|
|
|
const featureFlag =
|
|
caps?.features?.[feature] ?? caps?.features?.[bundle] ?? caps?.features?.[FEATURE_TO_BUNDLE[feature]];
|
|
|
|
if (featureFlag === false) {
|
|
return (
|
|
<CapabilityUnavailable
|
|
title="ماژول در بسته فعال نیست"
|
|
description="این بخش در بسته (bundle) فعال Hospitality شما موجود نیست."
|
|
requiredBundle={bundle}
|
|
requiredCapability={feature}
|
|
secondaryHref="/hospitality/bundles"
|
|
secondaryLabel="بستههای Hospitality"
|
|
/>
|
|
);
|
|
}
|
|
|
|
if (!tenantId) return <>{children}</>;
|
|
|
|
return (
|
|
<FeatureLock
|
|
featureKey={commercialKey}
|
|
tenantId={tenantId}
|
|
requiredBundle={bundle}
|
|
requiredCapability={commercialKey}
|
|
fallback={
|
|
<CapabilityUnavailable
|
|
title="نیاز به entitlement تجاری"
|
|
description="دسترسی تجاری برای این قابلیت تأیید نشد."
|
|
requiredBundle={bundle}
|
|
requiredCapability={commercialKey}
|
|
/>
|
|
}
|
|
>
|
|
{children}
|
|
</FeatureLock>
|
|
);
|
|
}
|