Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rewrited auth mutation endpoints using RTK Query #1422

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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