Files
diplom-frontend/app/components/modals/update-profile-modal.tsx
2025-05-21 08:46:12 +03:00

154 lines
5.7 KiB
TypeScript

import { zodResolver } from "@hookform/resolvers/zod";
import { useForm } from "react-hook-form";
import { z } from "zod";
import { useShallow } from "zustand/react/shallow";
import file from "~/lib/api/client/file";
import { patchUser } from "~/lib/api/client/user";
import { ModalType, useModalStore } from "~/stores/modal-store";
import { useUsersStore } from "~/stores/users-store";
import { Button } from "../ui/button";
import {
Dialog,
DialogClose,
DialogContent,
DialogDescription,
DialogFooter,
DialogHeader,
DialogTitle,
} from "../ui/dialog";
import {
Form,
FormControl,
FormField,
FormItem,
FormLabel,
FormMessage,
} from "../ui/form";
import { IconUploadField } from "../ui/icon-upload-field";
import { Input } from "../ui/input";
const schema = z.object({
displayName: z.string().min(1).max(32).optional().nullable(),
avatar: z.instanceof(File).optional().nullable(),
});
export default function UpdateProfileModal() {
const { type, isOpen, onClose } = useModalStore();
const user = useUsersStore(useShallow((state) => state.getCurrentUser()));
const isModalOpen = type === ModalType.UPDATE_PROFILE && isOpen;
let form = useForm<z.infer<typeof schema>>({
resolver: zodResolver(schema),
});
const onOpenChange = () => {
form.reset();
onClose();
};
const onSubmit = async (values: z.infer<typeof schema>) => {
console.log("values", values);
if (!values) return;
let avatarId: string | null | undefined =
values.avatar === null ? null : undefined;
if (values.avatar) {
avatarId = (await file.uploadFile(values.avatar))[0];
}
const response = await patchUser({
displayName: values.displayName,
avatarId,
});
form.reset();
onClose();
};
return (
<Dialog open={isModalOpen} onOpenChange={onOpenChange}>
<DialogContent className="sm:max-w-md">
<DialogHeader>
<DialogTitle>Update profile</DialogTitle>
<DialogDescription>Update your profile.</DialogDescription>
</DialogHeader>
<Form {...form}>
<form
onSubmit={form.handleSubmit(onSubmit)}
className="space-y-4"
>
<FormField
control={form.control}
name="avatar"
render={({ field, fieldState }) => (
<FormItem>
<FormLabel
required={
!schema.shape.avatar.isOptional()
}
>
Avatar
</FormLabel>
<FormControl>
<div className="flex flex-col items-center justify-center">
<IconUploadField
defaultPreview={user?.avatarUrl}
formDefaultValue={
user?.avatarUrl
}
field={field}
error={fieldState.error}
/>
</div>
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name="displayName"
render={({ field }) => (
<FormItem>
<FormLabel
required={
!schema.shape.displayName.isOptional()
}
>
Display Name
</FormLabel>
<FormControl>
<Input
{...field}
placeholder={user?.displayName}
/>
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<DialogFooter className=" justify-between">
<DialogClose asChild>
<Button type="button" variant="secondary">
Close
</Button>
</DialogClose>
<Button
type="submit"
disabled={form.formState.isSubmitting}
>
{form.formState.isSubmitting
? "Updating..."
: "Update"}
</Button>
</DialogFooter>
</form>
</Form>
</DialogContent>
</Dialog>
);
}