import { zodResolver } from '@hookform/resolvers/zod' import { PermissionAction } from '@supabase/shared-types/out/constants' import { useParams } from 'common' import { ChevronRight } from 'lucide-react' import Link from 'next/link' import { useEffect } from 'react' import { useForm } from 'react-hook-form' import { toast } from 'sonner' import { Button, Card, CardContent, CardFooter, Form, FormControl, FormField, Switch } from 'ui' import { Admonition } from 'ui-patterns/admonition' import { PageSection, PageSectionContent, PageSectionMeta, PageSectionSummary, PageSectionTitle, } from 'ui-patterns/PageSection' import { GenericSkeletonLoader } from 'ui-patterns/ShimmeringLoader' import * as z from 'zod' import { TEMPLATES_SCHEMAS } from './AuthTemplatesValidation' import { slugifyTitle } from './EmailTemplates.utils' import AlertError from '@/components/ui/AlertError' import { InlineLink } from '@/components/ui/InlineLink' import { useAuthConfigQuery } from '@/data/auth/auth-config-query' import { useAuthConfigUpdateMutation } from '@/data/auth/auth-config-update-mutation' import { useAsyncCheckPermissions } from '@/hooks/misc/useCheckPermissions' import { DOCS_URL } from '@/lib/constants' const notificationEnabledKeys = TEMPLATES_SCHEMAS.filter( (t) => t.misc?.emailTemplateType === 'security' ).map((template) => { return `MAILER_NOTIFICATIONS_${template.id?.replace('_NOTIFICATION', '')}_ENABLED` }) const NotificationsFormSchema = z.object({ ...notificationEnabledKeys.reduce( (acc, key) => { acc[key] = z.boolean() return acc }, {} as Record ), }) export const EmailTemplates = () => { const { ref: projectRef } = useParams() const { can: canUpdateConfig } = useAsyncCheckPermissions( PermissionAction.UPDATE, 'custom_config_gotrue' ) const { data: authConfig, error: authConfigError, isPending: isLoading, isError, isSuccess, } = useAuthConfigQuery({ projectRef }) const { mutate: updateAuthConfig, isPending: isUpdatingConfig } = useAuthConfigUpdateMutation({ onError: (error) => { toast.error(`Failed to update settings: ${error?.message}`) }, onSuccess: () => { toast.success('Successfully updated settings') }, }) const builtInSMTP = isSuccess && authConfig && (!authConfig.SMTP_HOST || !authConfig.SMTP_USER || !authConfig.SMTP_PASS) const defaultValues = notificationEnabledKeys.reduce( (acc, key) => { acc[key] = authConfig ? Boolean(authConfig[key as keyof typeof authConfig]) : false return acc }, {} as Record ) const notificationsForm = useForm>({ resolver: zodResolver(NotificationsFormSchema as any), defaultValues, }) const onSubmit = (values: any) => { if (!projectRef) return console.error('Project ref is required') updateAuthConfig({ projectRef: projectRef, config: { ...values } }) } useEffect(() => { if (authConfig) { notificationsForm.reset(defaultValues) } // eslint-disable-next-line react-hooks/exhaustive-deps }, [authConfig]) return ( <> {isError && ( )} {isLoading && ( )} {isSuccess && ( <> {builtInSMTP && ( You’re using the built-in email service. This service has rate limits and is not meant to be used for production apps.{' '} Learn more {' '}

} layout="horizontal" className="mb-4" actions={ } /> )} Authentication {TEMPLATES_SCHEMAS.filter( (t) => t.misc?.emailTemplateType === 'authentication' ).map((template) => { const templateSlug = slugifyTitle(template.title) return (

{template.title}

{template.purpose && (

{template.purpose}

)}
) })}
Security
{TEMPLATES_SCHEMAS.filter((t) => t.misc?.emailTemplateType === 'security').map( (template) => { const templateSlug = slugifyTitle(template.title) const templateEnabledKey = `MAILER_NOTIFICATIONS_${template.id?.replace('_NOTIFICATION', '')}_ENABLED` as keyof typeof authConfig return (

{template.title}

{template.purpose && (

{template.purpose}

)}
( )} />
) } )} {notificationsForm.formState.isDirty && ( )}
)} ) }