Files
smoothschedule/frontend/src/hooks/usePlatformSettings.ts
poduck dcb14503a2 feat: Dashboard redesign, plan permissions, and help docs improvements
Major updates including:
- Customizable dashboard with drag-and-drop widget grid layout
- Plan-based feature locking for plugins and tasks
- Comprehensive help documentation updates across all pages
- Plugin seeding in deployment process for all tenants
- Permission synchronization system for subscription plans
- QuotaOverageModal component and enhanced UX flows

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-03 13:02:44 -05:00

258 lines
6.7 KiB
TypeScript

/**
* Platform Settings Hooks
*/
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
import apiClient from '../api/client';
export interface PlatformSettings {
stripe_secret_key_masked: string;
stripe_publishable_key_masked: string;
stripe_webhook_secret_masked: string;
stripe_account_id: string;
stripe_account_name: string;
stripe_keys_validated_at: string | null;
stripe_validation_error: string;
has_stripe_keys: boolean;
stripe_keys_from_env: boolean;
email_check_interval_minutes: number;
updated_at: string;
}
export interface GeneralSettingsUpdate {
email_check_interval_minutes?: number;
}
export interface StripeKeysUpdate {
stripe_secret_key?: string;
stripe_publishable_key?: string;
stripe_webhook_secret?: string;
}
export interface SubscriptionPlan {
id: number;
name: string;
description: string;
plan_type: 'base' | 'addon';
stripe_product_id: string;
stripe_price_id: string;
price_monthly: string | null;
price_yearly: string | null;
business_tier: string;
features: string[];
limits: Record<string, any>;
permissions: Record<string, boolean>;
transaction_fee_percent: string;
transaction_fee_fixed: string;
// Communication pricing
sms_enabled: boolean;
sms_price_per_message_cents: number;
masked_calling_enabled: boolean;
masked_calling_price_per_minute_cents: number;
proxy_number_enabled: boolean;
proxy_number_monthly_fee_cents: number;
// Default credit settings
default_auto_reload_enabled: boolean;
default_auto_reload_threshold_cents: number;
default_auto_reload_amount_cents: number;
is_active: boolean;
is_public: boolean;
is_most_popular: boolean;
show_price: boolean;
created_at: string;
updated_at: string;
}
export interface SubscriptionPlanCreate {
name: string;
description?: string;
plan_type?: 'base' | 'addon';
price_monthly?: number | null;
price_yearly?: number | null;
business_tier?: string;
features?: string[];
limits?: Record<string, any>;
permissions?: Record<string, boolean>;
transaction_fee_percent?: number;
transaction_fee_fixed?: number;
// Communication pricing
sms_enabled?: boolean;
sms_price_per_message_cents?: number;
masked_calling_enabled?: boolean;
masked_calling_price_per_minute_cents?: number;
proxy_number_enabled?: boolean;
proxy_number_monthly_fee_cents?: number;
// Default credit settings
default_auto_reload_enabled?: boolean;
default_auto_reload_threshold_cents?: number;
default_auto_reload_amount_cents?: number;
is_active?: boolean;
is_public?: boolean;
is_most_popular?: boolean;
show_price?: boolean;
create_stripe_product?: boolean;
stripe_product_id?: string;
stripe_price_id?: string;
}
/**
* Hook to get platform settings
*/
export const usePlatformSettings = () => {
return useQuery<PlatformSettings>({
queryKey: ['platformSettings'],
queryFn: async () => {
const { data } = await apiClient.get('/platform/settings/');
return data;
},
staleTime: 5 * 60 * 1000, // 5 minutes
});
};
/**
* Hook to update general platform settings
*/
export const useUpdateGeneralSettings = () => {
const queryClient = useQueryClient();
return useMutation({
mutationFn: async (settings: GeneralSettingsUpdate) => {
const { data } = await apiClient.post('/platform/settings/general/', settings);
return data;
},
onSuccess: (data) => {
queryClient.setQueryData(['platformSettings'], data);
},
});
};
/**
* Hook to update platform Stripe keys
*/
export const useUpdateStripeKeys = () => {
const queryClient = useQueryClient();
return useMutation({
mutationFn: async (keys: StripeKeysUpdate) => {
const { data } = await apiClient.post('/platform/settings/stripe/keys/', keys);
return data;
},
onSuccess: (data) => {
queryClient.setQueryData(['platformSettings'], data);
},
});
};
/**
* Hook to validate platform Stripe keys
*/
export const useValidateStripeKeys = () => {
const queryClient = useQueryClient();
return useMutation({
mutationFn: async () => {
const { data } = await apiClient.post('/platform/settings/stripe/validate/');
return data;
},
onSuccess: (data) => {
if (data.settings) {
queryClient.setQueryData(['platformSettings'], data.settings);
}
},
});
};
/**
* Hook to get subscription plans
*/
export const useSubscriptionPlans = () => {
return useQuery<SubscriptionPlan[]>({
queryKey: ['subscriptionPlans'],
queryFn: async () => {
const { data } = await apiClient.get('/platform/subscription-plans/');
return data;
},
staleTime: 5 * 60 * 1000,
});
};
/**
* Hook to create a subscription plan
*/
export const useCreateSubscriptionPlan = () => {
const queryClient = useQueryClient();
return useMutation({
mutationFn: async (plan: SubscriptionPlanCreate) => {
const { data } = await apiClient.post('/platform/subscription-plans/', plan);
return data;
},
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ['subscriptionPlans'] });
},
});
};
/**
* Hook to update a subscription plan
*/
export const useUpdateSubscriptionPlan = () => {
const queryClient = useQueryClient();
return useMutation({
mutationFn: async ({ id, ...updates }: Partial<SubscriptionPlanCreate> & { id: number }) => {
const { data } = await apiClient.patch(`/platform/subscription-plans/${id}/`, updates);
return data;
},
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ['subscriptionPlans'] });
},
});
};
/**
* Hook to delete a subscription plan
*/
export const useDeleteSubscriptionPlan = () => {
const queryClient = useQueryClient();
return useMutation({
mutationFn: async (id: number) => {
const { data } = await apiClient.delete(`/platform/subscription-plans/${id}/`);
return data;
},
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ['subscriptionPlans'] });
},
});
};
/**
* Hook to sync plans with Stripe
*/
export const useSyncPlansWithStripe = () => {
const queryClient = useQueryClient();
return useMutation({
mutationFn: async () => {
const { data } = await apiClient.post('/platform/subscription-plans/sync_with_stripe/');
return data;
},
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ['subscriptionPlans'] });
},
});
};
/**
* Hook to sync a plan's permissions to all tenants on that plan
*/
export const useSyncPlanToTenants = () => {
return useMutation({
mutationFn: async (planId: number) => {
const { data } = await apiClient.post(`/platform/subscription-plans/${planId}/sync_tenants/`);
return data as { message: string; tenant_count: number };
},
});
};