mirror of
https://github.com/Paris-est-Ludique/intranet.git
synced 2025-06-10 01:24:20 +02:00
Add custom db read support
This commit is contained in:
parent
7fb466d91c
commit
0391fdccd9
@ -9,9 +9,10 @@ import { AppDispatch, AppState } from "../../store"
|
|||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
dispatch: AppDispatch
|
dispatch: AppDispatch
|
||||||
|
preVolunteerCount: number | undefined
|
||||||
}
|
}
|
||||||
|
|
||||||
const RegisterForm = ({ dispatch }: Props): JSX.Element => {
|
const RegisterForm = ({ dispatch, preVolunteerCount }: Props): JSX.Element => {
|
||||||
const [firstname, setFirstname] = useState("")
|
const [firstname, setFirstname] = useState("")
|
||||||
const [lastname, setLastname] = useState("")
|
const [lastname, setLastname] = useState("")
|
||||||
const [email, setEmail] = useState("")
|
const [email, setEmail] = useState("")
|
||||||
@ -158,7 +159,10 @@ const RegisterForm = ({ dispatch }: Props): JSX.Element => {
|
|||||||
Les prochains sont les 21 décembre et 27 janvier, mais nous vous appelerons
|
Les prochains sont les 21 décembre et 27 janvier, mais nous vous appelerons
|
||||||
d'ici là pour les détails :)
|
d'ici là pour les détails :)
|
||||||
<br />
|
<br />
|
||||||
<span className={styles.lightTitle}>(Déjà au moins 8 inscrits !)</span>
|
{/* */}
|
||||||
|
<span className={styles.lightTitle} hidden={(preVolunteerCount || 0) < 3}>
|
||||||
|
(Déjà {preVolunteerCount} inscrits !)
|
||||||
|
</span>
|
||||||
</dt>
|
</dt>
|
||||||
<dd>
|
<dd>
|
||||||
<div className={styles.formLine} key="line-firstname">
|
<div className={styles.formLine} key="line-firstname">
|
@ -5,5 +5,15 @@ import VolunteerSet from "./VolunteerSet"
|
|||||||
import ErrorBoundary from "./ErrorBoundary"
|
import ErrorBoundary from "./ErrorBoundary"
|
||||||
import Loading from "./Loading"
|
import Loading from "./Loading"
|
||||||
import WishAdd from "./WishAdd"
|
import WishAdd from "./WishAdd"
|
||||||
|
import RegisterForm from "./RegisterForm"
|
||||||
|
|
||||||
export { VolunteerList, JavGameList, VolunteerInfo, VolunteerSet, ErrorBoundary, Loading, WishAdd }
|
export {
|
||||||
|
VolunteerList,
|
||||||
|
JavGameList,
|
||||||
|
VolunteerInfo,
|
||||||
|
VolunteerSet,
|
||||||
|
ErrorBoundary,
|
||||||
|
Loading,
|
||||||
|
WishAdd,
|
||||||
|
RegisterForm,
|
||||||
|
}
|
||||||
|
@ -50,10 +50,6 @@ const Home: FC<Props> = (): JSX.Element => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Fetch server-side data here
|
// Fetch server-side data here
|
||||||
export const loadData = (): AppThunk[] => [
|
export const loadData = (): AppThunk[] => [fetchWishListIfNeed(), fetchJavGameListIfNeed()]
|
||||||
fetchWishListIfNeed(),
|
|
||||||
fetchJavGameListIfNeed(),
|
|
||||||
// More pre-fetched actions...
|
|
||||||
]
|
|
||||||
|
|
||||||
export default memo(Home)
|
export default memo(Home)
|
||||||
|
@ -1,22 +1,48 @@
|
|||||||
|
import { FC, useEffect, memo } from "react"
|
||||||
import { RouteComponentProps } from "react-router-dom"
|
import { RouteComponentProps } from "react-router-dom"
|
||||||
import { useDispatch } from "react-redux"
|
import { useDispatch, useSelector, shallowEqual } from "react-redux"
|
||||||
import { FC, memo } from "react"
|
|
||||||
import { Helmet } from "react-helmet"
|
import { Helmet } from "react-helmet"
|
||||||
|
|
||||||
|
import { AppState, AppThunk, ValueRequest } from "../../store"
|
||||||
|
import { fetchPreVolunteerCountIfNeed } from "../../store/preVolunteerCount"
|
||||||
|
import { RegisterForm } from "../../components"
|
||||||
import styles from "./styles.module.scss"
|
import styles from "./styles.module.scss"
|
||||||
import RegisterForm from "../../components/RegisterForm/RegisterForm"
|
|
||||||
|
|
||||||
export type Props = RouteComponentProps
|
export type Props = RouteComponentProps
|
||||||
|
|
||||||
const RegisterPage: FC<Props> = (): JSX.Element => {
|
function useList(
|
||||||
|
stateToProp: (state: AppState) => ValueRequest<number | undefined>,
|
||||||
|
fetchDataIfNeed: () => AppThunk
|
||||||
|
) {
|
||||||
const dispatch = useDispatch()
|
const dispatch = useDispatch()
|
||||||
return (
|
const { readyStatus, value } = useSelector(stateToProp, shallowEqual)
|
||||||
<div className={styles.registerPage}>
|
|
||||||
<div className={styles.registerContent}>
|
// Fetch client-side data here
|
||||||
<Helmet title="RegisterPage" />
|
useEffect(() => {
|
||||||
<RegisterForm dispatch={dispatch} />
|
dispatch(fetchDataIfNeed())
|
||||||
</div>
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
</div>
|
}, [dispatch])
|
||||||
)
|
|
||||||
|
return () => {
|
||||||
|
if (!readyStatus || readyStatus === "idle" || readyStatus === "request")
|
||||||
|
return <p>Loading...</p>
|
||||||
|
|
||||||
|
if (readyStatus === "failure") return <p>Oops, Failed to load!</p>
|
||||||
|
|
||||||
|
return <RegisterForm dispatch={dispatch} preVolunteerCount={value} />
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const RegisterPage: FC<Props> = (): JSX.Element => (
|
||||||
|
<div className={styles.registerPage}>
|
||||||
|
<div className={styles.registerContent}>
|
||||||
|
<Helmet title="RegisterPage" />
|
||||||
|
{useList((state: AppState) => state.preVolunteerCount, fetchPreVolunteerCountIfNeed)()}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
|
||||||
|
// Fetch server-side data here
|
||||||
|
export const loadData = (): AppThunk[] => [fetchPreVolunteerCountIfNeed()]
|
||||||
|
|
||||||
export default memo(RegisterPage)
|
export default memo(RegisterPage)
|
||||||
|
@ -8,7 +8,7 @@ import { GoogleSpreadsheet, GoogleSpreadsheetWorksheet } from "google-spreadshee
|
|||||||
|
|
||||||
const CRED_PATH = path.resolve(process.cwd(), "access/gsheets.json")
|
const CRED_PATH = path.resolve(process.cwd(), "access/gsheets.json")
|
||||||
|
|
||||||
const REMOTE_SAVE_DELAY = 20000
|
const REMOTE_UPDATE_DELAY = 20000
|
||||||
|
|
||||||
export type ElementWithId<ElementNoId> = { id: number } & ElementNoId
|
export type ElementWithId<ElementNoId> = { id: number } & ElementNoId
|
||||||
|
|
||||||
@ -32,7 +32,7 @@ setInterval(
|
|||||||
Object.values(sheetList).forEach((sheet: Sheet<object, ElementWithId<object>>) =>
|
Object.values(sheetList).forEach((sheet: Sheet<object, ElementWithId<object>>) =>
|
||||||
sheet.dbUpdate()
|
sheet.dbUpdate()
|
||||||
),
|
),
|
||||||
REMOTE_SAVE_DELAY
|
REMOTE_UPDATE_DELAY
|
||||||
)
|
)
|
||||||
|
|
||||||
export function getSheet<
|
export function getSheet<
|
||||||
@ -51,7 +51,7 @@ export function getSheet<
|
|||||||
return sheetList[sheetName] as Sheet<ElementNoId, Element>
|
return sheetList[sheetName] as Sheet<ElementNoId, Element>
|
||||||
}
|
}
|
||||||
|
|
||||||
class Sheet<
|
export class Sheet<
|
||||||
// eslint-disable-next-line @typescript-eslint/ban-types
|
// eslint-disable-next-line @typescript-eslint/ban-types
|
||||||
ElementNoId extends object,
|
ElementNoId extends object,
|
||||||
Element extends ElementWithId<ElementNoId>
|
Element extends ElementWithId<ElementNoId>
|
||||||
@ -88,7 +88,7 @@ class Sheet<
|
|||||||
return JSON.parse(JSON.stringify(this._state))
|
return JSON.parse(JSON.stringify(this._state))
|
||||||
}
|
}
|
||||||
|
|
||||||
setList(newState: Element[] | undefined) {
|
setList(newState: Element[] | undefined): void {
|
||||||
this._state = JSON.parse(JSON.stringify(newState))
|
this._state = JSON.parse(JSON.stringify(newState))
|
||||||
this.modifiedSinceSave = true
|
this.modifiedSinceSave = true
|
||||||
}
|
}
|
||||||
|
@ -1,25 +1,29 @@
|
|||||||
import { Request, Response, NextFunction } from "express"
|
import { Request, Response, NextFunction } from "express"
|
||||||
import { SheetNames, ElementWithId, getSheet } from "./accessors"
|
import { SheetNames, ElementWithId, getSheet, Sheet } from "./accessors"
|
||||||
|
|
||||||
export default function getExpressAccessors<
|
export default class ExpressAccessors<
|
||||||
// eslint-disable-next-line @typescript-eslint/ban-types
|
// eslint-disable-next-line @typescript-eslint/ban-types
|
||||||
ElementNoId extends object,
|
ElementNoId extends object,
|
||||||
Element extends ElementWithId<ElementNoId>
|
Element extends ElementWithId<ElementNoId>
|
||||||
>(
|
> {
|
||||||
sheetName: keyof SheetNames,
|
sheet: Sheet<ElementNoId, Element>
|
||||||
specimen: Element,
|
|
||||||
translation: { [k in keyof Element]: string }
|
|
||||||
): any {
|
|
||||||
const sheet = getSheet<ElementNoId, Element>(sheetName, specimen, translation)
|
|
||||||
|
|
||||||
function listGetRequest() {
|
constructor(
|
||||||
|
readonly sheetName: keyof SheetNames,
|
||||||
|
readonly specimen: Element,
|
||||||
|
readonly translation: { [k in keyof Element]: string }
|
||||||
|
) {
|
||||||
|
this.sheet = getSheet<ElementNoId, Element>(sheetName, specimen, translation)
|
||||||
|
}
|
||||||
|
|
||||||
|
listGet() {
|
||||||
return async (
|
return async (
|
||||||
_request: Request,
|
_request: Request,
|
||||||
response: Response,
|
response: Response,
|
||||||
_next: NextFunction
|
_next: NextFunction
|
||||||
): Promise<void> => {
|
): Promise<void> => {
|
||||||
try {
|
try {
|
||||||
const elements = await sheet.getList()
|
const elements = await this.sheet.getList()
|
||||||
if (elements) {
|
if (elements) {
|
||||||
response.status(200).json(elements)
|
response.status(200).json(elements)
|
||||||
}
|
}
|
||||||
@ -29,11 +33,11 @@ export default function getExpressAccessors<
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function getRequest() {
|
get() {
|
||||||
return async (request: Request, response: Response, _next: NextFunction): Promise<void> => {
|
return async (request: Request, response: Response, _next: NextFunction): Promise<void> => {
|
||||||
try {
|
try {
|
||||||
const id = parseInt(request.query.id as string, 10) || -1
|
const id = parseInt(request.query.id as string, 10) || -1
|
||||||
const elements = await sheet.getList()
|
const elements = await this.sheet.getList()
|
||||||
if (elements) {
|
if (elements) {
|
||||||
const element = elements.find((e: Element) => e.id === id)
|
const element = elements.find((e: Element) => e.id === id)
|
||||||
response.status(200).json(element)
|
response.status(200).json(element)
|
||||||
@ -44,14 +48,14 @@ export default function getExpressAccessors<
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function addRequest() {
|
add() {
|
||||||
return async (request: Request, response: Response, _next: NextFunction): Promise<void> => {
|
return async (request: Request, response: Response, _next: NextFunction): Promise<void> => {
|
||||||
try {
|
try {
|
||||||
sheet.add(request.body)
|
this.sheet.add(request.body)
|
||||||
const elements: Element[] = (await sheet.getList()) || []
|
const elements: Element[] = (await this.sheet.getList()) || []
|
||||||
const element: Element = { id: await sheet.nextId(), ...request.body }
|
const element: Element = { id: await this.sheet.nextId(), ...request.body }
|
||||||
elements.push(element)
|
elements.push(element)
|
||||||
await sheet.setList(elements)
|
await this.sheet.setList(elements)
|
||||||
if (element) {
|
if (element) {
|
||||||
response.status(200).json(element)
|
response.status(200).json(element)
|
||||||
}
|
}
|
||||||
@ -61,10 +65,10 @@ export default function getExpressAccessors<
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function setRequest() {
|
set() {
|
||||||
return async (request: Request, response: Response, _next: NextFunction): Promise<void> => {
|
return async (request: Request, response: Response, _next: NextFunction): Promise<void> => {
|
||||||
try {
|
try {
|
||||||
await sheet.set(request.body)
|
await this.sheet.set(request.body)
|
||||||
response.status(200)
|
response.status(200)
|
||||||
} catch (e: unknown) {
|
} catch (e: unknown) {
|
||||||
response.status(400).json(e)
|
response.status(400).json(e)
|
||||||
@ -72,5 +76,18 @@ export default function getExpressAccessors<
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return { getRequest, addRequest, listGetRequest, setRequest }
|
customGet(transformer: (list?: Element[]) => any) {
|
||||||
|
return async (
|
||||||
|
_request: Request,
|
||||||
|
response: Response,
|
||||||
|
_next: NextFunction
|
||||||
|
): Promise<void> => {
|
||||||
|
try {
|
||||||
|
const elements = await this.sheet.getList()
|
||||||
|
response.status(200).json(transformer(elements))
|
||||||
|
} catch (e: unknown) {
|
||||||
|
response.status(400).json(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,15 +1,16 @@
|
|||||||
import getExpressAccessors from "./expressAccessors"
|
import ExpressAccessors from "./expressAccessors"
|
||||||
import { JavGame, JavGameWithoutId, translationJavGame } from "../../services/javGames"
|
import { JavGame, JavGameWithoutId, translationJavGame } from "../../services/javGames"
|
||||||
|
|
||||||
const { listGetRequest, getRequest, setRequest, addRequest } = getExpressAccessors<
|
const expressAccessor = new ExpressAccessors<JavGameWithoutId, JavGame>(
|
||||||
JavGameWithoutId,
|
"JavGames",
|
||||||
JavGame
|
new JavGame(),
|
||||||
>("JavGames", new JavGame(), translationJavGame)
|
translationJavGame
|
||||||
|
)
|
||||||
|
|
||||||
export const javGameListGet = listGetRequest()
|
export const javGameListGet = expressAccessor.listGet()
|
||||||
|
|
||||||
export const javGameGet = getRequest()
|
export const javGameGet = expressAccessor.get()
|
||||||
|
|
||||||
export const javGameAdd = addRequest()
|
export const javGameAdd = expressAccessor.add()
|
||||||
|
|
||||||
export const javGameSet = setRequest()
|
export const javGameSet = expressAccessor.set()
|
||||||
|
@ -1,19 +1,24 @@
|
|||||||
import getExpressAccessors from "./expressAccessors"
|
import ExpressAccessors from "./expressAccessors"
|
||||||
import {
|
import {
|
||||||
PreVolunteer,
|
PreVolunteer,
|
||||||
PreVolunteerWithoutId,
|
PreVolunteerWithoutId,
|
||||||
translationPreVolunteer,
|
translationPreVolunteer,
|
||||||
} from "../../services/preVolunteers"
|
} from "../../services/preVolunteers"
|
||||||
|
|
||||||
const { listGetRequest, getRequest, setRequest, addRequest } = getExpressAccessors<
|
const expressAccessor = new ExpressAccessors<PreVolunteerWithoutId, PreVolunteer>(
|
||||||
PreVolunteerWithoutId,
|
"PreVolunteers",
|
||||||
PreVolunteer
|
new PreVolunteer(),
|
||||||
>("PreVolunteers", new PreVolunteer(), translationPreVolunteer)
|
translationPreVolunteer
|
||||||
|
)
|
||||||
|
|
||||||
export const preVolunteerListGet = listGetRequest()
|
export const preVolunteerListGet = expressAccessor.listGet()
|
||||||
|
|
||||||
export const preVolunteerGet = getRequest()
|
export const preVolunteerGet = expressAccessor.get()
|
||||||
|
|
||||||
export const preVolunteerAdd = addRequest()
|
export const preVolunteerAdd = expressAccessor.add()
|
||||||
|
|
||||||
export const preVolunteerSet = setRequest()
|
export const preVolunteerSet = expressAccessor.set()
|
||||||
|
|
||||||
|
export const preVolunteerCountGet = expressAccessor.customGet(
|
||||||
|
(list?: PreVolunteer[]) => (list && list.length) || 0
|
||||||
|
)
|
||||||
|
@ -1,15 +1,16 @@
|
|||||||
import getExpressAccessors from "./expressAccessors"
|
import ExpressAccessors from "./expressAccessors"
|
||||||
import { Volunteer, VolunteerWithoutId, translationVolunteer } from "../../services/volunteers"
|
import { Volunteer, VolunteerWithoutId, translationVolunteer } from "../../services/volunteers"
|
||||||
|
|
||||||
const { listGetRequest, getRequest, setRequest, addRequest } = getExpressAccessors<
|
const expressAccessor = new ExpressAccessors<VolunteerWithoutId, Volunteer>(
|
||||||
VolunteerWithoutId,
|
"Volunteers",
|
||||||
Volunteer
|
new Volunteer(),
|
||||||
>("Volunteers", new Volunteer(), translationVolunteer)
|
translationVolunteer
|
||||||
|
)
|
||||||
|
|
||||||
export const volunteerListGet = listGetRequest()
|
export const volunteerListGet = expressAccessor.listGet()
|
||||||
|
|
||||||
export const volunteerGet = getRequest()
|
export const volunteerGet = expressAccessor.get()
|
||||||
|
|
||||||
export const volunteerAdd = addRequest()
|
export const volunteerAdd = expressAccessor.add()
|
||||||
|
|
||||||
export const volunteerSet = setRequest()
|
export const volunteerSet = expressAccessor.set()
|
||||||
|
@ -1,15 +1,16 @@
|
|||||||
import getExpressAccessors from "./expressAccessors"
|
import ExpressAccessors from "./expressAccessors"
|
||||||
import { Wish, WishWithoutId, translationWish } from "../../services/wishes"
|
import { Wish, WishWithoutId, translationWish } from "../../services/wishes"
|
||||||
|
|
||||||
const { listGetRequest, getRequest, setRequest, addRequest } = getExpressAccessors<
|
const expressAccessor = new ExpressAccessors<WishWithoutId, Wish>(
|
||||||
WishWithoutId,
|
"Wishes",
|
||||||
Wish
|
new Wish(),
|
||||||
>("Wishes", new Wish(), translationWish)
|
translationWish
|
||||||
|
)
|
||||||
|
|
||||||
export const wishListGet = listGetRequest()
|
export const wishListGet = expressAccessor.listGet()
|
||||||
|
|
||||||
export const wishGet = getRequest()
|
export const wishGet = expressAccessor.get()
|
||||||
|
|
||||||
export const wishAdd = addRequest()
|
export const wishAdd = expressAccessor.add()
|
||||||
|
|
||||||
export const wishSet = setRequest()
|
export const wishSet = expressAccessor.set()
|
||||||
|
@ -18,7 +18,7 @@ import certbotRouter from "../routes/certbot"
|
|||||||
import { secure } from "./secure"
|
import { secure } from "./secure"
|
||||||
import { javGameListGet } from "./gsheets/javGames"
|
import { javGameListGet } from "./gsheets/javGames"
|
||||||
import { wishListGet, wishAdd } from "./gsheets/wishes"
|
import { wishListGet, wishAdd } from "./gsheets/wishes"
|
||||||
import { preVolunteerAdd } from "./gsheets/preVolunteers"
|
import { preVolunteerAdd, preVolunteerCountGet } from "./gsheets/preVolunteers"
|
||||||
import { volunteerGet, volunteerSet } from "./gsheets/volunteers"
|
import { volunteerGet, volunteerSet } from "./gsheets/volunteers"
|
||||||
import loginHandler from "./userManagement/login"
|
import loginHandler from "./userManagement/login"
|
||||||
import config from "../config"
|
import config from "../config"
|
||||||
@ -58,6 +58,7 @@ app.get("/JavGameListGet", javGameListGet)
|
|||||||
app.get("/WishListGet", wishListGet)
|
app.get("/WishListGet", wishListGet)
|
||||||
app.post("/WishAdd", wishAdd)
|
app.post("/WishAdd", wishAdd)
|
||||||
app.post("/PreVolunteerAdd", preVolunteerAdd)
|
app.post("/PreVolunteerAdd", preVolunteerAdd)
|
||||||
|
app.get("/PreVolunteerCountGet", preVolunteerCountGet)
|
||||||
|
|
||||||
// Secured APIs
|
// Secured APIs
|
||||||
app.get("/VolunteerGet", secure as RequestHandler, volunteerGet)
|
app.get("/VolunteerGet", secure as RequestHandler, volunteerGet)
|
||||||
|
@ -147,5 +147,26 @@ export default function getServiceAccessors<
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return { listGet, get, set, add }
|
function countGet(): () => Promise<{
|
||||||
|
data?: number
|
||||||
|
error?: Error
|
||||||
|
}> {
|
||||||
|
interface ElementCountGetResponse {
|
||||||
|
data?: number
|
||||||
|
error?: Error
|
||||||
|
}
|
||||||
|
return async (): Promise<ElementCountGetResponse> => {
|
||||||
|
try {
|
||||||
|
const { data } = await axios.get(
|
||||||
|
`${config.API_URL}/${elementName}CountGet`,
|
||||||
|
axiosConfig
|
||||||
|
)
|
||||||
|
return { data }
|
||||||
|
} catch (error) {
|
||||||
|
return { error: error as Error }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return { listGet, get, set, add, countGet }
|
||||||
}
|
}
|
||||||
|
@ -30,12 +30,13 @@ const elementName = "PreVolunteer"
|
|||||||
|
|
||||||
export type PreVolunteerWithoutId = Omit<PreVolunteer, "id">
|
export type PreVolunteerWithoutId = Omit<PreVolunteer, "id">
|
||||||
|
|
||||||
const { listGet, get, set, add } = getServiceAccessors<PreVolunteerWithoutId, PreVolunteer>(
|
const { listGet, get, set, add, countGet } = getServiceAccessors<
|
||||||
elementName,
|
PreVolunteerWithoutId,
|
||||||
translationPreVolunteer
|
PreVolunteer
|
||||||
)
|
>(elementName, translationPreVolunteer)
|
||||||
|
|
||||||
export const preVolunteerListGet = listGet()
|
export const preVolunteerListGet = listGet()
|
||||||
export const preVolunteerGet = get()
|
export const preVolunteerGet = get()
|
||||||
export const preVolunteerAdd = add()
|
export const preVolunteerAdd = add()
|
||||||
export const preVolunteerSet = set()
|
export const preVolunteerSet = set()
|
||||||
|
export const preVolunteerCountGet = countGet()
|
||||||
|
@ -41,4 +41,6 @@ export type AppThunk = ThunkAction<void, AppState, unknown, Action<string>>
|
|||||||
|
|
||||||
export type EntitiesRequest<T> = EntityState<T> & StateRequest
|
export type EntitiesRequest<T> = EntityState<T> & StateRequest
|
||||||
|
|
||||||
|
export type ValueRequest<T> = { value?: T } & StateRequest
|
||||||
|
|
||||||
export default createStore
|
export default createStore
|
||||||
|
45
src/store/preVolunteerCount.ts
Normal file
45
src/store/preVolunteerCount.ts
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
import { PayloadAction, createSlice } from "@reduxjs/toolkit"
|
||||||
|
|
||||||
|
import { StateRequest, toastError, elementValueFetch } from "./utils"
|
||||||
|
import { preVolunteerCountGet } from "../services/preVolunteers"
|
||||||
|
import { AppThunk, AppState } from "."
|
||||||
|
|
||||||
|
export const initialState: StateRequest & { value?: number } = { readyStatus: "idle" }
|
||||||
|
|
||||||
|
const preVolunteerCount = createSlice({
|
||||||
|
name: "preVolunteerCount",
|
||||||
|
initialState,
|
||||||
|
reducers: {
|
||||||
|
getRequesting: (state) => {
|
||||||
|
state.readyStatus = "request"
|
||||||
|
},
|
||||||
|
getSuccess: (state, { payload }: PayloadAction<number>) => {
|
||||||
|
state.readyStatus = "success"
|
||||||
|
state.value = payload
|
||||||
|
},
|
||||||
|
getFailure: (state, { payload }: PayloadAction<string>) => {
|
||||||
|
state.readyStatus = "failure"
|
||||||
|
state.error = payload
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
export default preVolunteerCount.reducer
|
||||||
|
export const { getRequesting, getSuccess, getFailure } = preVolunteerCount.actions
|
||||||
|
|
||||||
|
export const fetchPreVolunteerCount = elementValueFetch(
|
||||||
|
preVolunteerCountGet,
|
||||||
|
getRequesting,
|
||||||
|
getSuccess,
|
||||||
|
getFailure,
|
||||||
|
(error: Error) => toastError(`Erreur lors du chargement des volunteers: ${error.message}`)
|
||||||
|
)
|
||||||
|
|
||||||
|
const shouldFetchPreVolunteerCount = (state: AppState) =>
|
||||||
|
state.preVolunteerCount.readyStatus !== "success"
|
||||||
|
|
||||||
|
export const fetchPreVolunteerCountIfNeed = (): AppThunk => (dispatch, getState) => {
|
||||||
|
if (shouldFetchPreVolunteerCount(getState())) return dispatch(fetchPreVolunteerCount())
|
||||||
|
|
||||||
|
return null
|
||||||
|
}
|
@ -9,6 +9,7 @@ import volunteerAdd from "./volunteerAdd"
|
|||||||
import volunteerList from "./volunteerList"
|
import volunteerList from "./volunteerList"
|
||||||
import volunteerSet from "./volunteerSet"
|
import volunteerSet from "./volunteerSet"
|
||||||
import preVolunteerAdd from "./preVolunteerAdd"
|
import preVolunteerAdd from "./preVolunteerAdd"
|
||||||
|
import preVolunteerCount from "./preVolunteerCount"
|
||||||
|
|
||||||
// Use inferred return type for making correctly Redux types
|
// Use inferred return type for making correctly Redux types
|
||||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
|
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
|
||||||
@ -21,6 +22,7 @@ export default (history: History) => ({
|
|||||||
volunteerList,
|
volunteerList,
|
||||||
volunteerSet,
|
volunteerSet,
|
||||||
preVolunteerAdd,
|
preVolunteerAdd,
|
||||||
|
preVolunteerCount,
|
||||||
router: connectRouter(history) as any,
|
router: connectRouter(history) as any,
|
||||||
// Register more reducers...
|
// Register more reducers...
|
||||||
})
|
})
|
||||||
|
@ -154,3 +154,33 @@ export function elementSet<Element>(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function elementValueFetch<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()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user