mirror of
https://github.com/Paris-est-Ludique/intranet.git
synced 2025-09-11 22:06:29 +02:00
Factors redux tools to access the DB
This commit is contained in:
@@ -1,13 +1,7 @@
|
||||
import axios from "axios"
|
||||
|
||||
import mockStore from "../../utils/mockStore"
|
||||
import membre, {
|
||||
getRequesting,
|
||||
getSuccess,
|
||||
getFailure,
|
||||
fetchMembreData,
|
||||
initialState,
|
||||
} from "../membre"
|
||||
import membre, { getRequesting, getSuccess, getFailure, fetchMembre, initialState } from "../membre"
|
||||
|
||||
jest.mock("axios")
|
||||
|
||||
@@ -71,7 +65,7 @@ describe("membre action", () => {
|
||||
// @ts-expect-error
|
||||
axios.get.mockResolvedValue({ data: mockData })
|
||||
|
||||
await dispatch(fetchMembreData(id))
|
||||
await dispatch(fetchMembre(id))
|
||||
expect(getActions()).toEqual(expectedActions)
|
||||
})
|
||||
|
||||
@@ -85,7 +79,7 @@ describe("membre action", () => {
|
||||
// @ts-expect-error
|
||||
axios.get.mockRejectedValue({ message: mockError })
|
||||
|
||||
await dispatch(fetchMembreData(id))
|
||||
await dispatch(fetchMembre(id))
|
||||
expect(getActions()).toEqual(expectedActions)
|
||||
})
|
||||
})
|
||||
|
@@ -1,13 +1,9 @@
|
||||
import { PayloadAction, createSlice, createEntityAdapter } from "@reduxjs/toolkit"
|
||||
import { toast } from "react-toastify"
|
||||
|
||||
import { StateRequest } from "./utils"
|
||||
import { Envie, EnvieWithoutId, envieAdd } from "../services/envies"
|
||||
import { AppThunk } from "."
|
||||
import { StateRequest, toastError, toastSuccess, elementAddFetch } from "./utils"
|
||||
import { Envie, envieAdd } from "../services/envies"
|
||||
|
||||
const envieAdapter = createEntityAdapter<Envie>({
|
||||
selectId: (envie) => envie.id,
|
||||
})
|
||||
const envieAdapter = createEntityAdapter<Envie>()
|
||||
|
||||
const envieAddSlice = createSlice({
|
||||
name: "addEnvie",
|
||||
@@ -32,34 +28,11 @@ const envieAddSlice = createSlice({
|
||||
export default envieAddSlice.reducer
|
||||
export const { getRequesting, getSuccess, getFailure } = envieAddSlice.actions
|
||||
|
||||
export const sendAddEnvie =
|
||||
(envieWithoutId: EnvieWithoutId): AppThunk =>
|
||||
async (dispatch) => {
|
||||
dispatch(getRequesting())
|
||||
|
||||
const { error, data } = await envieAdd(envieWithoutId)
|
||||
|
||||
if (error) {
|
||||
dispatch(getFailure(error.message))
|
||||
toast.error(`Erreur lors de l'ajout d'une envie: ${error.message}`, {
|
||||
position: "top-center",
|
||||
autoClose: 6000,
|
||||
hideProgressBar: true,
|
||||
closeOnClick: true,
|
||||
pauseOnHover: true,
|
||||
draggable: true,
|
||||
progress: undefined,
|
||||
})
|
||||
} else {
|
||||
dispatch(getSuccess(data as Envie))
|
||||
toast.success("Envie ajoutée !", {
|
||||
position: "top-center",
|
||||
autoClose: 3000,
|
||||
hideProgressBar: true,
|
||||
closeOnClick: true,
|
||||
pauseOnHover: true,
|
||||
draggable: true,
|
||||
progress: undefined,
|
||||
})
|
||||
}
|
||||
}
|
||||
export const fetchEnvieAdd = elementAddFetch(
|
||||
envieAdd,
|
||||
getRequesting,
|
||||
getSuccess,
|
||||
getFailure,
|
||||
(error: Error) => toastError(`Erreur lors de l'ajout d'une envie: ${error.message}`),
|
||||
() => toastSuccess("Envie ajoutée !")
|
||||
)
|
||||
|
@@ -1,13 +1,10 @@
|
||||
import { PayloadAction, createSlice, createEntityAdapter } from "@reduxjs/toolkit"
|
||||
import { toast } from "react-toastify"
|
||||
|
||||
import { StateRequest } from "./utils"
|
||||
import { StateRequest, toastError, elementListFetch } from "./utils"
|
||||
import { Envie, envieListGet } from "../services/envies"
|
||||
import { AppThunk, AppState } from "."
|
||||
|
||||
const envieAdapter = createEntityAdapter<Envie>({
|
||||
selectId: (envie) => envie.id,
|
||||
})
|
||||
const envieAdapter = createEntityAdapter<Envie>()
|
||||
|
||||
const envieList = createSlice({
|
||||
name: "getEnvieList",
|
||||
@@ -32,26 +29,13 @@ const envieList = createSlice({
|
||||
export default envieList.reducer
|
||||
export const { getRequesting, getSuccess, getFailure } = envieList.actions
|
||||
|
||||
export const fetchEnvieList = (): AppThunk => async (dispatch) => {
|
||||
dispatch(getRequesting())
|
||||
|
||||
const { error, data } = await envieListGet()
|
||||
|
||||
if (error) {
|
||||
dispatch(getFailure(error.message))
|
||||
toast.error(`Erreur lors du chargement des envies: ${error.message}`, {
|
||||
position: "top-center",
|
||||
autoClose: 6000,
|
||||
hideProgressBar: true,
|
||||
closeOnClick: true,
|
||||
pauseOnHover: true,
|
||||
draggable: true,
|
||||
progress: undefined,
|
||||
})
|
||||
} else {
|
||||
dispatch(getSuccess(data as Envie[]))
|
||||
}
|
||||
}
|
||||
export const fetchEnvieList = elementListFetch(
|
||||
envieListGet,
|
||||
getRequesting,
|
||||
getSuccess,
|
||||
getFailure,
|
||||
(error: Error) => toastError(`Erreur lors du chargement des envies: ${error.message}`)
|
||||
)
|
||||
|
||||
const shouldFetchEnvieList = (state: AppState) => state.envieList.readyStatus !== "success"
|
||||
|
||||
|
@@ -1,13 +1,10 @@
|
||||
import { PayloadAction, createSlice, createEntityAdapter } from "@reduxjs/toolkit"
|
||||
import { toast } from "react-toastify"
|
||||
|
||||
import { StateRequest } from "./utils"
|
||||
import { JeuJav, getJeuJavList } from "../services/jeuJav"
|
||||
import { StateRequest, toastError, elementListFetch } from "./utils"
|
||||
import { JeuJav, jeuJavListGet } from "../services/jeuxJav"
|
||||
import { AppThunk, AppState } from "."
|
||||
|
||||
const jeuJavAdapter = createEntityAdapter<JeuJav>({
|
||||
selectId: (jeuJav) => jeuJav.id,
|
||||
})
|
||||
const jeuJavAdapter = createEntityAdapter<JeuJav>()
|
||||
|
||||
export const initialState = jeuJavAdapter.getInitialState({
|
||||
readyStatus: "idle",
|
||||
@@ -34,26 +31,13 @@ const jeuJavList = createSlice({
|
||||
export default jeuJavList.reducer
|
||||
export const { getRequesting, getSuccess, getFailure } = jeuJavList.actions
|
||||
|
||||
export const fetchJeuJavList = (): AppThunk => async (dispatch) => {
|
||||
dispatch(getRequesting())
|
||||
|
||||
const { error, data } = await getJeuJavList()
|
||||
|
||||
if (error) {
|
||||
dispatch(getFailure(error.message))
|
||||
toast.error(`Erreur lors du chargement des jeux JAV: ${error.message}`, {
|
||||
position: "top-center",
|
||||
autoClose: 6000,
|
||||
hideProgressBar: true,
|
||||
closeOnClick: true,
|
||||
pauseOnHover: true,
|
||||
draggable: true,
|
||||
progress: undefined,
|
||||
})
|
||||
} else {
|
||||
dispatch(getSuccess(data as JeuJav[]))
|
||||
}
|
||||
}
|
||||
export const fetchJeuJavList = elementListFetch(
|
||||
jeuJavListGet,
|
||||
getRequesting,
|
||||
getSuccess,
|
||||
getFailure,
|
||||
(error: Error) => toastError(`Erreur lors du chargement des jeux JAV: ${error.message}`)
|
||||
)
|
||||
|
||||
const shouldFetchJeuJavList = (state: AppState) => state.jeuJavList.readyStatus !== "success"
|
||||
|
||||
|
@@ -1,7 +1,6 @@
|
||||
import { PayloadAction, createSlice } from "@reduxjs/toolkit"
|
||||
import { toast } from "react-toastify"
|
||||
|
||||
import { StateRequest } from "./utils"
|
||||
import { StateRequest, toastError, elementFetch } from "./utils"
|
||||
import { Membre, membreGet } from "../services/membres"
|
||||
import { AppThunk, AppState } from "."
|
||||
|
||||
@@ -32,36 +31,21 @@ const membre = createSlice({
|
||||
export default membre.reducer
|
||||
export const { getRequesting, getSuccess, getFailure } = membre.actions
|
||||
|
||||
export const fetchMembreData =
|
||||
(id: number): AppThunk =>
|
||||
async (dispatch) => {
|
||||
dispatch(getRequesting())
|
||||
export const fetchMembre = elementFetch(
|
||||
membreGet,
|
||||
getRequesting,
|
||||
getSuccess,
|
||||
getFailure,
|
||||
(error: Error) => toastError(`Erreur lors du chargement d'un membre: ${error.message}`)
|
||||
)
|
||||
|
||||
const { error, data } = await membreGet(id)
|
||||
|
||||
if (error) {
|
||||
dispatch(getFailure(error.message))
|
||||
toast.error(`Erreur lors du chargement du membre ${id}: ${error.message}`, {
|
||||
position: "top-center",
|
||||
autoClose: 6000,
|
||||
hideProgressBar: true,
|
||||
closeOnClick: true,
|
||||
pauseOnHover: true,
|
||||
draggable: true,
|
||||
progress: undefined,
|
||||
})
|
||||
} else {
|
||||
dispatch(getSuccess(data as Membre))
|
||||
}
|
||||
}
|
||||
|
||||
const shouldFetchMembreData = (state: AppState, id: number) =>
|
||||
const shouldFetchMembre = (state: AppState, id: number) =>
|
||||
state.membre.readyStatus !== "success" || (state.membre.entity && state.membre.entity.id !== id)
|
||||
|
||||
export const fetchMembreDataIfNeed =
|
||||
export const fetchMembreIfNeed =
|
||||
(id: number): AppThunk =>
|
||||
(dispatch, getState) => {
|
||||
if (shouldFetchMembreData(getState(), id)) return dispatch(fetchMembreData(id))
|
||||
if (shouldFetchMembre(getState(), id)) return dispatch(fetchMembre(id))
|
||||
|
||||
return null
|
||||
}
|
||||
|
38
src/store/membreAdd.ts
Normal file
38
src/store/membreAdd.ts
Normal file
@@ -0,0 +1,38 @@
|
||||
import { PayloadAction, createSlice, createEntityAdapter } from "@reduxjs/toolkit"
|
||||
|
||||
import { StateRequest, toastError, toastSuccess, elementAddFetch } from "./utils"
|
||||
import { Membre, membreAdd } from "../services/membres"
|
||||
|
||||
const membreAdapter = createEntityAdapter<Membre>()
|
||||
|
||||
const membreAddSlice = createSlice({
|
||||
name: "addMembre",
|
||||
initialState: membreAdapter.getInitialState({
|
||||
readyStatus: "idle",
|
||||
} as StateRequest),
|
||||
reducers: {
|
||||
getRequesting: (state) => {
|
||||
state.readyStatus = "request"
|
||||
},
|
||||
getSuccess: (state, { payload }: PayloadAction<Membre>) => {
|
||||
state.readyStatus = "success"
|
||||
membreAdapter.addOne(state, payload)
|
||||
},
|
||||
getFailure: (state, { payload }: PayloadAction<string>) => {
|
||||
state.readyStatus = "failure"
|
||||
state.error = payload
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
export default membreAddSlice.reducer
|
||||
export const { getRequesting, getSuccess, getFailure } = membreAddSlice.actions
|
||||
|
||||
export const fetchMembreAdd = elementAddFetch(
|
||||
membreAdd,
|
||||
getRequesting,
|
||||
getSuccess,
|
||||
getFailure,
|
||||
(error: Error) => toastError(`Erreur lors de l'ajout d'une membre: ${error.message}`),
|
||||
() => toastSuccess("Membre ajoutée !")
|
||||
)
|
@@ -1,7 +1,6 @@
|
||||
import { PayloadAction, createSlice, createEntityAdapter } from "@reduxjs/toolkit"
|
||||
import { toast } from "react-toastify"
|
||||
|
||||
import { StateRequest } from "./utils"
|
||||
import { StateRequest, toastError, elementListFetch } from "./utils"
|
||||
import { Membre, membreListGet } from "../services/membres"
|
||||
import { AppThunk, AppState } from "."
|
||||
|
||||
@@ -32,26 +31,13 @@ const membreList = createSlice({
|
||||
export default membreList.reducer
|
||||
export const { getRequesting, getSuccess, getFailure } = membreList.actions
|
||||
|
||||
export const fetchMembreList = (): AppThunk => async (dispatch) => {
|
||||
dispatch(getRequesting())
|
||||
|
||||
const { error, data } = await membreListGet()
|
||||
|
||||
if (error) {
|
||||
dispatch(getFailure(error.message))
|
||||
toast.error(`Erreur lors du chargement des utilisateurs: ${error.message}`, {
|
||||
position: "top-center",
|
||||
autoClose: 6000,
|
||||
hideProgressBar: true,
|
||||
closeOnClick: true,
|
||||
pauseOnHover: true,
|
||||
draggable: true,
|
||||
progress: undefined,
|
||||
})
|
||||
} else {
|
||||
dispatch(getSuccess(data as Membre[]))
|
||||
}
|
||||
}
|
||||
export const fetchMembreList = elementListFetch(
|
||||
membreListGet,
|
||||
getRequesting,
|
||||
getSuccess,
|
||||
getFailure,
|
||||
(error: Error) => toastError(`Erreur lors du chargement des membres: ${error.message}`)
|
||||
)
|
||||
|
||||
const shouldFetchMembreList = (state: AppState) => state.membreList.readyStatus !== "success"
|
||||
|
||||
|
@@ -1,13 +1,9 @@
|
||||
import { PayloadAction, createSlice, createEntityAdapter } from "@reduxjs/toolkit"
|
||||
import { toast } from "react-toastify"
|
||||
|
||||
import { StateRequest } from "./utils"
|
||||
import { StateRequest, toastError, toastSuccess, elementSet } from "./utils"
|
||||
import { Membre, membreSet } from "../services/membres"
|
||||
import { AppThunk } from "."
|
||||
|
||||
const membreAdapter = createEntityAdapter<Membre>({
|
||||
selectId: (membre) => membre.id,
|
||||
})
|
||||
const membreAdapter = createEntityAdapter<Membre>()
|
||||
|
||||
const membreSetSlice = createSlice({
|
||||
name: "membreSet",
|
||||
@@ -20,7 +16,7 @@ const membreSetSlice = createSlice({
|
||||
},
|
||||
getSuccess: (state, { payload }: PayloadAction<Membre>) => {
|
||||
state.readyStatus = "success"
|
||||
membreAdapter.addOne(state, payload)
|
||||
membreAdapter.setOne(state, payload)
|
||||
},
|
||||
getFailure: (state, { payload }: PayloadAction<string>) => {
|
||||
state.readyStatus = "failure"
|
||||
@@ -32,34 +28,11 @@ const membreSetSlice = createSlice({
|
||||
export default membreSetSlice.reducer
|
||||
export const { getRequesting, getSuccess, getFailure } = membreSetSlice.actions
|
||||
|
||||
export const sendMembreSet =
|
||||
(membre: Membre): AppThunk =>
|
||||
async (dispatch) => {
|
||||
dispatch(getRequesting())
|
||||
|
||||
const { error, data } = await membreSet(membre)
|
||||
|
||||
if (error) {
|
||||
dispatch(getFailure(error.message))
|
||||
toast.error(`Erreur lors de la modification d'un membre: ${error.message}`, {
|
||||
position: "top-center",
|
||||
autoClose: 6000,
|
||||
hideProgressBar: true,
|
||||
closeOnClick: true,
|
||||
pauseOnHover: true,
|
||||
draggable: true,
|
||||
progress: undefined,
|
||||
})
|
||||
} else {
|
||||
dispatch(getSuccess(data as Membre))
|
||||
toast.success("Membre modifié !", {
|
||||
position: "top-center",
|
||||
autoClose: 3000,
|
||||
hideProgressBar: true,
|
||||
closeOnClick: true,
|
||||
pauseOnHover: true,
|
||||
draggable: true,
|
||||
progress: undefined,
|
||||
})
|
||||
}
|
||||
}
|
||||
export const fetchMembreSet = elementSet(
|
||||
membreSet,
|
||||
getRequesting,
|
||||
getSuccess,
|
||||
getFailure,
|
||||
(error: Error) => toastError(`Erreur lors de la modification d'un membre: ${error.message}`),
|
||||
() => toastSuccess("Membre modifié !")
|
||||
)
|
||||
|
@@ -1,18 +1,24 @@
|
||||
import { History } from "history"
|
||||
import { connectRouter } from "connected-react-router"
|
||||
|
||||
import membreList from "./membreList"
|
||||
import membre from "./membre"
|
||||
import jeuJavList from "./jeuJavList"
|
||||
import envieAdd from "./envieAdd"
|
||||
import envieList from "./envieList"
|
||||
import jeuJavList from "./jeuJavList"
|
||||
import membre from "./membre"
|
||||
import membreAdd from "./membreAdd"
|
||||
import membreList from "./membreList"
|
||||
import membreSet from "./membreSet"
|
||||
|
||||
// Use inferred return type for making correctly Redux types
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
|
||||
export default (history: History) => ({
|
||||
membreList,
|
||||
membre,
|
||||
jeuJavList,
|
||||
envieAdd,
|
||||
envieList,
|
||||
jeuJavList,
|
||||
membre,
|
||||
membreAdd,
|
||||
membreList,
|
||||
membreSet,
|
||||
router: connectRouter(history) as any,
|
||||
// Register more reducers...
|
||||
})
|
||||
|
@@ -1,4 +1,156 @@
|
||||
import { ActionCreatorWithoutPayload, ActionCreatorWithPayload } from "@reduxjs/toolkit"
|
||||
import { toast } from "react-toastify"
|
||||
|
||||
import { AppThunk } from "."
|
||||
|
||||
export interface StateRequest {
|
||||
readyStatus: "idle" | "request" | "success" | "failure"
|
||||
error?: string
|
||||
}
|
||||
|
||||
export function toastError(message: string): void {
|
||||
toast.error(message, {
|
||||
position: "top-center",
|
||||
autoClose: 6000,
|
||||
hideProgressBar: true,
|
||||
closeOnClick: true,
|
||||
pauseOnHover: true,
|
||||
draggable: true,
|
||||
progress: undefined,
|
||||
})
|
||||
}
|
||||
|
||||
export function toastSuccess(message: string): void {
|
||||
toast.success(message, {
|
||||
position: "top-center",
|
||||
autoClose: 3000,
|
||||
hideProgressBar: true,
|
||||
closeOnClick: true,
|
||||
pauseOnHover: true,
|
||||
draggable: true,
|
||||
progress: undefined,
|
||||
})
|
||||
}
|
||||
|
||||
export function elementFetch<Element>(
|
||||
elementService: (id: number) => Promise<{
|
||||
data?: Element | undefined
|
||||
error?: Error | undefined
|
||||
}>,
|
||||
getRequesting: ActionCreatorWithoutPayload<string>,
|
||||
getSuccess: ActionCreatorWithPayload<Element, string>,
|
||||
getFailure: ActionCreatorWithPayload<string, string>,
|
||||
errorMessage: (error: Error) => void = (_error) => {
|
||||
/* Meant to be empty */
|
||||
},
|
||||
successMessage: () => void = () => {
|
||||
/* Meant to be empty */
|
||||
}
|
||||
): (id: number) => AppThunk {
|
||||
return (id: number): AppThunk =>
|
||||
async (dispatch) => {
|
||||
dispatch(getRequesting())
|
||||
|
||||
const { error, data } = await elementService(id)
|
||||
|
||||
if (error) {
|
||||
dispatch(getFailure(error.message))
|
||||
errorMessage(error)
|
||||
} else {
|
||||
dispatch(getSuccess(data as Element))
|
||||
successMessage()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function elementAddFetch<Element>(
|
||||
elementAddService: (membreWithoutId: Omit<Element, "id">) => Promise<{
|
||||
data?: Element | undefined
|
||||
error?: Error | undefined
|
||||
}>,
|
||||
getRequesting: ActionCreatorWithoutPayload<string>,
|
||||
getSuccess: ActionCreatorWithPayload<Element, string>,
|
||||
getFailure: ActionCreatorWithPayload<string, string>,
|
||||
errorMessage: (error: Error) => void = (_error) => {
|
||||
/* Meant to be empty */
|
||||
},
|
||||
successMessage: () => void = () => {
|
||||
/* Meant to be empty */
|
||||
}
|
||||
): (membreWithoutId: Omit<Element, "id">) => AppThunk {
|
||||
return (membreWithoutId: Omit<Element, "id">): AppThunk =>
|
||||
async (dispatch) => {
|
||||
dispatch(getRequesting())
|
||||
|
||||
const { error, data } = await elementAddService(membreWithoutId)
|
||||
|
||||
if (error) {
|
||||
dispatch(getFailure(error.message))
|
||||
errorMessage(error)
|
||||
} else {
|
||||
dispatch(getSuccess(data as Element))
|
||||
successMessage()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function elementListFetch<Element>(
|
||||
elementListService: () => Promise<{
|
||||
data?: Element[] | undefined
|
||||
error?: Error | undefined
|
||||
}>,
|
||||
getRequesting: ActionCreatorWithoutPayload<string>,
|
||||
getSuccess: ActionCreatorWithPayload<Element[], string>,
|
||||
getFailure: ActionCreatorWithPayload<string, string>,
|
||||
errorMessage: (error: Error) => void = (_error) => {
|
||||
/* Meant to be empty */
|
||||
},
|
||||
successMessage: () => void = () => {
|
||||
/* Meant to be empty */
|
||||
}
|
||||
): () => AppThunk {
|
||||
return (): AppThunk => async (dispatch) => {
|
||||
dispatch(getRequesting())
|
||||
|
||||
const { error, data } = await elementListService()
|
||||
|
||||
if (error) {
|
||||
dispatch(getFailure(error.message))
|
||||
errorMessage(error)
|
||||
} else {
|
||||
dispatch(getSuccess(data as Element[]))
|
||||
successMessage()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function elementSet<Element>(
|
||||
elementSetService: (membre: Element) => Promise<{
|
||||
data?: Element | undefined
|
||||
error?: Error | undefined
|
||||
}>,
|
||||
getRequesting: ActionCreatorWithoutPayload<string>,
|
||||
getSuccess: ActionCreatorWithPayload<Element, string>,
|
||||
getFailure: ActionCreatorWithPayload<string, string>,
|
||||
errorMessage: (error: Error) => void = (_error) => {
|
||||
/* Meant to be empty */
|
||||
},
|
||||
successMessage: () => void = () => {
|
||||
/* Meant to be empty */
|
||||
}
|
||||
): (element: Element) => AppThunk {
|
||||
return (element: Element): AppThunk =>
|
||||
async (dispatch) => {
|
||||
dispatch(getRequesting())
|
||||
|
||||
const { error, data } = await elementSetService(element)
|
||||
|
||||
if (error) {
|
||||
dispatch(getFailure(error.message))
|
||||
errorMessage(error)
|
||||
} else {
|
||||
dispatch(getSuccess(data as Element))
|
||||
successMessage()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user