import type { FeatureState, PolicyApiClient, PolicySnapshotDto } from '@/lib/api/policy/PolicyApiClient'; export interface CapabilityEvaluationResult { isLoading: boolean; isError: boolean; capabilityState: FeatureState | null; shouldShowChildren: boolean; shouldShowComingSoon: boolean; } export class PolicyService { constructor(private readonly apiClient: PolicyApiClient) {} getSnapshot(): Promise { return this.apiClient.getSnapshot(); } getCapabilityState(snapshot: PolicySnapshotDto, capabilityKey: string): FeatureState { return snapshot.capabilities[capabilityKey] ?? 'hidden'; } isCapabilityEnabled(snapshot: PolicySnapshotDto, capabilityKey: string): boolean { return this.getCapabilityState(snapshot, capabilityKey) === 'enabled'; } /** * Evaluate capability state and determine what should be rendered * Centralizes the logic for capability-based UI rendering */ evaluateCapability( snapshot: PolicySnapshotDto | null, capabilityKey: string, isLoading: boolean, isError: boolean ): CapabilityEvaluationResult { if (isLoading || isError || !snapshot) { return { isLoading, isError, capabilityState: null, shouldShowChildren: false, shouldShowComingSoon: false, }; } const capabilityState = this.getCapabilityState(snapshot, capabilityKey); return { isLoading, isError, capabilityState, shouldShowChildren: capabilityState === 'enabled', shouldShowComingSoon: capabilityState === 'coming_soon', }; } /** * Get the appropriate content based on capability state * Handles fallback and coming soon logic */ getCapabilityContent( snapshot: PolicySnapshotDto | null, capabilityKey: string, isLoading: boolean, isError: boolean, children: React.ReactNode, fallback: React.ReactNode = null, comingSoon: React.ReactNode = null ): React.ReactNode { const evaluation = this.evaluateCapability(snapshot, capabilityKey, isLoading, isError); if (evaluation.shouldShowChildren) { return children; } if (evaluation.shouldShowComingSoon) { return comingSoon ?? fallback; } return fallback; } }