From 0301e407125e3df86aa91c01e8cb0e484d0f0b11 Mon Sep 17 00:00:00 2001 From: Dominik Hryshaiev Date: Wed, 23 Oct 2024 00:10:46 +0200 Subject: [PATCH] refactor(user-account): deprecate redundant state provider (#110) --- src/components/Providers.tsx | 17 +-- src/components/header/Header.test.tsx | 6 +- .../user-account/AccountPage.test.tsx | 22 ++- .../user-account/AuthModalButton.test.tsx | 70 +++++----- .../user-account/AuthModalButton.tsx | 56 +++++--- src/context/UserAccount/UserAccountContext.ts | 24 ---- .../UserAccount/UserAccountProvider.tsx | 132 ------------------ src/context/UserAccount/index.ts | 3 - src/context/index.ts | 2 - src/services/user-account.ts | 41 +++--- 10 files changed, 117 insertions(+), 256 deletions(-) delete mode 100644 src/context/UserAccount/UserAccountContext.ts delete mode 100644 src/context/UserAccount/UserAccountProvider.tsx delete mode 100644 src/context/UserAccount/index.ts diff --git a/src/components/Providers.tsx b/src/components/Providers.tsx index 103d8a7..e7c27bd 100644 --- a/src/components/Providers.tsx +++ b/src/components/Providers.tsx @@ -3,7 +3,6 @@ import { OccurrencesProvider, SnackbarProvider, TraitsProvider, - UserAccountProvider, } from '@context'; import { supabaseClient } from '@helpers'; import { NextUIProvider } from '@nextui-org/react'; @@ -27,15 +26,13 @@ const LowerProviders = ({ children, rangeStart, rangeEnd }: ProviderProps) => { return ( - - - - - {children} - - - - + + + + {children} + + + ); diff --git a/src/components/header/Header.test.tsx b/src/components/header/Header.test.tsx index eeed039..2d859a5 100644 --- a/src/components/header/Header.test.tsx +++ b/src/components/header/Header.test.tsx @@ -1,4 +1,4 @@ -import { SnackbarProvider, UserAccountProvider } from '@context'; +import { SnackbarProvider } from '@context'; import { render } from '@testing-library/react'; import React from 'react'; import { BrowserRouter } from 'react-router-dom'; @@ -24,9 +24,7 @@ describe(Header.name, () => { const { getByText } = render( - -
- +
); diff --git a/src/components/user-account/AccountPage.test.tsx b/src/components/user-account/AccountPage.test.tsx index 82a077a..7bf1fa8 100644 --- a/src/components/user-account/AccountPage.test.tsx +++ b/src/components/user-account/AccountPage.test.tsx @@ -1,3 +1,12 @@ +import { SnackbarProvider } from '@context'; +import { useUser } from '@supabase/auth-helpers-react'; +import { act, fireEvent, render } from '@testing-library/react'; +import React from 'react'; +import { BrowserRouter } from 'react-router-dom'; + +import AccountPage from './AccountPage'; +import { useAccountPage } from './use-account-page'; + jest.mock('./use-account-page'); jest.mock('@supabase/auth-helpers-react', () => ({ ...jest.requireActual('@supabase/auth-helpers-react'), @@ -10,15 +19,6 @@ jest.mock('./use-auth-search-params', () => ({ useAuthSearchParams: jest.fn(), })); -import { SnackbarProvider, UserAccountProvider } from '@context'; -import { useUser } from '@supabase/auth-helpers-react'; -import { act, fireEvent, render } from '@testing-library/react'; -import React from 'react'; -import { BrowserRouter } from 'react-router-dom'; - -import AccountPage from './AccountPage'; -import { useAccountPage } from './use-account-page'; - describe(AccountPage.name, () => { it('should show loader', () => { (useAccountPage as jest.Mock).mockReturnValue({ @@ -53,9 +53,7 @@ describe(AccountPage.name, () => { const { getByTestId } = render( - - - + ); diff --git a/src/components/user-account/AuthModalButton.test.tsx b/src/components/user-account/AuthModalButton.test.tsx index b263ffb..8cc311d 100644 --- a/src/components/user-account/AuthModalButton.test.tsx +++ b/src/components/user-account/AuthModalButton.test.tsx @@ -1,4 +1,4 @@ -import { SnackbarProvider, useUserAccount } from '@context'; +import { SnackbarProvider } from '@context'; import { act, fireEvent, render, waitFor } from '@testing-library/react'; import React from 'react'; import { BrowserRouter } from 'react-router-dom'; @@ -21,13 +21,13 @@ jest.mock('react-router-dom', () => ({ jest.mock('@context', () => ({ ...jest.requireActual('@context'), __esModule: true, - useUserAccount: jest.fn().mockReturnValue({ - supabaseUser: { id: null }, - login: jest.fn(), - logout: jest.fn(), - register: jest.fn(), - authenticating: false, - }), + // useUserAccount: jest.fn().mockReturnValue({ + // supabaseUser: { id: null }, + // login: jest.fn(), + // logout: jest.fn(), + // register: jest.fn(), + // authenticating: false, + // }), })); describe(AuthModalButton.name, () => { @@ -46,9 +46,9 @@ describe(AuthModalButton.name, () => { }); it.skip('should navigate to /account if user is logged in', async () => { - (useUserAccount as jest.Mock).mockReturnValue({ - supabaseUser: { id: '123' }, - }); + // (useUserAccount as jest.Mock).mockReturnValue({ + // supabaseUser: { id: '123' }, + // }); const { getByTestId, queryByText } = render( @@ -63,9 +63,9 @@ describe(AuthModalButton.name, () => { }); it.skip('should switch to register mode', () => { - (useUserAccount as jest.Mock).mockReturnValue({ - supabaseUser: { id: null }, - }); + // (useUserAccount as jest.Mock).mockReturnValue({ + // supabaseUser: { id: null }, + // }); const { getByTestId, getByText } = render( @@ -104,10 +104,10 @@ describe(AuthModalButton.name, () => { }); it.skip('should call login on submit', async () => { - (useUserAccount as jest.Mock).mockReturnValue({ - supabaseUser: { id: null }, - login: jest.fn(), - }); + // (useUserAccount as jest.Mock).mockReturnValue({ + // supabaseUser: { id: null }, + // login: jest.fn(), + // }); const { getByTestId } = render( @@ -117,16 +117,16 @@ describe(AuthModalButton.name, () => { fireEvent.click(button); const submit = getByTestId('submit-button'); fireEvent.click(submit); - await waitFor(() => { - expect(useUserAccount().login).toHaveBeenCalled(); - }); + // await waitFor(() => { + // expect(useUserAccount().login).toHaveBeenCalled(); + // }); }); it.skip('should call register on submit', async () => { - (useUserAccount as jest.Mock).mockReturnValue({ - supabaseUser: { id: null }, - register: jest.fn(), - }); + // (useUserAccount as jest.Mock).mockReturnValue({ + // supabaseUser: { id: null }, + // register: jest.fn(), + // }); const { getByTestId, getByText } = render( @@ -138,15 +138,15 @@ describe(AuthModalButton.name, () => { fireEvent.click(registerTab); const submitRegisterButton = getByTestId('submit-button'); fireEvent.click(submitRegisterButton); - await waitFor(() => { - expect(useUserAccount().register).toHaveBeenCalled(); - }); + // await waitFor(() => { + // expect(useUserAccount().register).toHaveBeenCalled(); + // }); }); it.skip('should display start decorators and logout button if user is logged in', () => { - (useUserAccount as jest.Mock).mockReturnValue({ - supabaseUser: { id: '123' }, - }); + // (useUserAccount as jest.Mock).mockReturnValue({ + // supabaseUser: { id: '123' }, + // }); const { getByTestId, queryByTestId } = render( @@ -160,10 +160,10 @@ describe(AuthModalButton.name, () => { it.skip('should call logout on logout button click if user is logged in', () => { const mockLogOut = jest.fn(); - (useUserAccount as jest.Mock).mockReturnValue({ - supabaseUser: { id: '123' }, - logout: mockLogOut, - }); + // (useUserAccount as jest.Mock).mockReturnValue({ + // supabaseUser: { id: '123' }, + // logout: mockLogOut, + // }); const { getByTestId } = render( diff --git a/src/components/user-account/AuthModalButton.tsx b/src/components/user-account/AuthModalButton.tsx index 11eb383..09973a7 100644 --- a/src/components/user-account/AuthModalButton.tsx +++ b/src/components/user-account/AuthModalButton.tsx @@ -1,4 +1,4 @@ -import { useUserAccount } from '@context'; +import { useSnackbar } from '@context'; import { Button, ButtonGroup, @@ -16,6 +16,9 @@ import { SignOut as SignOutIcon, User as UserIcon, } from '@phosphor-icons/react'; +import { sendPasswordResetEmail, signIn, signOut, signUp } from '@services'; +import { useUser } from '@supabase/auth-helpers-react'; +import { getErrorMessage } from '@utils'; import React from 'react'; import { Link } from 'react-router-dom'; @@ -24,15 +27,10 @@ import AuthForm from './AuthForm'; export type AuthMode = 'login' | 'register' | 'reset-password'; const AuthModalButton = () => { - const { - login, - logout, - register, - resetPassword, - authenticating, - supabaseUser, - } = useUserAccount(); + const user = useUser(); + const { showSnackbar } = useSnackbar(); const { isOpen, onOpen, onOpenChange, onClose } = useDisclosure(); + const [authenticating, setAuthenticating] = React.useState(false); const [mode, setMode] = React.useState('login'); const handleClose = () => { @@ -48,9 +46,9 @@ const AuthModalButton = () => { AuthMode, (email: string, password: string, name: string) => Promise > = { - login, - register, - 'reset-password': resetPassword, + login: signIn, + register: signUp, + 'reset-password': sendPasswordResetEmail, }; const actionLabels: Record = { @@ -65,14 +63,40 @@ const AuthModalButton = () => { 'reset-password': 'Reset your password', }; + const successfulMessages: Record = { + login: 'Welcome back!', + register: 'Account created!', + 'reset-password': 'Password reset email sent!', + }; + const handleSubmit = async ( email: string, password: string, name: string ) => { - await actions[mode](email, password, name); + try { + setAuthenticating(true); + + await actions[mode](email, password, name); + + setAuthenticating(false); + + handleClose(); - handleClose(); + showSnackbar(successfulMessages[mode], { + color: 'success', + dismissible: true, + dismissText: 'Done', + }); + } catch (error) { + showSnackbar('Something went wrong. Please try again.', { + description: `Error details: ${getErrorMessage(error)}`, + color: 'danger', + dismissible: true, + }); + } finally { + setAuthenticating(false); + } }; const authFormProps = { @@ -87,7 +111,7 @@ const AuthModalButton = () => { return ( <> - {supabaseUser?.id ? ( + {user?.id ? (