diff --git a/src/app/dashboard/profile/ChangeProfilePictureModal.tsx b/src/app/dashboard/profile/ChangeProfilePictureModal.tsx new file mode 100644 index 0000000..37ae0b1 --- /dev/null +++ b/src/app/dashboard/profile/ChangeProfilePictureModal.tsx @@ -0,0 +1,97 @@ +'use client'; + +import React, { useCallback } from 'react'; +import { useRouter } from 'next/navigation'; +import { Controller, type SubmitHandler, useForm } from 'react-hook-form'; +import { toast } from 'react-toastify'; +import { zodResolver } from '@hookform/resolvers/zod'; +import { z } from 'zod'; +import { Modal, ModalButton, type ModalProps } from '@/components/Modal'; +import { FileInput } from '@/components/Forms'; +import { Button } from '@/components/Button'; +import { fetchApi } from '@/utils/fetch'; +import { type User } from '@/types/users'; + +const profilePictureSchema = z.object({ + avatar: z.union([ + z.instanceof(File, { message: 'This field is required' }), + z.string(), + ]), +}); + +type ProfilePictureFormValues = z.infer; + +interface ChangeProfilePictureModalProps extends ModalProps { + user: User; +} + +export const ChangeProfilePictureModal: React.FC = ({ user, show, close }) => { + const router = useRouter(); + + const { control, handleSubmit, formState: { errors, isSubmitting } } = useForm({ + resolver: zodResolver(profilePictureSchema), + }); + + const putProfilePicture: SubmitHandler = useCallback((values) => { + const data = new FormData(); + + data.append('avatar', values.avatar); + + toast.promise( + fetchApi(`/users/${user.cid}/`, { method: 'PUT', body: data }), + { + pending: 'Saving changes', + success: 'Successfully saved', + error: 'Something went wrong, check console for more info', + }, + ) + .then(() => { + router.refresh(); + close?.(); + }); + }, [user, router, close]); + + const resetProfilePicture = () => putProfilePicture({ avatar: '' }); + + return ( + +
+ ( + onChange(acceptedFiles[0])} + /> + )} + /> + +
+ + + +
+ +
+ ); +}; + +export const ChangeProfilePictureButton: React.FC = ({ ...props }) => ( + }> + Change + +); diff --git a/src/app/dashboard/profile/EditProfileForm.tsx b/src/app/dashboard/profile/EditProfileForm.tsx index 3f3c063..c110e3c 100644 --- a/src/app/dashboard/profile/EditProfileForm.tsx +++ b/src/app/dashboard/profile/EditProfileForm.tsx @@ -9,6 +9,7 @@ import { TextAreaInput } from '@/components/Forms'; import { ProfilePicture } from '@/components/ProfilePicture'; import { fetchApi } from '@/utils/fetch'; import { type User } from '@/types/users'; +import { ChangeProfilePictureButton } from './ChangeProfilePictureModal'; import { type EditProfileFormValues, editProfileSchema } from './editProfileSchema'; interface EditProfileFormProps { @@ -38,22 +39,27 @@ export const EditProfileForm: React.FC = ({ user }) => { }, [user]); return ( -
-
- -

Profile picture updates coming soon!

+ <> +
+

Profile Picture

+
+ + +
- + + - - + + + ); }; diff --git a/src/app/staff/StaffCard.tsx b/src/app/staff/StaffCard.tsx index 8fc8436..72307e9 100644 --- a/src/app/staff/StaffCard.tsx +++ b/src/app/staff/StaffCard.tsx @@ -14,7 +14,7 @@ interface StaffCardProps { export const StaffCard: React.FC = ({ user, title, description, email }) => (
- +

{user ? `${user.first_name} ${user.last_name}` : 'Vacant'} diff --git a/src/components/ProfilePicture.tsx b/src/components/ProfilePicture.tsx index d001f23..a3d6471 100644 --- a/src/components/ProfilePicture.tsx +++ b/src/components/ProfilePicture.tsx @@ -1,53 +1,41 @@ import React from 'react'; import Image from 'next/image'; import classNames from 'classnames'; +import { LuUser } from 'react-icons/lu'; import { type BasicUser } from '@/types/users'; interface ProfilePictureProps { user?: BasicUser; - alt?: string; size: number; className?: string; } -export const ProfilePicture: React.FC = ({ user, size, alt = '', className }) => { - if (!user) { +export const ProfilePicture: React.FC = ({ user, size, className }) => { + if (user?.profile) { return ( {alt} ); } - if (!user.profile) { - return ( -

- {user.initials} -
- ); - } - return ( - {`${user.first_name} +
+ {user ? user.initials : } +
); };