feat: Multi-email ticketing system with platform email addresses

- Add PlatformEmailAddress model for managing platform-level email addresses
- Add TicketEmailAddress model for tenant-level email addresses
- Create MailServerService for IMAP integration with mail.talova.net
- Implement PlatformEmailReceiver for processing incoming platform emails
- Add email autoconfiguration for Mozilla, Microsoft, and Apple clients
- Add configurable email polling interval in platform settings
- Add "Check Emails" button on support page for manual refresh
- Add ticket counts to status tabs on support page
- Add platform email addresses management page
- Add Privacy Policy and Terms of Service pages
- Add robots.txt for SEO
- Restrict email addresses to smoothschedule.com domain only

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

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
poduck
2025-12-01 17:49:09 -05:00
parent 65da1c73d0
commit ae74b4c2ed
47 changed files with 6523 additions and 1407 deletions

View File

@@ -15,9 +15,14 @@ export interface PlatformSettings {
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;
@@ -35,10 +40,14 @@ export interface SubscriptionPlan {
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;
is_active: boolean;
is_public: boolean;
is_most_popular: boolean;
show_price: boolean;
created_at: string;
updated_at: string;
}
@@ -51,10 +60,14 @@ export interface SubscriptionPlanCreate {
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;
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;
@@ -74,6 +87,23 @@ export const usePlatformSettings = () => {
});
};
/**
* 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
*/
@@ -148,7 +178,7 @@ export const useUpdateSubscriptionPlan = () => {
const queryClient = useQueryClient();
return useMutation({
mutationFn: async ({ id, ...updates }: Partial<SubscriptionPlan> & { id: number }) => {
mutationFn: async ({ id, ...updates }: Partial<SubscriptionPlanCreate> & { id: number }) => {
const { data } = await apiClient.patch(`/platform/subscription-plans/${id}/`, updates);
return data;
},