All files / src/hooks usePlanFeatures.ts

100% Statements 15/15
100% Branches 4/4
100% Functions 6/6
100% Lines 13/13

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115                                                                                            2x 35x   35x 70x   10x   60x     35x 12x     35x 23x     35x                         2x                                       2x                                
/**
 * Plan Features Hook
 *
 * Provides utilities for checking feature availability based on subscription plan.
 */
 
import { useCurrentBusiness } from './useBusiness';
import { PlanPermissions } from '../types';
 
export type FeatureKey = keyof PlanPermissions;
 
export interface PlanFeatureCheck {
  /**
   * Check if a feature is available in the current plan
   */
  canUse: (feature: FeatureKey) => boolean;
 
  /**
   * Check if any of the features are available
   */
  canUseAny: (features: FeatureKey[]) => boolean;
 
  /**
   * Check if all of the features are available
   */
  canUseAll: (features: FeatureKey[]) => boolean;
 
  /**
   * Get the current plan tier
   */
  plan: string | undefined;
 
  /**
   * All plan permissions
   */
  permissions: PlanPermissions | undefined;
 
  /**
   * Whether permissions are still loading
   */
  isLoading: boolean;
}
 
/**
 * Hook to check plan feature availability
 */
export const usePlanFeatures = (): PlanFeatureCheck => {
  const { data: business, isLoading } = useCurrentBusiness();
 
  const canUse = (feature: FeatureKey): boolean => {
    if (!business?.planPermissions) {
      // Default to false if no permissions loaded yet
      return false;
    }
    return business.planPermissions[feature] ?? false;
  };
 
  const canUseAny = (features: FeatureKey[]): boolean => {
    return features.some(feature => canUse(feature));
  };
 
  const canUseAll = (features: FeatureKey[]): boolean => {
    return features.every(feature => canUse(feature));
  };
 
  return {
    canUse,
    canUseAny,
    canUseAll,
    plan: business?.plan,
    permissions: business?.planPermissions,
    isLoading,
  };
};
 
/**
 * Feature display names for UI
 */
export const FEATURE_NAMES: Record<FeatureKey, string> = {
  sms_reminders: 'SMS Reminders',
  webhooks: 'Webhooks',
  api_access: 'API Access',
  custom_domain: 'Custom Domain',
  white_label: 'White Label',
  custom_oauth: 'Custom OAuth',
  plugins: 'Custom Plugins',
  tasks: 'Scheduled Tasks',
  export_data: 'Data Export',
  video_conferencing: 'Video Conferencing',
  two_factor_auth: 'Two-Factor Authentication',
  masked_calling: 'Masked Calling',
  pos_system: 'POS System',
  mobile_app: 'Mobile App',
};
 
/**
 * Feature descriptions for upgrade prompts
 */
export const FEATURE_DESCRIPTIONS: Record<FeatureKey, string> = {
  sms_reminders: 'Send automated SMS reminders to customers and staff',
  webhooks: 'Integrate with external services using webhooks',
  api_access: 'Access the SmoothSchedule API for custom integrations',
  custom_domain: 'Use your own custom domain for your booking site',
  white_label: 'Remove SmoothSchedule branding and use your own',
  custom_oauth: 'Configure your own OAuth credentials for social login',
  plugins: 'Create custom plugins to extend functionality',
  tasks: 'Create scheduled tasks to automate plugin execution',
  export_data: 'Export your data to CSV or other formats',
  video_conferencing: 'Add video conferencing links to appointments',
  two_factor_auth: 'Require two-factor authentication for enhanced security',
  masked_calling: 'Use masked phone numbers to protect privacy',
  pos_system: 'Process in-person payments with Point of Sale',
  mobile_app: 'Access SmoothSchedule on mobile devices',
};