import { WithLabel } from '@/components/forms/input-with-label'; import FullPageLoadingState from '@/components/full-page-loading-state'; import { Button } from '@/components/ui/button'; import { Switch } from '@/components/ui/switch'; import { Widget, WidgetBody, WidgetHead } from '@/components/widget'; import { useTRPC } from '@/integrations/trpc/react'; import { handleError } from '@/integrations/trpc/react'; import { emailCategories } from '@openpanel/constants'; import { useSuspenseQuery } from '@tanstack/react-query'; import { useMutation, useQueryClient } from '@tanstack/react-query'; import { createFileRoute } from '@tanstack/react-router'; import { SaveIcon } from 'lucide-react'; import { Controller, useForm } from 'react-hook-form'; import { toast } from 'sonner'; import { z } from 'zod'; const validator = z.object({ categories: z.record(z.string(), z.boolean()), }); type IForm = z.infer; /** * Build explicit boolean values for every key in emailCategories. * Uses saved preferences when available, falling back to true (opted-in). */ function buildCategoryDefaults( savedPreferences?: Record, ): Record { return Object.keys(emailCategories).reduce( (acc, category) => { acc[category] = savedPreferences?.[category] ?? true; return acc; }, {} as Record, ); } export const Route = createFileRoute( '/_app/$organizationId/profile/_tabs/email-preferences', )({ component: Component, pendingComponent: FullPageLoadingState, }); function Component() { const trpc = useTRPC(); const queryClient = useQueryClient(); const preferencesQuery = useSuspenseQuery( trpc.email.getPreferences.queryOptions(), ); const { control, handleSubmit, formState, reset } = useForm({ defaultValues: { categories: buildCategoryDefaults(preferencesQuery.data), }, }); const mutation = useMutation( trpc.email.updatePreferences.mutationOptions({ onSuccess: async () => { toast('Email preferences updated', { description: 'Your email preferences have been saved.', }); await queryClient.invalidateQueries( trpc.email.getPreferences.pathFilter(), ); // Reset form with fresh data after refetch const freshData = await queryClient.fetchQuery( trpc.email.getPreferences.queryOptions(), ); reset({ categories: buildCategoryDefaults(freshData), }); }, onError: handleError, }), ); return (
{ mutation.mutate(values); })} > Email Preferences

Choose which types of emails you want to receive. Uncheck a category to stop receiving those emails.

{Object.entries(emailCategories).map(([category, label]) => ( (
{label}
{category === 'onboarding' && 'Get started tips and guidance emails'} {category === 'billing' && 'Subscription updates and payment reminders'}
)} /> ))}
); }