Skip to content

Commit

Permalink
Rewrited auth mutation endpoints using RTK Query (#1422)
Browse files Browse the repository at this point in the history
* rewrited mutation endpoints using RTK Query

* fix

* moved dispatch to api slice

* fix tests
  • Loading branch information
Tolik170 authored Nov 28, 2023
1 parent 6285810 commit e1fc2a7
Show file tree
Hide file tree
Showing 18 changed files with 224 additions and 221 deletions.
15 changes: 7 additions & 8 deletions src/containers/guest-home-page/google-button/GoogleButton.jsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import { useCallback, useEffect } from 'react'
import { useDispatch } from 'react-redux'
import { useHref } from 'react-router-dom'

import { googleAuth } from '~/redux/reducer'
import { useGoogleAuthMutation } from '~/services/auth-service'
import { useModalContext } from '~/context/modal-context'
import { useSnackBarContext } from '~/context/snackbar-context'
import { scrollToHash } from '~/utils/hash-scroll'
Expand All @@ -12,29 +11,29 @@ import { snackbarVariants } from '~/constants'
import { styles } from '~/containers/guest-home-page/google-button/GoogleButton.styles'

const GoogleButton = ({ role, route, buttonWidth, type }) => {
const dispatch = useDispatch()
const ref = useHref(route)
const mediaQuery = useBreakpoints().isLaptopAndAbove ? 'md' : 'xs'
const { closeModal } = useModalContext()
const { setAlert } = useSnackBarContext()
const ref = useHref(route)
const [googleAuth] = useGoogleAuthMutation()

const handleCredentialResponse = useCallback(
async (token) => {
try {
await dispatch(googleAuth({ token, role })).unwrap()
await googleAuth({ token, role }).unwrap()
closeModal()
} catch (e) {
setAlert({
severity: snackbarVariants.error,
message: `errors.${e}`
message: `errors.${e.data.code}`
})
if (e === 'USER_NOT_FOUND') {
if (e.data.code === 'USER_NOT_FOUND') {
closeModal()
scrollToHash(ref)
}
}
},
[dispatch, role, closeModal, setAlert, ref]
[googleAuth, role, closeModal, setAlert, ref]
)

useEffect(() => {
Expand Down
9 changes: 4 additions & 5 deletions src/containers/guest-home-page/login-dialog/LoginDialog.jsx
Original file line number Diff line number Diff line change
@@ -1,36 +1,35 @@
import Box from '@mui/material/Box'
import Typography from '@mui/material/Typography'
import { useTranslation } from 'react-i18next'
import { useDispatch } from 'react-redux'

import GoogleLogin from '~/containers/guest-home-page/google-login/GoogleLogin'
import LoginForm from '~/containers/guest-home-page/login-form/LoginForm'
import useForm from '~/hooks/use-form'
import { useLoginMutation } from '~/services/auth-service'
import { useModalContext } from '~/context/modal-context'
import { useSnackBarContext } from '~/context/snackbar-context'
import { email } from '~/utils/validations/login'
import loginImg from '~/assets/img/login-dialog/login.svg'
import { login, snackbarVariants } from '~/constants'
import { loginUser } from '~/redux/reducer'

import styles from '~/containers/guest-home-page/login-dialog/LoginDialog.styles'

const LoginDialog = () => {
const { t } = useTranslation()
const { closeModal } = useModalContext()
const { setAlert } = useSnackBarContext()
const dispatch = useDispatch()
const [loginUser] = useLoginMutation()

const { handleSubmit, handleInputChange, handleBlur, data, errors } = useForm(
{
onSubmit: async () => {
try {
await dispatch(loginUser(data)).unwrap()
await loginUser(data).unwrap()
closeModal()
} catch (e) {
setAlert({
severity: snackbarVariants.error,
message: `errors.${e}`
message: `errors.${e.data.code}`
})
}
},
Expand Down
9 changes: 4 additions & 5 deletions src/containers/guest-home-page/signup-dialog/SignupDialog.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@ import { useEffect } from 'react'
import Box from '@mui/material/Box'
import Typography from '@mui/material/Typography'
import { useTranslation } from 'react-i18next'
import { useDispatch } from 'react-redux'

import useForm from '~/hooks/use-form'
import useConfirm from '~/hooks/use-confirm'
import { useSignUpMutation } from '~/services/auth-service'
import { useModalContext } from '~/context/modal-context'
import { useSnackBarContext } from '~/context/snackbar-context'

Expand All @@ -20,7 +20,6 @@ import { signup, snackbarVariants } from '~/constants'
import GoogleLogin from '~/containers/guest-home-page/google-login/GoogleLogin'
import SignupForm from '~/containers/guest-home-page/signup-form/SignupForm'
import NotificationModal from '~/containers/guest-home-page/notification-modal/NotificationModal'
import { signupUser } from '~/redux/reducer'

import student from '~/assets/img/signup-dialog/student.svg'
import tutor from '~/assets/img/signup-dialog/tutor.svg'
Expand All @@ -33,15 +32,15 @@ const SignupDialog = ({ type }) => {
const { setNeedConfirmation } = useConfirm()
const { openModal, closeModal } = useModalContext()
const { setAlert } = useSnackBarContext()
const dispatch = useDispatch()
const [signUp] = useSignUpMutation()

const signupImg = { student, tutor }

const { handleSubmit, handleInputChange, handleBlur, data, isDirty, errors } =
useForm({
onSubmit: async () => {
try {
await dispatch(signupUser({ ...data, role: type })).unwrap()
await signUp({ ...data, role: type }).unwrap()
openModal(
{
component: (
Expand All @@ -59,7 +58,7 @@ const SignupDialog = ({ type }) => {
} catch (e) {
setAlert({
severity: snackbarVariants.error,
message: `errors.${e}`
message: `errors.${e.data.code}`
})
}
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,10 @@ import Loader from '~/components/loader/Loader'
import AppButton from '~/components/app-button/AppButton'
import AddCategoriesModal from '~/containers/my-resources/add-categories-modal/AddCategoriesModal'
import AddResourceWithInput from '~/containers/my-resources/add-resource-with-input/AddResourceWithInput'
import { ResourceService } from '~/services/resource-service'
import {
ResourceService,
useUpdateResourceCategoryMutation
} from '~/services/resource-service'
import MyResourcesTable from '~/containers/my-resources/my-resources-table/MyResourcesTable'
import useAxios from '~/hooks/use-axios'
import useSort from '~/hooks/table/use-sort'
Expand All @@ -29,7 +32,6 @@ import {
GetResourcesCategoriesParams,
ErrorResponse,
ResourcesTabsEnum,
UpdateResourceCategory,
CreateCategoriesParams
} from '~/types'
import { ajustColumns, getScreenBasedLimit } from '~/utils/helper-functions'
Expand All @@ -45,6 +47,7 @@ const CategoriesContainer = () => {
const { openModal, closeModal } = useModalContext()
const { setAlert } = useSnackBarContext()
const [selectedItemId, setSelectedItemId] = useState<string>('')
const [updateResourceCategory] = useUpdateResourceCategoryMutation()

const { sort } = sortOptions
const itemsPerPage = getScreenBasedLimit(breakpoints, itemsLoadLimit)
Expand Down Expand Up @@ -90,12 +93,6 @@ const CategoriesContainer = () => {
[]
)

const updateCategory = useCallback(
(params?: UpdateResourceCategory) =>
ResourceService.updateResourceCategory(params),
[]
)

const deleteCategory = useCallback(
(id?: string) => ResourceService.deleteResourceCategory(id ?? ''),
[]
Expand Down Expand Up @@ -127,14 +124,6 @@ const CategoriesContainer = () => {
onResponse: onCategoryCreate
})

const { fetchData: updateData } = useAxios({
service: updateCategory,
defaultResponse: null,
onResponseError,
onResponse: onCategoryUpdate,
fetchOnMount: false
})

const onAdd = () => {
openModal({
component: (
Expand All @@ -146,7 +135,8 @@ const CategoriesContainer = () => {
})
}
const onSave = async (name: string) => {
if (name) await updateData({ id: selectedItemId, name })
if (name) await updateResourceCategory({ id: selectedItemId, name })
onCategoryUpdate()
setSelectedItemId('')
}
const onEdit = (id: string) => setSelectedItemId(id)
Expand Down
17 changes: 10 additions & 7 deletions src/pages/logout/Logout.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,21 @@
import { useEffect } from 'react'
import { useEffect, useCallback } from 'react'
import { useNavigate } from 'react-router-dom'
import { useAppDispatch } from '~/hooks/use-redux'

import { logoutUser } from '~/redux/reducer'
import { useLogoutMutation } from '~/services/auth-service'
import { guestRoutes } from '~/router/constants/guestRoutes'

const Logout = () => {
const dispatch = useAppDispatch()
const navigate = useNavigate()
const [logoutUser] = useLogoutMutation()

useEffect(() => {
void dispatch(logoutUser())
const onLogoutUser = useCallback(async () => {
await logoutUser()
navigate(guestRoutes.home.route)
}, [dispatch, navigate])
}, [logoutUser, navigate])

useEffect(() => {
void onLogoutUser()
}, [onLogoutUser])

return null
}
Expand Down
10 changes: 10 additions & 0 deletions src/redux/apiSlice.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react'

export const appApi = createApi({
baseQuery: fetchBaseQuery({
baseUrl: import.meta.env.VITE_API_BASE_PATH,
credentials: 'include'
}),
reducerPath: 'appApi',
endpoints: () => ({})
})
76 changes: 14 additions & 62 deletions src/redux/reducer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,9 @@ import {
isFulfilled,
isRejected
} from '@reduxjs/toolkit'
import { AuthService } from '~/services/auth-service'
import { AuthService, authService } from '~/services/auth-service'
import { AxiosError } from 'axios'
import {
AccessToken,
ErrorResponse,
GoogleAuthParams,
LoginParams,
SignupParams,
UserRole
} from '~/types'
import { AccessToken, ErrorResponse, UserRole } from '~/types'

interface UserState {
userId: string
Expand All @@ -37,57 +30,6 @@ const initialState: UserState = {
isFirstLogin: true
}

export const loginUser = createAsyncThunk(
'appMain/loginUser',
async (userData: LoginParams, { rejectWithValue, dispatch }) => {
try {
const { data } = await AuthService.login(userData)
dispatch(setUser(data.accessToken))
} catch (e) {
const error = e as AxiosError<ErrorResponse>
return rejectWithValue(error.response?.data.code)
}
}
)

export const googleAuth = createAsyncThunk(
'appMain/googleAuth',
async (userData: GoogleAuthParams, { rejectWithValue, dispatch }) => {
try {
const { data } = await AuthService.googleAuth(userData)
dispatch(setUser(data.accessToken))
} catch (e) {
const error = e as AxiosError<ErrorResponse>
return rejectWithValue(error.response?.data.code)
}
}
)

export const signupUser = createAsyncThunk(
'appMain/signupUser',
async (userData: SignupParams, { rejectWithValue }) => {
try {
await AuthService.signup(userData)
} catch (e) {
const error = e as AxiosError<ErrorResponse>
return rejectWithValue(error.response?.data.code)
}
}
)

export const logoutUser = createAsyncThunk(
'appMain/logoutUser',
async (_, { rejectWithValue, dispatch }) => {
try {
await AuthService.logout()
dispatch(logout())
} catch (e) {
const error = e as AxiosError<ErrorResponse>
return rejectWithValue(error.response?.data.code)
}
}
)

export const checkAuth = createAsyncThunk(
'appMain/checkAuth',
async (_, { rejectWithValue, dispatch }) => {
Expand Down Expand Up @@ -138,15 +80,25 @@ export const mainSlice = createSlice({
},
extraReducers: (builder) => {
builder.addMatcher(isPending, (state, action) => {
if (isAnyOf(checkAuth.pending, logoutUser.pending)(action)) {
if (
isAnyOf(
checkAuth.pending,
authService.endpoints.logout.matchPending
)(action)
) {
state.loading = true
} else {
state.authLoading = true
}
state.error = ''
})
builder.addMatcher(isFulfilled, (state, action) => {
if (isAnyOf(checkAuth.fulfilled, logoutUser.fulfilled)(action)) {
if (
isAnyOf(
checkAuth.fulfilled,
authService.endpoints.logout.matchFulfilled
)(action)
) {
state.loading = false
} else {
state.authLoading = false
Expand Down
12 changes: 10 additions & 2 deletions src/redux/store.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,21 @@
import { configureStore } from '@reduxjs/toolkit'
import { setupListeners } from '@reduxjs/toolkit/query/react'
import { ToolkitStore } from '@reduxjs/toolkit/dist/configureStore'

import { appApi } from '~/redux/apiSlice'
import appMainReducer from '~/redux/reducer'

export const store = configureStore({
reducer: {
appMain: appMainReducer
}
appMain: appMainReducer,
[appApi.reducerPath]: appApi.reducer
},
middleware: (getDefaultMiddleware) =>
getDefaultMiddleware().concat(appApi.middleware)
})

setupListeners(store.dispatch)

export type RootState = ReturnType<typeof store.getState>
export type AppDispatch = typeof store.dispatch
export interface Store extends ToolkitStore {
Expand Down
Loading

0 comments on commit e1fc2a7

Please sign in to comment.