import { useMemo } from 'react'; import { zodResolver } from '@hookform/resolvers/zod'; import { Trans, msg } from '@lingui/macro'; import { useLingui } from '@lingui/react'; // Todo // import { ErrorCode, useDropzone } from 'react-dropzone'; import { useForm } from 'react-hook-form'; import { match } from 'ts-pattern'; import { z } from 'zod'; import { AppError } from '@documenso/lib/errors/app-error'; import { formatAvatarUrl } from '@documenso/lib/utils/avatars'; import { extractInitials } from '@documenso/lib/utils/recipient-formatter'; import { trpc } from '@documenso/trpc/react'; import { cn } from '@documenso/ui/lib/utils'; import { Avatar, AvatarFallback, AvatarImage } from '@documenso/ui/primitives/avatar'; import { Button } from '@documenso/ui/primitives/button'; import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage, } from '@documenso/ui/primitives/form/form'; import { useToast } from '@documenso/ui/primitives/use-toast'; import { useAuth } from '~/providers/auth'; import { useOptionalCurrentTeam } from '~/providers/team'; export const ZAvatarImageFormSchema = z.object({ bytes: z.string().nullish(), }); export type TAvatarImageFormSchema = z.infer; export type AvatarImageFormProps = { className?: string; }; export const AvatarImageForm = ({ className }: AvatarImageFormProps) => { const { _ } = useLingui(); const { toast } = useToast(); const { user } = useAuth(); const team = useOptionalCurrentTeam(); const { mutateAsync: setProfileImage } = trpc.profile.setProfileImage.useMutation(); const initials = extractInitials(team?.name || user.name || ''); const hasAvatarImage = useMemo(() => { if (team) { return team.avatarImageId !== null; } return user.avatarImageId !== null; }, [team, user.avatarImageId]); const avatarImageId = team ? team.avatarImageId : user.avatarImageId; const form = useForm({ values: { bytes: null, }, resolver: zodResolver(ZAvatarImageFormSchema), }); // const { getRootProps, getInputProps } = useDropzone({ // maxSize: 1024 * 1024, // accept: { // 'image/*': ['.png', '.jpg', '.jpeg'], // }, // multiple: false, // onDropAccepted: ([file]) => { // void file.arrayBuffer().then((buffer) => { // const contents = base64.encode(new Uint8Array(buffer)); // form.setValue('bytes', contents); // void form.handleSubmit(onFormSubmit)(); // }); // }, // onDropRejected: ([file]) => { // form.setError('bytes', { // type: 'onChange', // message: match(file.errors[0].code) // .with(ErrorCode.FileTooLarge, () => _(msg`Uploaded file is too large`)) // .with(ErrorCode.FileTooSmall, () => _(msg`Uploaded file is too small`)) // .with(ErrorCode.FileInvalidType, () => _(msg`Uploaded file not an allowed file type`)) // .otherwise(() => _(msg`An unknown error occurred`)), // }); // }, // }); const onFormSubmit = async (data: TAvatarImageFormSchema) => { try { await setProfileImage({ bytes: data.bytes, teamId: team?.id, }); toast({ title: _(msg`Avatar Updated`), description: _(msg`Your avatar has been updated successfully.`), duration: 5000, }); // router.refresh(); // Todo } catch (err) { const error = AppError.parseError(err); const errorMessage = match(error.code).otherwise( () => msg`We encountered an unknown error while attempting to update your password. Please try again later.`, ); toast({ title: _(msg`An error occurred`), description: _(errorMessage), variant: 'destructive', }); } }; return (
( Avatar
{avatarImageId && } {initials} {hasAvatarImage && ( )}
)} />
); };