mirror of
https://github.com/Paris-est-Ludique/intranet.git
synced 2025-09-11 22:06:29 +02:00
Adds createEntityAdapter
This commit is contained in:
@@ -1,19 +1,19 @@
|
||||
import axios from "axios"
|
||||
|
||||
import mockStore from "../../utils/mockStore"
|
||||
import JeuxJavList, {
|
||||
import JeuJavList, {
|
||||
initialState,
|
||||
getRequesting,
|
||||
getSuccess,
|
||||
getFailure,
|
||||
fetchJeuxJavList,
|
||||
} from "../jeuxJavList"
|
||||
fetchJeuJavList,
|
||||
} from "../jeuJavList"
|
||||
|
||||
jest.mock("axios")
|
||||
|
||||
const mockData = [
|
||||
{
|
||||
id: 5,
|
||||
const mockData = {
|
||||
"5": {
|
||||
jeuId: 5,
|
||||
titre: "6 qui prend!",
|
||||
auteur: "Wolfgang Kramer",
|
||||
editeur: "(uncredited) , Design Edge , B",
|
||||
@@ -31,33 +31,34 @@ const mockData = [
|
||||
horodatage: "0000-00-00",
|
||||
ean: "3421272101313",
|
||||
},
|
||||
]
|
||||
}
|
||||
const mockError = "Oops! Something went wrong."
|
||||
|
||||
describe("JeuxJavList reducer", () => {
|
||||
describe("JeuJavList reducer", () => {
|
||||
it("should handle initial state", () => {
|
||||
// @ts-expect-error
|
||||
expect(JeuxJavList(undefined, {})).toEqual(initialState)
|
||||
expect(JeuJavList(undefined, {})).toEqual(initialState)
|
||||
})
|
||||
|
||||
it("should handle requesting correctly", () => {
|
||||
expect(JeuxJavList(undefined, { type: getRequesting.type })).toEqual({
|
||||
expect(JeuJavList(undefined, { type: getRequesting.type })).toEqual({
|
||||
readyStatus: "request",
|
||||
items: [],
|
||||
error: null,
|
||||
ids: [],
|
||||
entities: {},
|
||||
})
|
||||
})
|
||||
|
||||
it("should handle success correctly", () => {
|
||||
expect(JeuxJavList(undefined, { type: getSuccess.type, payload: mockData })).toEqual({
|
||||
expect(JeuJavList(undefined, { type: getSuccess.type, payload: mockData })).toEqual({
|
||||
...initialState,
|
||||
readyStatus: "success",
|
||||
items: mockData,
|
||||
ids: [5],
|
||||
entities: mockData,
|
||||
})
|
||||
})
|
||||
|
||||
it("should handle failure correctly", () => {
|
||||
expect(JeuxJavList(undefined, { type: getFailure.type, payload: mockError })).toEqual({
|
||||
expect(JeuJavList(undefined, { type: getFailure.type, payload: mockError })).toEqual({
|
||||
...initialState,
|
||||
readyStatus: "failure",
|
||||
error: mockError,
|
||||
@@ -65,8 +66,8 @@ describe("JeuxJavList reducer", () => {
|
||||
})
|
||||
})
|
||||
|
||||
describe("JeuxJavList action", () => {
|
||||
it("fetches JeuxJav list successful", async () => {
|
||||
describe("JeuJavList action", () => {
|
||||
it("fetches JeuJav list successful", async () => {
|
||||
const { dispatch, getActions } = mockStore()
|
||||
const expectedActions = [
|
||||
{ type: getRequesting.type },
|
||||
@@ -76,11 +77,11 @@ describe("JeuxJavList action", () => {
|
||||
// @ts-expect-error
|
||||
axios.get.mockResolvedValue({ data: mockData })
|
||||
|
||||
await dispatch(fetchJeuxJavList())
|
||||
await dispatch(fetchJeuJavList())
|
||||
expect(getActions()).toEqual(expectedActions)
|
||||
})
|
||||
|
||||
it("fetches JeuxJav list failed", async () => {
|
||||
it("fetches JeuJav list failed", async () => {
|
||||
const { dispatch, getActions } = mockStore()
|
||||
const expectedActions = [
|
||||
{ type: getRequesting.type },
|
||||
@@ -90,7 +91,7 @@ describe("JeuxJavList action", () => {
|
||||
// @ts-expect-error
|
||||
axios.get.mockRejectedValue({ message: mockError })
|
||||
|
||||
await dispatch(fetchJeuxJavList())
|
||||
await dispatch(fetchJeuJavList())
|
||||
expect(getActions()).toEqual(expectedActions)
|
||||
})
|
||||
})
|
@@ -1,29 +1,35 @@
|
||||
import axios from "axios"
|
||||
|
||||
import mockStore from "../../utils/mockStore"
|
||||
import userData, { getRequesting, getSuccess, getFailure, fetchUserData } from "../userData"
|
||||
import userData, {
|
||||
getRequesting,
|
||||
getSuccess,
|
||||
getFailure,
|
||||
fetchUserData,
|
||||
initialState,
|
||||
} from "../userData"
|
||||
|
||||
jest.mock("axios")
|
||||
|
||||
const mockData = {
|
||||
id: 1,
|
||||
membreId: 1,
|
||||
name: "PeL",
|
||||
phone: "+886 0970...",
|
||||
email: "forceoranj@gmail.com",
|
||||
website: "https://www.parisestludique.fr",
|
||||
}
|
||||
const { id } = mockData
|
||||
const { membreId } = mockData
|
||||
const mockError = "Oops! Something went wrong."
|
||||
|
||||
describe("userData reducer", () => {
|
||||
it("should handle initial state correctly", () => {
|
||||
// @ts-expect-error
|
||||
expect(userData(undefined, {})).toEqual({})
|
||||
expect(userData(undefined, {})).toEqual(initialState)
|
||||
})
|
||||
|
||||
it("should handle requesting correctly", () => {
|
||||
expect(userData(undefined, { type: getRequesting.type, payload: id })).toEqual({
|
||||
[id]: { readyStatus: "request" },
|
||||
expect(userData(undefined, { type: getRequesting.type, payload: membreId })).toEqual({
|
||||
readyStatus: "request",
|
||||
})
|
||||
})
|
||||
|
||||
@@ -31,53 +37,47 @@ describe("userData reducer", () => {
|
||||
expect(
|
||||
userData(undefined, {
|
||||
type: getSuccess.type,
|
||||
payload: { id, item: mockData },
|
||||
payload: mockData,
|
||||
})
|
||||
).toEqual({
|
||||
[id]: { readyStatus: "success", item: mockData },
|
||||
})
|
||||
).toEqual({ readyStatus: "success", entity: mockData })
|
||||
})
|
||||
|
||||
it("should handle failure correctly", () => {
|
||||
expect(
|
||||
userData(undefined, {
|
||||
type: getFailure.type,
|
||||
payload: { id, error: mockError },
|
||||
payload: mockError,
|
||||
})
|
||||
).toEqual({
|
||||
[id]: { readyStatus: "failure", error: mockError },
|
||||
})
|
||||
).toEqual({ readyStatus: "failure", error: mockError })
|
||||
})
|
||||
})
|
||||
|
||||
describe("userData action", () => {
|
||||
const strId = id.toString()
|
||||
|
||||
it("fetches user data successful", async () => {
|
||||
const { dispatch, getActions } = mockStore()
|
||||
const expectedActions = [
|
||||
{ type: getRequesting.type, payload: strId },
|
||||
{ type: getSuccess.type, payload: { id: strId, item: mockData } },
|
||||
{ type: getRequesting.type },
|
||||
{ type: getSuccess.type, payload: mockData },
|
||||
]
|
||||
|
||||
// @ts-expect-error
|
||||
axios.get.mockResolvedValue({ data: mockData })
|
||||
|
||||
await dispatch(fetchUserData(strId))
|
||||
await dispatch(fetchUserData(membreId))
|
||||
expect(getActions()).toEqual(expectedActions)
|
||||
})
|
||||
|
||||
it("fetches user data failed", async () => {
|
||||
const { dispatch, getActions } = mockStore()
|
||||
const expectedActions = [
|
||||
{ type: getRequesting.type, payload: strId },
|
||||
{ type: getFailure.type, payload: { id: strId, error: mockError } },
|
||||
{ type: getRequesting.type },
|
||||
{ type: getFailure.type, payload: mockError },
|
||||
]
|
||||
|
||||
// @ts-expect-error
|
||||
axios.get.mockRejectedValue({ message: mockError })
|
||||
|
||||
await dispatch(fetchUserData(strId))
|
||||
await dispatch(fetchUserData(membreId))
|
||||
expect(getActions()).toEqual(expectedActions)
|
||||
})
|
||||
})
|
||||
|
@@ -11,15 +11,15 @@ import userList, {
|
||||
|
||||
jest.mock("axios")
|
||||
|
||||
const mockData = [
|
||||
{
|
||||
id: 1,
|
||||
const mockData = {
|
||||
"1": {
|
||||
membreId: 1,
|
||||
name: "PeL",
|
||||
phone: "+886 0970...",
|
||||
email: "forceoranj@gmail.com",
|
||||
website: "https://www.parisestludique.fr",
|
||||
},
|
||||
]
|
||||
}
|
||||
const mockError = "Oops! Something went wrong."
|
||||
|
||||
describe("userList reducer", () => {
|
||||
@@ -31,8 +31,8 @@ describe("userList reducer", () => {
|
||||
it("should handle requesting correctly", () => {
|
||||
expect(userList(undefined, { type: getRequesting.type })).toEqual({
|
||||
readyStatus: "request",
|
||||
items: [],
|
||||
error: null,
|
||||
ids: [],
|
||||
entities: {},
|
||||
})
|
||||
})
|
||||
|
||||
@@ -40,7 +40,8 @@ describe("userList reducer", () => {
|
||||
expect(userList(undefined, { type: getSuccess.type, payload: mockData })).toEqual({
|
||||
...initialState,
|
||||
readyStatus: "success",
|
||||
items: mockData,
|
||||
ids: [1],
|
||||
entities: mockData,
|
||||
})
|
||||
})
|
||||
|
||||
|
@@ -1,31 +1,26 @@
|
||||
import { PayloadAction, createSlice } from "@reduxjs/toolkit"
|
||||
import { PayloadAction, createSlice, createEntityAdapter } from "@reduxjs/toolkit"
|
||||
import { toast } from "react-toastify"
|
||||
|
||||
import { StateRequest } from "./utils"
|
||||
import { Envie, EnvieWithoutId, addEnvie } from "../services/envies"
|
||||
import { AppThunk } from "."
|
||||
|
||||
interface EnvieRequest {
|
||||
readyStatus: string
|
||||
items: Envie | null
|
||||
error: string | null
|
||||
}
|
||||
const envieAdapter = createEntityAdapter<Envie>({
|
||||
selectId: (envie) => envie.envieId,
|
||||
})
|
||||
|
||||
export const initialState: EnvieRequest = {
|
||||
readyStatus: "invalid",
|
||||
items: null,
|
||||
error: null,
|
||||
}
|
||||
|
||||
const envieList = createSlice({
|
||||
const envieAdd = createSlice({
|
||||
name: "addEnvie",
|
||||
initialState,
|
||||
initialState: envieAdapter.getInitialState({
|
||||
readyStatus: "idle",
|
||||
} as StateRequest),
|
||||
reducers: {
|
||||
getRequesting: (state: EnvieRequest) => {
|
||||
getRequesting: (state) => {
|
||||
state.readyStatus = "request"
|
||||
},
|
||||
getSuccess: (state, { payload }: PayloadAction<Envie>) => {
|
||||
state.readyStatus = "success"
|
||||
state.items = payload
|
||||
envieAdapter.addOne(state, payload)
|
||||
},
|
||||
getFailure: (state, { payload }: PayloadAction<string>) => {
|
||||
state.readyStatus = "failure"
|
||||
@@ -34,8 +29,8 @@ const envieList = createSlice({
|
||||
},
|
||||
})
|
||||
|
||||
export default envieList.reducer
|
||||
export const { getRequesting, getSuccess, getFailure } = envieList.actions
|
||||
export default envieAdd.reducer
|
||||
export const { getRequesting, getSuccess, getFailure } = envieAdd.actions
|
||||
|
||||
export const postEnvie =
|
||||
(envieWithoutId: EnvieWithoutId): AppThunk =>
|
||||
@@ -46,7 +41,7 @@ export const postEnvie =
|
||||
|
||||
if (error) {
|
||||
dispatch(getFailure(error.message))
|
||||
toast.error(`Erreur lors de l'ajout: ${error.message}`, {
|
||||
toast.error(`Erreur lors de l'ajout d'une envie: ${error.message}`, {
|
||||
position: "top-center",
|
||||
autoClose: 6000,
|
||||
hideProgressBar: true,
|
||||
|
@@ -1,30 +1,26 @@
|
||||
import { PayloadAction, createSlice } from "@reduxjs/toolkit"
|
||||
import { PayloadAction, createSlice, createEntityAdapter } from "@reduxjs/toolkit"
|
||||
import { toast } from "react-toastify"
|
||||
|
||||
import { StateRequest } from "./utils"
|
||||
import { Envie, getEnvieList } from "../services/envies"
|
||||
import { AppThunk, AppState } from "."
|
||||
|
||||
interface EnvieListRequest {
|
||||
readyStatus: string
|
||||
items: Envie[]
|
||||
error: string | null
|
||||
}
|
||||
|
||||
export const initialState: EnvieListRequest = {
|
||||
readyStatus: "invalid",
|
||||
items: [],
|
||||
error: null,
|
||||
}
|
||||
const envieAdapter = createEntityAdapter<Envie>({
|
||||
selectId: (envie) => envie.envieId,
|
||||
})
|
||||
|
||||
const envieList = createSlice({
|
||||
name: "getEnvieList",
|
||||
initialState,
|
||||
initialState: envieAdapter.getInitialState({
|
||||
readyStatus: "idle",
|
||||
} as StateRequest),
|
||||
reducers: {
|
||||
getRequesting: (state: EnvieListRequest) => {
|
||||
getRequesting: (state) => {
|
||||
state.readyStatus = "request"
|
||||
},
|
||||
getSuccess: (state, { payload }: PayloadAction<Envie[]>) => {
|
||||
state.readyStatus = "success"
|
||||
state.items = payload
|
||||
envieAdapter.setAll(state, payload)
|
||||
},
|
||||
getFailure: (state, { payload }: PayloadAction<string>) => {
|
||||
state.readyStatus = "failure"
|
||||
@@ -43,6 +39,15 @@ export const fetchEnvieList = (): AppThunk => async (dispatch) => {
|
||||
|
||||
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[]))
|
||||
}
|
||||
|
@@ -1,9 +1,10 @@
|
||||
import { createMemoryHistory, createBrowserHistory } from "history"
|
||||
import { Action, configureStore } from "@reduxjs/toolkit"
|
||||
import { Action, configureStore, EntityState } from "@reduxjs/toolkit"
|
||||
import { ThunkAction } from "redux-thunk"
|
||||
import { routerMiddleware } from "connected-react-router"
|
||||
|
||||
import createRootReducer from "./rootReducer"
|
||||
import { StateRequest } from "./utils"
|
||||
|
||||
interface Arg {
|
||||
initialState?: typeof window.__INITIAL_STATE__
|
||||
@@ -38,4 +39,6 @@ export type AppDispatch = typeof store.dispatch
|
||||
|
||||
export type AppThunk = ThunkAction<void, AppState, unknown, Action<string>>
|
||||
|
||||
export type EntitiesRequest<T> = EntityState<T> & StateRequest
|
||||
|
||||
export default createStore
|
||||
|
64
src/store/jeuJavList.ts
Normal file
64
src/store/jeuJavList.ts
Normal file
@@ -0,0 +1,64 @@
|
||||
import { PayloadAction, createSlice, createEntityAdapter } from "@reduxjs/toolkit"
|
||||
import { toast } from "react-toastify"
|
||||
|
||||
import { StateRequest } from "./utils"
|
||||
import { JeuJav, getJeuJavList } from "../services/jeuJav"
|
||||
import { AppThunk, AppState } from "."
|
||||
|
||||
const jeuJavAdapter = createEntityAdapter<JeuJav>({
|
||||
selectId: (jeuJav) => jeuJav.jeuId,
|
||||
})
|
||||
|
||||
export const initialState = jeuJavAdapter.getInitialState({
|
||||
readyStatus: "idle",
|
||||
} as StateRequest)
|
||||
|
||||
const jeuJavList = createSlice({
|
||||
name: "jeuJavList",
|
||||
initialState,
|
||||
reducers: {
|
||||
getRequesting: (state) => {
|
||||
state.readyStatus = "request"
|
||||
},
|
||||
getSuccess: (state, { payload }: PayloadAction<JeuJav[]>) => {
|
||||
state.readyStatus = "success"
|
||||
jeuJavAdapter.setAll(state, payload)
|
||||
},
|
||||
getFailure: (state, { payload }: PayloadAction<string>) => {
|
||||
state.readyStatus = "failure"
|
||||
state.error = payload
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
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[]))
|
||||
}
|
||||
}
|
||||
|
||||
const shouldFetchJeuJavList = (state: AppState) => state.jeuJavList.readyStatus !== "success"
|
||||
|
||||
export const fetchJeuJavListIfNeed = (): AppThunk => (dispatch, getState) => {
|
||||
if (shouldFetchJeuJavList(getState())) return dispatch(fetchJeuJavList())
|
||||
|
||||
return null
|
||||
}
|
@@ -1,57 +0,0 @@
|
||||
import { PayloadAction, createSlice } from "@reduxjs/toolkit"
|
||||
|
||||
import { JeuxJav, getJeuxJavList } from "../services/jeuxJav"
|
||||
import { AppThunk, AppState } from "."
|
||||
|
||||
interface JeuxJavList {
|
||||
readyStatus: string // TODO Change it to: "invalid" | "request" | "success" | "failure"
|
||||
items: JeuxJav[]
|
||||
error: string | null
|
||||
}
|
||||
|
||||
export const initialState: JeuxJavList = {
|
||||
readyStatus: "invalid",
|
||||
items: [],
|
||||
error: null,
|
||||
}
|
||||
|
||||
const jeuxJavList = createSlice({
|
||||
name: "jeuxJavList",
|
||||
initialState,
|
||||
reducers: {
|
||||
getRequesting: (state: JeuxJavList) => {
|
||||
state.readyStatus = "request"
|
||||
},
|
||||
getSuccess: (state, { payload }: PayloadAction<JeuxJav[]>) => {
|
||||
state.readyStatus = "success"
|
||||
state.items = payload
|
||||
},
|
||||
getFailure: (state, { payload }: PayloadAction<string>) => {
|
||||
state.readyStatus = "failure"
|
||||
state.error = payload
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
export default jeuxJavList.reducer
|
||||
export const { getRequesting, getSuccess, getFailure } = jeuxJavList.actions
|
||||
|
||||
export const fetchJeuxJavList = (): AppThunk => async (dispatch) => {
|
||||
dispatch(getRequesting())
|
||||
|
||||
const { error, data } = await getJeuxJavList()
|
||||
|
||||
if (error) {
|
||||
dispatch(getFailure(error.message))
|
||||
} else {
|
||||
dispatch(getSuccess(data as JeuxJav[]))
|
||||
}
|
||||
}
|
||||
|
||||
const shouldFetchJeuxJavList = (state: AppState) => state.jeuxJavList.readyStatus !== "success"
|
||||
|
||||
export const fetchJeuxJavListIfNeed = (): AppThunk => (dispatch, getState) => {
|
||||
if (shouldFetchJeuxJavList(getState())) return dispatch(fetchJeuxJavList())
|
||||
|
||||
return null
|
||||
}
|
@@ -3,7 +3,7 @@ import { connectRouter } from "connected-react-router"
|
||||
|
||||
import userList from "./userList"
|
||||
import userData from "./userData"
|
||||
import jeuxJavList from "./jeuxJavList"
|
||||
import jeuJavList from "./jeuJavList"
|
||||
import envieList from "./envieList"
|
||||
|
||||
// Use inferred return type for making correctly Redux types
|
||||
@@ -11,7 +11,7 @@ import envieList from "./envieList"
|
||||
export default (history: History) => ({
|
||||
userList,
|
||||
userData,
|
||||
jeuxJavList,
|
||||
jeuJavList,
|
||||
envieList,
|
||||
router: connectRouter(history) as any,
|
||||
// Register more reducers...
|
||||
|
@@ -1,39 +1,31 @@
|
||||
import { PayloadAction, createSlice } from "@reduxjs/toolkit"
|
||||
import { toast } from "react-toastify"
|
||||
|
||||
import { StateRequest } from "./utils"
|
||||
import { User, getUserData } from "../services/jsonPlaceholder"
|
||||
import { AppThunk, AppState } from "."
|
||||
|
||||
interface UserDate {
|
||||
[id: string]: {
|
||||
readyStatus: string
|
||||
item?: User
|
||||
error?: string
|
||||
}
|
||||
}
|
||||
type StateUser = { entity?: User } & StateRequest
|
||||
|
||||
interface Success {
|
||||
id: string
|
||||
item: User
|
||||
}
|
||||
|
||||
interface Failure {
|
||||
id: string
|
||||
error: string
|
||||
export const initialState: StateUser = {
|
||||
readyStatus: "idle",
|
||||
}
|
||||
|
||||
const userData = createSlice({
|
||||
name: "userData",
|
||||
initialState: {} as UserDate,
|
||||
initialState,
|
||||
reducers: {
|
||||
getRequesting: (state, { payload }: PayloadAction<string>) => {
|
||||
state[payload] = { readyStatus: "request" }
|
||||
},
|
||||
getSuccess: (state, { payload }: PayloadAction<Success>) => {
|
||||
state[payload.id] = { readyStatus: "success", item: payload.item }
|
||||
},
|
||||
getFailure: (state, { payload }: PayloadAction<Failure>) => {
|
||||
state[payload.id] = { readyStatus: "failure", error: payload.error }
|
||||
},
|
||||
getRequesting: (_) => ({
|
||||
readyStatus: "request",
|
||||
}),
|
||||
getSuccess: (_, { payload }: PayloadAction<User>) => ({
|
||||
readyStatus: "success",
|
||||
entity: payload,
|
||||
}),
|
||||
getFailure: (_, { payload }: PayloadAction<string>) => ({
|
||||
readyStatus: "failure",
|
||||
error: payload,
|
||||
}),
|
||||
},
|
||||
})
|
||||
|
||||
@@ -41,24 +33,34 @@ export default userData.reducer
|
||||
export const { getRequesting, getSuccess, getFailure } = userData.actions
|
||||
|
||||
export const fetchUserData =
|
||||
(id: string): AppThunk =>
|
||||
(id: number): AppThunk =>
|
||||
async (dispatch) => {
|
||||
dispatch(getRequesting(id))
|
||||
dispatch(getRequesting())
|
||||
|
||||
const { error, data } = await getUserData(id)
|
||||
|
||||
if (error) {
|
||||
dispatch(getFailure({ id, error: error.message }))
|
||||
dispatch(getFailure(error.message))
|
||||
toast.error(`Erreur lors du chargement de l'utilisateur ${id}: ${error.message}`, {
|
||||
position: "top-center",
|
||||
autoClose: 6000,
|
||||
hideProgressBar: true,
|
||||
closeOnClick: true,
|
||||
pauseOnHover: true,
|
||||
draggable: true,
|
||||
progress: undefined,
|
||||
})
|
||||
} else {
|
||||
dispatch(getSuccess({ id, item: data as User }))
|
||||
dispatch(getSuccess(data as User))
|
||||
}
|
||||
}
|
||||
|
||||
const shouldFetchUserData = (state: AppState, id: string) =>
|
||||
state.userData[id]?.readyStatus !== "success"
|
||||
const shouldFetchUserData = (state: AppState, id: number) =>
|
||||
state.userData.readyStatus !== "success" ||
|
||||
(state.userData.entity && state.userData.entity.membreId !== id)
|
||||
|
||||
export const fetchUserDataIfNeed =
|
||||
(id: string): AppThunk =>
|
||||
(id: number): AppThunk =>
|
||||
(dispatch, getState) => {
|
||||
if (shouldFetchUserData(getState(), id)) return dispatch(fetchUserData(id))
|
||||
|
||||
|
@@ -1,30 +1,28 @@
|
||||
import { PayloadAction, createSlice } from "@reduxjs/toolkit"
|
||||
import { PayloadAction, createSlice, createEntityAdapter } from "@reduxjs/toolkit"
|
||||
import { toast } from "react-toastify"
|
||||
|
||||
import { StateRequest } from "./utils"
|
||||
import { User, getUserList } from "../services/jsonPlaceholder"
|
||||
import { AppThunk, AppState } from "."
|
||||
|
||||
interface UserList {
|
||||
readyStatus: string
|
||||
items: User[]
|
||||
error: string | null
|
||||
}
|
||||
const userAdapter = createEntityAdapter<User>({
|
||||
selectId: (user) => user.membreId,
|
||||
})
|
||||
|
||||
export const initialState: UserList = {
|
||||
readyStatus: "invalid",
|
||||
items: [],
|
||||
error: null,
|
||||
}
|
||||
export const initialState = userAdapter.getInitialState({
|
||||
readyStatus: "idle",
|
||||
} as StateRequest)
|
||||
|
||||
const userList = createSlice({
|
||||
name: "userList",
|
||||
initialState,
|
||||
reducers: {
|
||||
getRequesting: (state: UserList) => {
|
||||
getRequesting: (state) => {
|
||||
state.readyStatus = "request"
|
||||
},
|
||||
getSuccess: (state, { payload }: PayloadAction<User[]>) => {
|
||||
state.readyStatus = "success"
|
||||
state.items = payload
|
||||
userAdapter.setAll(state, payload)
|
||||
},
|
||||
getFailure: (state, { payload }: PayloadAction<string>) => {
|
||||
state.readyStatus = "failure"
|
||||
@@ -43,6 +41,15 @@ export const fetchUserList = (): AppThunk => async (dispatch) => {
|
||||
|
||||
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 User[]))
|
||||
}
|
||||
|
4
src/store/utils.ts
Normal file
4
src/store/utils.ts
Normal file
@@ -0,0 +1,4 @@
|
||||
export interface StateRequest {
|
||||
readyStatus: "idle" | "request" | "success" | "failure"
|
||||
error?: string
|
||||
}
|
Reference in New Issue
Block a user