From a6dc105e8b9fa4a32b5706c1779866e02250b8b5 Mon Sep 17 00:00:00 2001 From: madhav-relish Date: Thu, 15 Aug 2024 17:40:13 +0530 Subject: [PATCH] Fix: #177 Loading state in profile setting modal - A custom skeleton component is added which can be used further - Two loading states are there one for when the profile details are loading and the other when the user submits the form --- .../components/layout/settings.component.tsx | 85 ++++++++++++++++--- .../src/components/layout/skeleton.tsx | 32 +++++++ 2 files changed, 104 insertions(+), 13 deletions(-) create mode 100644 apps/frontend/src/components/layout/skeleton.tsx diff --git a/apps/frontend/src/components/layout/settings.component.tsx b/apps/frontend/src/components/layout/settings.component.tsx index a8854ae2..77f75719 100644 --- a/apps/frontend/src/components/layout/settings.component.tsx +++ b/apps/frontend/src/components/layout/settings.component.tsx @@ -1,5 +1,12 @@ import { useModals } from '@mantine/modals'; -import React, { FC, Ref, useCallback, useEffect, useMemo } from 'react'; +import React, { + FC, + Ref, + useCallback, + useEffect, + useMemo, + useState, +} from 'react'; import { Input } from '@gitroom/react/form/input'; import { Button } from '@gitroom/react/form/button'; import { Textarea } from '@gitroom/react/form/textarea'; @@ -16,6 +23,8 @@ import { isGeneral } from '@gitroom/react/helpers/is.general'; import { useUser } from '@gitroom/frontend/components/layout/user.context'; import { LogoutComponent } from '@gitroom/frontend/components/layout/logout.component'; import { useSearchParams } from 'next/navigation'; +import ReactLoading from 'react-loading'; +import Skeleton from './skeleton'; export const SettingsPopup: FC<{ getRef?: Ref }> = (props) => { const { getRef } = props; @@ -23,6 +32,11 @@ export const SettingsPopup: FC<{ getRef?: Ref }> = (props) => { const toast = useToaster(); const swr = useSWRConfig(); const user = useUser(); + // Loading states for better ux + const [loading, setLoading] = useState({ + isProfileLoading: false, //When the user details are loading + isSaving: false, // When the user submits the form + }); const resolver = useMemo(() => { return classValidatorResolver(UserDetailDto); @@ -38,10 +52,18 @@ export const SettingsPopup: FC<{ getRef?: Ref }> = (props) => { const showLogout = !url.get('onboarding'); const loadProfile = useCallback(async () => { + setLoading((prevState) => ({ + ...prevState, + isProfileLoading: true, + })); const personal = await (await fetch('/user/personal')).json(); form.setValue('fullname', personal.name || ''); form.setValue('bio', personal.bio || ''); form.setValue('picture', personal.picture); + setLoading((prevState) => ({ + ...prevState, + isProfileLoading: false, + })); }, []); const openMedia = useCallback(() => { @@ -55,6 +77,10 @@ export const SettingsPopup: FC<{ getRef?: Ref }> = (props) => { }, []); const submit = useCallback(async (val: any) => { + setLoading((prevState) => ({ + ...prevState, + isSaving: true, + })); await fetch('/user/personal', { method: 'POST', body: JSON.stringify(val), @@ -64,6 +90,10 @@ export const SettingsPopup: FC<{ getRef?: Ref }> = (props) => { return; } + setLoading((prevState) => ({ + ...prevState, + isSaving: false, + })); toast.show('Profile updated'); swr.mutate('/marketplace/account'); close(); @@ -119,18 +149,29 @@ export const SettingsPopup: FC<{ getRef?: Ref }> = (props) => {
- + {loading.isProfileLoading ? ( +
+ + +
+ ) : ( + + )}
-
- {!!picture?.path && ( - profile - )} -
+ {loading.isProfileLoading ? ( + + ) : ( +
+ {!!picture?.path && ( + profile + )} +
+ )}
Profile Picture
@@ -183,12 +224,30 @@ export const SettingsPopup: FC<{ getRef?: Ref }> = (props) => {
-