mirror of
https://github.com/Paris-est-Ludique/intranet.git
synced 2025-09-11 22:06:29 +02:00
Add notifications to home page
This commit is contained in:
@@ -8,25 +8,11 @@ import volunteer, {
|
||||
fetchVolunteer,
|
||||
initialState,
|
||||
} from "../volunteer"
|
||||
import { Volunteer } from "../../services/volunteers"
|
||||
import { Volunteer, volunteerExample } from "../../services/volunteers"
|
||||
|
||||
jest.mock("axios")
|
||||
|
||||
const mockData: Volunteer = {
|
||||
id: 1,
|
||||
lastname: "Aupeix",
|
||||
firstname: "Amélie",
|
||||
email: "pakouille.lakouille@yahoo.fr",
|
||||
mobile: "0675650392",
|
||||
photo: "images/volunteers/$taille/amélie_aupeix.jpg",
|
||||
food: "Végétarien",
|
||||
adult: 1,
|
||||
privileges: 0,
|
||||
active: 0,
|
||||
created: new Date(0),
|
||||
password1: "$2y$10$fSxY9AIuxSiEjwF.J3eXGubIxUPlobkyRrNIal8ASimSjNj4SR.9O",
|
||||
password2: "$2y$10$fSxY9AIuxSiEjwF.J3eXGubIxUPlobkyRrNIal8ASimSjNj4SR.9O",
|
||||
}
|
||||
const mockData: Volunteer = volunteerExample
|
||||
const { id } = mockData
|
||||
const mockError = "Oops! Something went wrong."
|
||||
|
||||
|
@@ -9,27 +9,11 @@ import volunteerList, {
|
||||
getFailure,
|
||||
fetchVolunteerList,
|
||||
} from "../volunteerList"
|
||||
import { Volunteer } from "../../services/volunteers"
|
||||
import { Volunteer, volunteerExample } from "../../services/volunteers"
|
||||
|
||||
jest.mock("axios")
|
||||
|
||||
const mockData: Volunteer[] = [
|
||||
{
|
||||
id: 1,
|
||||
lastname: "Aupeix",
|
||||
firstname: "Amélie",
|
||||
email: "pakouille.lakouille@yahoo.fr",
|
||||
mobile: "0675650392",
|
||||
photo: "images/volunteers/$taille/amélie_aupeix.jpg",
|
||||
food: "Végétarien",
|
||||
adult: 1,
|
||||
privileges: 0,
|
||||
active: 0,
|
||||
created: new Date(0),
|
||||
password1: "$2y$10$fSxY9AIuxSiEjwF.J3eXGubIxUPlobkyRrNIal8ASimSjNj4SR.9O",
|
||||
password2: "$2y$10$fSxY9AIuxSiEjwF.J3eXGubIxUPlobkyRrNIal8ASimSjNj4SR.9O",
|
||||
},
|
||||
]
|
||||
const mockData: Volunteer[] = [volunteerExample]
|
||||
const mockError = "Oops! Something went wrong."
|
||||
|
||||
describe("volunteerList reducer", () => {
|
||||
|
35
src/store/auth.ts
Normal file
35
src/store/auth.ts
Normal file
@@ -0,0 +1,35 @@
|
||||
import { createSlice, PayloadAction } from "@reduxjs/toolkit"
|
||||
import { AppState } from "."
|
||||
|
||||
// Define a type for the slice state
|
||||
interface AuthState {
|
||||
id: number
|
||||
jwt: string
|
||||
}
|
||||
|
||||
// Define the initial state using that type
|
||||
const initialState: AuthState = {
|
||||
id: 0,
|
||||
jwt: "",
|
||||
}
|
||||
|
||||
export const auth = createSlice({
|
||||
name: "auth",
|
||||
initialState,
|
||||
reducers: {
|
||||
setCurrentUser: (state, action: PayloadAction<AuthState>) => {
|
||||
state.id = action.payload.id
|
||||
state.jwt = action.payload.jwt
|
||||
},
|
||||
logoutUser: (state) => {
|
||||
state.id = 0
|
||||
state.jwt = ""
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
export const { setCurrentUser, logoutUser } = auth.actions
|
||||
|
||||
export const selectCount = (state: AppState): AuthState => state.auth
|
||||
|
||||
export default auth.reducer
|
@@ -2,18 +2,22 @@ import { createMemoryHistory, createBrowserHistory } from "history"
|
||||
import { Action, configureStore, EntityState } from "@reduxjs/toolkit"
|
||||
import { ThunkAction } from "redux-thunk"
|
||||
import { routerMiddleware } from "connected-react-router"
|
||||
import Cookies from "js-cookie"
|
||||
|
||||
import createRootReducer from "./rootReducer"
|
||||
import { StateRequest } from "./utils"
|
||||
import { setCurrentUser, logoutUser } from "./auth"
|
||||
|
||||
interface Arg {
|
||||
initialState?: typeof window.__INITIAL_STATE__
|
||||
url?: string
|
||||
jwt?: string
|
||||
id?: number
|
||||
}
|
||||
|
||||
// Use inferred return type for making correctly Redux types
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
|
||||
const createStore = ({ initialState, url }: Arg = {}) => {
|
||||
const createStore = ({ initialState, url, jwt, id }: Arg = {}) => {
|
||||
const history = __SERVER__
|
||||
? createMemoryHistory({ initialEntries: [url || "/"] })
|
||||
: createBrowserHistory()
|
||||
@@ -28,10 +32,20 @@ const createStore = ({ initialState, url }: Arg = {}) => {
|
||||
devTools: __DEV__,
|
||||
})
|
||||
|
||||
if (jwt && id) {
|
||||
store.dispatch(setCurrentUser({ jwt, id }))
|
||||
} else {
|
||||
store.dispatch(logoutUser())
|
||||
}
|
||||
|
||||
return { store, history }
|
||||
}
|
||||
|
||||
const { store } = createStore()
|
||||
const storage: any = localStorage
|
||||
const id = +(Cookies.get("id") || storage?.getItem("id"))
|
||||
const jwt = Cookies.get("jwt") || storage?.getItem("jwt")
|
||||
|
||||
const { store } = createStore({ id, jwt })
|
||||
|
||||
export type AppState = ReturnType<typeof store.getState>
|
||||
|
||||
|
@@ -1,6 +1,7 @@
|
||||
import { History } from "history"
|
||||
import { connectRouter } from "connected-react-router"
|
||||
|
||||
import auth from "./auth"
|
||||
import wishAdd from "./wishAdd"
|
||||
import wishList from "./wishList"
|
||||
import javGameList from "./javGameList"
|
||||
@@ -10,12 +11,14 @@ import volunteerList from "./volunteerList"
|
||||
import volunteerSet from "./volunteerSet"
|
||||
import volunteerLogin from "./volunteerLogin"
|
||||
import volunteerForgot from "./volunteerForgot"
|
||||
import volunteerNotifsSet from "./volunteerNotifsSet"
|
||||
import preVolunteerAdd from "./preVolunteerAdd"
|
||||
import preVolunteerCount from "./preVolunteerCount"
|
||||
|
||||
// Use inferred return type for making correctly Redux types
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
|
||||
export default (history: History) => ({
|
||||
auth,
|
||||
wishAdd,
|
||||
wishList,
|
||||
javGameList,
|
||||
@@ -25,6 +28,7 @@ export default (history: History) => ({
|
||||
volunteerSet,
|
||||
volunteerLogin,
|
||||
volunteerForgot,
|
||||
volunteerNotifsSet,
|
||||
preVolunteerAdd,
|
||||
preVolunteerCount,
|
||||
router: connectRouter(history) as any,
|
||||
|
@@ -1,7 +1,7 @@
|
||||
import { ActionCreatorWithoutPayload, ActionCreatorWithPayload } from "@reduxjs/toolkit"
|
||||
import { toast } from "react-toastify"
|
||||
|
||||
import { AppThunk } from "."
|
||||
import { AppThunk, AppDispatch } from "."
|
||||
|
||||
export interface StateRequest {
|
||||
readyStatus: "idle" | "request" | "success" | "failure"
|
||||
@@ -32,8 +32,8 @@ export function toastSuccess(message: string): void {
|
||||
})
|
||||
}
|
||||
|
||||
export function elementFetch<Element>(
|
||||
elementService: (...idArgs: any[]) => Promise<{
|
||||
export function elementFetch<Element, ServiceInput extends Array<any>>(
|
||||
elementService: (...idArgs: ServiceInput) => Promise<{
|
||||
data?: Element | undefined
|
||||
error?: Error | undefined
|
||||
}>,
|
||||
@@ -41,9 +41,9 @@ export function elementFetch<Element>(
|
||||
getSuccess: ActionCreatorWithPayload<Element, string>,
|
||||
getFailure: ActionCreatorWithPayload<string, string>,
|
||||
errorMessage?: (error: Error) => void,
|
||||
successMessage?: (data: Element) => void
|
||||
): (...idArgs: any[]) => AppThunk {
|
||||
return (...idArgs: any[]): AppThunk =>
|
||||
successMessage?: (data: Element, dispatch: AppDispatch) => void
|
||||
): (...idArgs: ServiceInput) => AppThunk {
|
||||
return (...idArgs: ServiceInput): AppThunk =>
|
||||
async (dispatch) => {
|
||||
dispatch(getRequesting())
|
||||
|
||||
@@ -54,7 +54,7 @@ export function elementFetch<Element>(
|
||||
errorMessage?.(error)
|
||||
} else {
|
||||
dispatch(getSuccess(data as Element))
|
||||
successMessage?.(data as Element)
|
||||
successMessage?.(data as Element, dispatch)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -3,6 +3,9 @@ import { PayloadAction, createSlice } from "@reduxjs/toolkit"
|
||||
import { StateRequest, elementFetch } from "./utils"
|
||||
import { VolunteerLogin, volunteerLogin } from "../services/volunteers"
|
||||
import { setJWT } from "../services/auth"
|
||||
import { AppDispatch } from "."
|
||||
import { setCurrentUser } from "./auth"
|
||||
import { fetchVolunteerNotifsSet } from "./volunteerNotifsSet"
|
||||
|
||||
type StateVolunteer = { entity?: VolunteerLogin } & StateRequest
|
||||
|
||||
@@ -31,13 +34,15 @@ const volunteerLoginSlice = createSlice({
|
||||
export default volunteerLoginSlice.reducer
|
||||
export const { getRequesting, getSuccess, getFailure } = volunteerLoginSlice.actions
|
||||
|
||||
export const fetchVolunteerLogin = elementFetch(
|
||||
export const fetchVolunteerLogin = elementFetch<VolunteerLogin, Parameters<typeof volunteerLogin>>(
|
||||
volunteerLogin,
|
||||
getRequesting,
|
||||
getSuccess,
|
||||
getFailure,
|
||||
undefined,
|
||||
(login: VolunteerLogin) => {
|
||||
setJWT(login.jwt)
|
||||
(login: VolunteerLogin, dispatch: AppDispatch) => {
|
||||
setJWT(login.jwt, login.id)
|
||||
dispatch(setCurrentUser(login))
|
||||
dispatch(fetchVolunteerNotifsSet(login.jwt, login.id, {}))
|
||||
}
|
||||
)
|
||||
|
57
src/store/volunteerNotifsSet.ts
Normal file
57
src/store/volunteerNotifsSet.ts
Normal file
@@ -0,0 +1,57 @@
|
||||
import { PayloadAction, createSlice } from "@reduxjs/toolkit"
|
||||
|
||||
import { StateRequest, toastError, elementFetch } from "./utils"
|
||||
import { VolunteerNotifs, volunteerNotifsSet } from "../services/volunteers"
|
||||
import { AppThunk, AppState } from "."
|
||||
|
||||
type StateVolunteerNotifsSet = { entity?: VolunteerNotifs } & StateRequest
|
||||
|
||||
export const initialState: StateVolunteerNotifsSet = {
|
||||
readyStatus: "idle",
|
||||
}
|
||||
|
||||
const volunteerNotifsSetSlice = createSlice({
|
||||
name: "volunteerNotifsSet",
|
||||
initialState,
|
||||
reducers: {
|
||||
getRequesting: (_) => ({
|
||||
readyStatus: "request",
|
||||
}),
|
||||
getSuccess: (_, { payload }: PayloadAction<VolunteerNotifs>) => ({
|
||||
readyStatus: "success",
|
||||
entity: payload,
|
||||
}),
|
||||
getFailure: (_, { payload }: PayloadAction<string>) => ({
|
||||
readyStatus: "failure",
|
||||
error: payload,
|
||||
}),
|
||||
},
|
||||
})
|
||||
|
||||
export default volunteerNotifsSetSlice.reducer
|
||||
export const { getRequesting, getSuccess, getFailure } = volunteerNotifsSetSlice.actions
|
||||
|
||||
export const fetchVolunteerNotifsSet = elementFetch(
|
||||
volunteerNotifsSet,
|
||||
getRequesting,
|
||||
getSuccess,
|
||||
getFailure,
|
||||
(error: Error) => toastError(`Erreur lors du chargement des notifications: ${error.message}`)
|
||||
)
|
||||
|
||||
const shouldFetchVolunteerNotifsSet = (state: AppState, id: number) =>
|
||||
state.volunteerNotifsSet.readyStatus !== "success" ||
|
||||
(state.volunteerNotifsSet.entity && state.volunteerNotifsSet.entity.id !== id)
|
||||
|
||||
export const fetchVolunteerNotifsSetIfNeed =
|
||||
(id = 0, notif: Partial<VolunteerNotifs> = {}): AppThunk =>
|
||||
(dispatch, getState) => {
|
||||
let jwt = ""
|
||||
if (!id) {
|
||||
;({ id, jwt } = getState().auth)
|
||||
}
|
||||
if (shouldFetchVolunteerNotifsSet(getState(), id))
|
||||
return dispatch(fetchVolunteerNotifsSet(jwt, id, notif))
|
||||
|
||||
return null
|
||||
}
|
Reference in New Issue
Block a user