import { zodResolver } from '@hookform/resolvers/zod' import { PermissionAction } from '@supabase/shared-types/out/constants' import { Form, FormControl, FormField } from '@ui/components/shadcn/ui/form' import { useParams } from 'common' import { useEffect } from 'react' import { useForm } from 'react-hook-form' import { toast } from 'sonner' import { FormMessage, Input } from 'ui' import { FormItemLayout } from 'ui-patterns/form/FormItemLayout/FormItemLayout' import { InfoTooltip } from 'ui-patterns/info-tooltip' import { MultiSelector, MultiSelectorContent, MultiSelectorList, MultiSelectorTrigger, } from 'ui-patterns/multi-select' import { z } from 'zod' import { ScaffoldSection, ScaffoldSectionContent, ScaffoldSectionDetail, } from '@/components/layouts/Scaffold' import { FormActions } from '@/components/ui/Forms/FormActions' import { FormPanel } from '@/components/ui/Forms/FormPanel' import { FormSection, FormSectionContent } from '@/components/ui/Forms/FormSection' import NoPermission from '@/components/ui/NoPermission' import { useOrganizationCustomerProfileQuery } from '@/data/organizations/organization-customer-profile-query' import { useOrganizationUpdateMutation } from '@/data/organizations/organization-update-mutation' import { useAsyncCheckPermissions } from '@/hooks/misc/useCheckPermissions' import { useSelectedOrganizationQuery } from '@/hooks/misc/useSelectedOrganization' const FORM_ID = 'org-billing-email' const formSchema = z.object({ billingEmail: z.string().email('Please provide a valid email address').optional(), additionalBillingEmails: z.string().email({ message: 'invalid_email' }).array().default([]), }) const BillingEmail = () => { const { slug } = useParams() const { data: selectedOrganization } = useSelectedOrganizationQuery() const { name, billing_email } = selectedOrganization ?? {} const { can: canReadBillingEmail, isSuccess: isPermissionsLoaded } = useAsyncCheckPermissions( PermissionAction.BILLING_READ, 'stripe.subscriptions' ) const { can: canUpdateOrganization } = useAsyncCheckPermissions( PermissionAction.UPDATE, 'organizations' ) const { data: billingCustomer, isPending: loadingBillingCustomer } = useOrganizationCustomerProfileQuery({ slug }, { enabled: canReadBillingEmail }) const form = useForm>({ resolver: zodResolver(formSchema as any), defaultValues: { billingEmail: billing_email ?? '', additionalBillingEmails: billingCustomer?.additional_emails ?? [], }, }) const { additionalBillingEmails } = form.watch() const { errors } = form.formState const additionalEmailsError = errors.additionalBillingEmails ?? [] const { mutate: updateOrganization, isPending: isUpdating } = useOrganizationUpdateMutation() const onUpdateOrganizationEmail = async (values: z.infer) => { if (!canUpdateOrganization) { return toast.error('You do not have the required permissions to update this organization') } if (!slug) return console.error('Slug is required') if (!name) return console.error('Organization name is required') updateOrganization( { slug, name, billing_email: values.billingEmail, additional_billing_emails: values.additionalBillingEmails, }, { onSuccess: () => { toast.success('Successfully saved settings') form.reset(values) }, } ) } useEffect(() => { if (billingCustomer) { form.reset({ billingEmail: billing_email ?? '', additionalBillingEmails: billingCustomer.additional_emails ?? [], }) } }, [billingCustomer]) return (

Email Recipient

All billing correspondence will go to this email

{isPermissionsLoaded && !canReadBillingEmail ? ( ) : (
} > ( )} /> ( Additional emails These email addresses will be CC'd in automated invoice or payment failure emails. Payment receipts will still only go to the primary billing address. } > {/* [Joshen] Manually construct the message here as MultiSelector doesn't handle array errors from RHF atm */} {Array.isArray(additionalEmailsError) && additionalEmailsError.length > 0 && (
{additionalEmailsError.map((_x, idx) => (

"{additionalBillingEmails[idx]}" is not a valid email address

))}
)}
)} />
)}
) } export default BillingEmail