Initial commit: SmoothSchedule multi-tenant scheduling platform
This commit includes: - Django backend with multi-tenancy (django-tenants) - React + TypeScript frontend with Vite - Platform administration API with role-based access control - Authentication system with token-based auth - Quick login dev tools for testing different user roles - CORS and CSRF configuration for local development - Docker development environment setup 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
193
frontend/src/hooks/usePlatformSettings.ts
Normal file
193
frontend/src/hooks/usePlatformSettings.ts
Normal file
@@ -0,0 +1,193 @@
|
||||
/**
|
||||
* 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;
|
||||
updated_at: string;
|
||||
}
|
||||
|
||||
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[];
|
||||
transaction_fee_percent: string;
|
||||
transaction_fee_fixed: string;
|
||||
is_active: boolean;
|
||||
is_public: 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[];
|
||||
transaction_fee_percent?: number;
|
||||
transaction_fee_fixed?: number;
|
||||
is_active?: boolean;
|
||||
is_public?: 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('/api/platform/settings/');
|
||||
return data;
|
||||
},
|
||||
staleTime: 5 * 60 * 1000, // 5 minutes
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Hook to update platform Stripe keys
|
||||
*/
|
||||
export const useUpdateStripeKeys = () => {
|
||||
const queryClient = useQueryClient();
|
||||
|
||||
return useMutation({
|
||||
mutationFn: async (keys: StripeKeysUpdate) => {
|
||||
const { data } = await apiClient.post('/api/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('/api/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('/api/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('/api/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<SubscriptionPlan> & { id: number }) => {
|
||||
const { data } = await apiClient.patch(`/api/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(`/api/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('/api/platform/subscription-plans/sync_with_stripe/');
|
||||
return data;
|
||||
},
|
||||
onSuccess: () => {
|
||||
queryClient.invalidateQueries({ queryKey: ['subscriptionPlans'] });
|
||||
},
|
||||
});
|
||||
};
|
||||
Reference in New Issue
Block a user