Advertisement
Guest User

Untitled

a guest
Jun 22nd, 2025
41
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. import {
  2.   getCognitoUser,
  3.   getEVUser,
  4.   setEVUserAttributes,
  5. } from '@/lib/schema/user/client-fetch';
  6. import { CognitoUser, EVUser } from '@/lib/schema/user/types';
  7. import { showToast } from '@/lib/toast';
  8. import { useQuery } from '@tanstack/react-query';
  9. import {
  10.   deleteUser as deleteCognitoUser,
  11.   updateUserAttributes,
  12. } from 'aws-amplify/auth';
  13. import { Hub, HubCapsule } from 'aws-amplify/utils';
  14.  
  15. import {
  16.   createContext,
  17.   FC,
  18.   PropsWithChildren,
  19.   useCallback,
  20.   useEffect,
  21.   useMemo,
  22.   useState,
  23. } from 'react';
  24.  
  25. export interface AuthContextType {
  26.   user: CognitoUser | null;
  27.   evUser: EVUser | null;
  28.   updateEVUser: (newEVUser: EVUser) => Promise<{ ok: boolean }>;
  29.   deleteUser: () => Promise<{ ok: boolean }>;
  30.   error: boolean;
  31.   loading: boolean;
  32. }
  33.  
  34. export const AuthContext = createContext<AuthContextType | null>(null);
  35.  
  36. interface AuthProviderProps {
  37.   ssrUser?: CognitoUser | null;
  38. }
  39.  
  40. /**
  41.  * Context that holds and controls the signed in state.
  42.  *
  43.  * @param {AuthProviderProps} props - The properties for the AuthProvider component.
  44.  * @param {ReactNode} props.children - The children components that require access to authentication context.
  45.  * @param {User} [props.preloadedUser] - A user object that is preloaded, if available.
  46.  * @param {User} [props.user] - The current authenticated Cognito user.
  47.  * @param {EVUser} props.evUser - The user data stored in the database - used to render user info on client side.
  48.  * @param {() => void} props.updateEVUser - Function to update the evUser - updates the database and will update the client render.
  49.  * @param {boolean} props.isLoading - Loading state of the authentication context.
  50.  * @param {boolean} props.isError - Error state of the authentication context.
  51.  * @returns {JSX.Element} The AuthContext.Provider component with authentication context values.
  52.  */
  53. export const AuthProvider: FC<PropsWithChildren<AuthProviderProps>> = ({
  54.   children,
  55.   ssrUser,
  56. }) => {
  57.   const [preloadedUser, setPreloadedUser] = useState(ssrUser);
  58.   const [evUser, setEVUser] = useState<EVUser | null>(null);
  59.   Hub.listen('auth', async (data: HubCapsule<'auth', any>) => {
  60.     switch (data.payload.event) {
  61.       case 'signedIn':
  62.         console.log('signedIn from auth provider');
  63.  
  64.         refetchUser();
  65.  
  66.         setPreloadedUser(null);
  67.         break;
  68.       case 'signedOut':
  69.         console.log('signed out from auth provider');
  70.         setPreloadedUser(null);
  71.         refetchUser();
  72.         break;
  73.       default:
  74.         break;
  75.     }
  76.   });
  77.  
  78.   const updateUser = async () => {
  79.     const newUser = await getCognitoUser();
  80.     if (newUser) {
  81.       const newEVUser = await getEVUser();
  82.       setEVUser(newEVUser);
  83.       if (newEVUser) {
  84.         const updatedFields: { given_name?: string; family_name?: string } = {};
  85.         if (newEVUser.firstName) {
  86.           updatedFields.given_name = newEVUser.firstName;
  87.         }
  88.         if (newEVUser.lastName) {
  89.           updatedFields.family_name = newEVUser.lastName;
  90.         }
  91.         await updateUserAttributes({ userAttributes: updatedFields });
  92.       }
  93.     }
  94.     return newUser;
  95.   };
  96.  
  97.   const updateEVUser = useCallback(async (newEVUser: EVUser) => {
  98.     try {
  99.       await setEVUserAttributes(newEVUser);
  100.       await updateUserAttributes({
  101.         userAttributes: {
  102.           given_name: newEVUser.firstName,
  103.           family_name: newEVUser.lastName,
  104.         },
  105.       });
  106.       setEVUser(newEVUser);
  107.       showToast('Successfully saved your profile!', { type: 'success' });
  108.       return { ok: true };
  109.     } catch (err) {
  110.       showToast('Something went wrong saving your profile. Please try again.', {
  111.         type: 'error',
  112.       });
  113.       return { ok: false };
  114.     }
  115.   }, []);
  116.  
  117.   const deleteUser = useCallback(async () => {
  118.     try {
  119.       if (evUser) {
  120.         await setEVUserAttributes({
  121.           ...evUser,
  122.           flaggedForDeletion: true,
  123.         });
  124.         await deleteCognitoUser();
  125.         setEVUser(null);
  126.       }
  127.       return { ok: true };
  128.     } catch (err) {
  129.       showToast(
  130.         'Something went wrong deleting your account. Please try again.',
  131.         {
  132.           type: 'error',
  133.         }
  134.       );
  135.       return { ok: false };
  136.     }
  137.   }, [evUser]);
  138.  
  139.   const {
  140.     data: user,
  141.     refetch: refetchUser,
  142.     isLoading,
  143.     isError,
  144.   } = useQuery({
  145.     queryKey: ['cognito-user'],
  146.     queryFn: updateUser,
  147.   });
  148.  
  149.   const value = useMemo(
  150.     () => ({
  151.       user: preloadedUser || user || null,
  152.       evUser,
  153.       updateEVUser,
  154.       deleteUser,
  155.       loading: isLoading,
  156.       error: isError,
  157.     }),
  158.     [preloadedUser, user, isLoading, isError, evUser, updateEVUser, deleteUser]
  159.   );
  160.  
  161.   return <AuthContext.Provider value={value}>{children}</AuthContext.Provider>;
  162. };
  163.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement