From f10abb7c8834566b3c7e816575b7db500a168631 Mon Sep 17 00:00:00 2001 From: onehanddev Date: Sat, 14 Dec 2024 17:41:44 +0530 Subject: [PATCH] Hide My custom projects tab in navigation sidebar when user is not logged and Re-organize My custom projects in Profile section --- client/src/containers/nav/index.tsx | 54 ++- .../profile/edit-password/form/index.tsx | 2 +- .../containers/profile/user-details/index.tsx | 392 +++++++++++++++++- 3 files changed, 412 insertions(+), 36 deletions(-) diff --git a/client/src/containers/nav/index.tsx b/client/src/containers/nav/index.tsx index 0d87477a..9dc71067 100644 --- a/client/src/containers/nav/index.tsx +++ b/client/src/containers/nav/index.tsx @@ -47,6 +47,7 @@ const navItems = { url: "/my-projects", icon: ClipboardListIcon, match: (pathname: string) => pathname === "/my-projects", + requireAuth: true, }, { title: "Admin", @@ -70,6 +71,9 @@ export default function MainNav() { const { status } = useSession(); const pathname = usePathname(); + // Don't render nav items until authentication is determined + const isLoading = status === "loading"; + return ( @@ -79,29 +83,33 @@ export default function MainNav() { - {navItems.main.map((item) => { - const isActive = item.match(pathname); - return ( - - - - {item.icon && } - {item.title} - - - - ); - })} + {!isLoading && navItems.main + .filter( + (item) => !item.requireAuth || status === "authenticated" + ) + .map((item) => { + const isActive = item.match(pathname); + return ( + + + + {item.icon && } + {item.title} + + + + ); + })} diff --git a/client/src/containers/profile/edit-password/form/index.tsx b/client/src/containers/profile/edit-password/form/index.tsx index aab9f53c..ab5348ac 100644 --- a/client/src/containers/profile/edit-password/form/index.tsx +++ b/client/src/containers/profile/edit-password/form/index.tsx @@ -96,7 +96,7 @@ const SignUpForm: FC = () => { name="password" render={({ field }) => ( - Password + Your password
{ + const queryClient = useQueryClient(); + const { data: session, update: updateSession } = useSession(); + const formRef = useRef(null); + const { toast } = useToast(); + + const { data: user } = client.user.findMe.useQuery( + queryKeys.user.me(session?.user?.id as string).queryKey, + { + extraHeaders: { + authorization: `Bearer ${session?.accessToken as string}`, + }, + }, + { + select: (data) => data.body.data, + queryKey: queryKeys.user.me(session?.user?.id as string).queryKey, + }, + ); + + const accountForm = useForm>({ + resolver: zodResolver(accountDetailsSchema), + defaultValues: { + name: user?.name, + role: user?.role, + }, + mode: "onSubmit", + }); + + const emailForm = useForm>({ + resolver: zodResolver(accountDetailsSchema), + defaultValues: { + email: user?.email, + }, + mode: "onSubmit", + }); + + const passwordForm = useForm>({ + resolver: zodResolver(changePasswordSchema), + defaultValues: { + password: "", + newPassword: "", + confirmPassword: "", + }, + mode: "onSubmit", + }); + + const onSubmitAccount = useCallback( + async (data: FormData) => { + const formData = Object.fromEntries(data); + const parsed = accountDetailsSchema.safeParse(formData); + + if (parsed.success) { + const response = await client.user.updateMe.mutation({ + params: { + id: session?.user?.id as string, + }, + body: { + name: parsed.data.name, + }, + extraHeaders: { + authorization: `Bearer ${session?.accessToken as string}`, + }, + }); + + if (response.status === 200) { + await updateSession(response.body); + await queryClient.invalidateQueries({ + queryKey: queryKeys.user.me(session?.user?.id as string).queryKey, + }); + toast({ + description: "Your account details have been updated successfully.", + }); + } + } + }, + [queryClient, session, updateSession, toast], + ); + + const onSubmitEmail = useCallback( + async (data: FormData) => { + const formData = Object.fromEntries(data); + const parsed = accountDetailsSchema.safeParse(formData); + + if (parsed.success) { + try { + const response = await client.user.requestEmailUpdate.mutation({ + body: { + newEmail: parsed.data.email, + }, + extraHeaders: { + authorization: `Bearer ${session?.accessToken as string}`, + }, + }); + + if (response.status === 200) { + updateSession(response.body); + queryClient.invalidateQueries({ + queryKey: queryKeys.user.me(session?.user?.id as string).queryKey, + }); + toast({ + description: "You will receive an email in your inbox.", + }); + } else { + toast({ + variant: "destructive", + description: "Something went wrong updating the email", + }); + } + } catch (e) { + toast({ + variant: "destructive", + description: "Something went wrong updating the email", + }); + } + } + }, + [queryClient, session, updateSession, toast], + ); + + const onSubmitPassword = useCallback( + async (data: FormData) => { + const formData = Object.fromEntries(data); + const parsed = changePasswordSchema.safeParse(formData); + if (parsed.success) { + try { + const response = await client.user.updatePassword.mutation({ + body: { + password: parsed.data.password, + newPassword: parsed.data.newPassword, + }, + extraHeaders: { + authorization: `Bearer ${session?.accessToken as string}`, + }, + }); + + if (response.status === 200) { + toast({ + description: "Your password has been updated successfully.", + }); + passwordForm.reset(); + } + + if (response.status === 400 || response.status === 401) { + toast({ + variant: "destructive", + description: response.body.errors?.[0].title, + }); + } + } catch (e) { + toast({ + variant: "destructive", + description: "Something went wrong updating the password", + }); + } + } + }, + [session, toast, passwordForm], + ); + + const handleEnterKey = useCallback( + (evt: KeyboardEvent, form: any, onSubmit: (data: FormData) => Promise) => { + if (evt.code === "Enter" && form.formState.isValid) { + form.handleSubmit(async () => { + await onSubmit(new FormData(formRef.current!)); + })(); + } + }, + [], + ); + return (
- - - - - - - - + +
+ {/* Account Details Section */} +
+ { + evt.preventDefault(); + accountForm.handleSubmit(async () => { + await onSubmitAccount(new FormData(formRef.current!)); + })(evt); + }} + > +

Account Details

+ ( + + Your name + +
+ handleEnterKey(e, accountForm, onSubmitAccount)} + {...field} + /> +
+
+ +
+ )} + /> + ( + + Role + +
+ +
+
+ +
+ )} + /> +
+ + +
+ + + + {/* Email Update Section */} +
+ { + evt.preventDefault(); + emailForm.handleSubmit(async () => { + await onSubmitEmail(new FormData(formRef.current!)); + })(evt); + }} + > +

Email Settings

+ ( + + Your email + +
+ handleEnterKey(e, emailForm, onSubmitEmail)} + placeholder={user?.email} + className="w-full" + {...field} + /> +
+
+ +
+ )} + /> +
+ +
+ + + + {/* Password Update Section */} +
+ { + evt.preventDefault(); + passwordForm.handleSubmit(async () => { + await onSubmitPassword(new FormData(formRef.current!)); + })(evt); + }} + > +

Password Settings

+ ( + + Current password + +
+ handleEnterKey(e, passwordForm, onSubmitPassword)} + {...field} + /> +
+
+ +
+ )} + /> + ( + + New password + +
+ handleEnterKey(e, passwordForm, onSubmitPassword)} + {...field} + /> +
+
+ +
+ )} + /> + ( + + Confirm new password + +
+ handleEnterKey(e, passwordForm, onSubmitPassword)} + {...field} + /> +
+
+ +
+ )} + /> +
+ +
+ + +
);