Rename all french to english

This commit is contained in:
pikiou 2021-12-08 10:46:53 +01:00
parent d63f906206
commit 1844c6acad
66 changed files with 653 additions and 625 deletions

View File

@ -315,13 +315,13 @@ export { SCOPES }
class Test { class Test {
id = 5 id = 5
envies = "" wishes = ""
dateAjout: Date = new Date(0) dateAjout: Date = new Date(0)
ignore = false ignore = false
membres: number[] = [] volunteers: number[] = []
equipes: string[] = [] equipes: string[] = []
@ -335,10 +335,10 @@ async function testGSheetAPi(): Promise<void> {
const dataset: Test[] = [ const dataset: Test[] = [
{ {
id: 1, id: 1,
envies: "Présenter le festival et son organisation à un nouveau bénévol au téléphone", wishes: "Présenter le festival et son organisation à un nouveau bénévol au téléphone",
dateAjout: new Date("2021-10-18T22:00:00.000Z"), dateAjout: new Date("2021-10-18T22:00:00.000Z"),
ignore: true, ignore: true,
membres: [2, 5, 6, 4, 2, 7], volunteers: [2, 5, 6, 4, 2, 7],
equipes: ["Accueillir les bénévoles"], equipes: ["Accueillir les bénévoles"],
datesPossibles: [ datesPossibles: [
new Date("2021-11-18T23:00:00.000Z"), new Date("2021-11-18T23:00:00.000Z"),
@ -349,34 +349,34 @@ async function testGSheetAPi(): Promise<void> {
}, },
{ {
id: 5, id: 5,
envies: "Créer de jolies pages webs", wishes: "Créer de jolies pages webs",
dateAjout: new Date("2021-10-18T22:00:00.000Z"), dateAjout: new Date("2021-10-18T22:00:00.000Z"),
ignore: false, ignore: false,
membres: [7], volunteers: [7],
equipes: ["Site Web Public", "Force Orange"], equipes: ["Site Web Public", "Force Orange"],
datesPossibles: [], datesPossibles: [],
tictactoe: [], tictactoe: [],
}, },
{ {
id: 6, id: 6,
envies: "Modérer un salon Discord", wishes: "Modérer un salon Discord",
dateAjout: new Date("2021-10-18T22:00:00.000Z"), dateAjout: new Date("2021-10-18T22:00:00.000Z"),
ignore: true, ignore: true,
membres: [], volunteers: [],
equipes: [], equipes: [],
datesPossibles: [new Date("2024-10-18T22:00:00.000Z")], datesPossibles: [new Date("2024-10-18T22:00:00.000Z")],
tictactoe: [false, false, false, false, true, true, true, true], tictactoe: [false, false, false, false, true, true, true, true],
}, },
] ]
// console.log("Lecture des Membres...") // console.log("Lecture des Volunteers...")
// const datasetMembresLu = await getList<Membre>("Membres", new Membre()) // const datasetVolunteersLu = await getList<Volunteer>("Volunteers", new Volunteer())
// if (!datasetMembresLu) { // if (!datasetVolunteersLu) {
// console.log("ECHEC de la lecture des membres", datasetMembresLu) // console.log("ECHEC de la lecture des volunteers", datasetVolunteersLu)
// return // return
// } // }
// console.log("Extraction des membres réussie") // console.log("Extraction des volunteers réussie")
// await fs.writeFile("membres.json", JSON.stringify(datasetMembresLu)) // await fs.writeFile("volunteers.json", JSON.stringify(datasetVolunteersLu))
console.log("Test d'écriture...") console.log("Test d'écriture...")
const resultatEcriture = await setList<Test>("Tests de l'API", dataset) const resultatEcriture = await setList<Test>("Tests de l'API", dataset)

View File

@ -5,15 +5,15 @@ import { render } from "@testing-library/react"
import { MemoryRouter } from "react-router-dom" import { MemoryRouter } from "react-router-dom"
import mockStore from "../../../utils/mockStore" import mockStore from "../../../utils/mockStore"
import JeuJavList from "../index" import JavGameList from "../index"
describe("<List />", () => { describe("<List />", () => {
const renderHelper = (reducer = { readyStatus: "idle" }) => { const renderHelper = (reducer = { readyStatus: "idle" }) => {
const { dispatch, ProviderWithStore } = mockStore({ jeuJavList: reducer }) const { dispatch, ProviderWithStore } = mockStore({ javGameList: reducer })
const { container } = render( const { container } = render(
<ProviderWithStore> <ProviderWithStore>
<MemoryRouter> <MemoryRouter>
<JeuJavList ids={[5]} /> <JavGameList ids={[5]} />
</MemoryRouter> </MemoryRouter>
</ProviderWithStore> </ProviderWithStore>
) )

View File

@ -2,7 +2,7 @@
exports[`<List /> renders 1`] = ` exports[`<List /> renders 1`] = `
<div <div
class="JeuJavList" class="JavGameList"
> >
<h4> <h4>
Jeux JAV Jeux JAV

View File

@ -10,10 +10,10 @@ interface Props {
ids: EntityId[] ids: EntityId[]
} }
const JeuJavList = ({ ids }: Props) => { const JavGameList = ({ ids }: Props) => {
const { entities: jeuxJav } = useSelector((state: AppState) => state.jeuJavList, shallowEqual) const { entities: jeuxJav } = useSelector((state: AppState) => state.javGameList, shallowEqual)
return ( return (
<div className={styles.JeuJavList}> <div className={styles.JavGameList}>
<h4>Jeux JAV</h4> <h4>Jeux JAV</h4>
<ul> <ul>
{ids.map((id) => { {ids.map((id) => {
@ -33,4 +33,4 @@ const JeuJavList = ({ ids }: Props) => {
) )
} }
export default memo(JeuJavList) export default memo(JavGameList)

View File

@ -1,20 +0,0 @@
import { memo } from "react"
import { Membre } from "../../services/membres"
import styles from "./styles.module.scss"
interface Props {
item: Membre
}
const MembreInfo = ({ item }: Props) => (
<div className={styles.MembreCard}>
<h4>Membre Info</h4>
<ul>
<li>Prénom: {item.firstname}</li>
<li>Nom: {item.lastname}</li>
</ul>
</div>
)
export default memo(MembreInfo)

View File

@ -4,7 +4,7 @@ import { toast } from "react-toastify"
import _ from "lodash" import _ from "lodash"
import styles from "./styles.module.scss" import styles from "./styles.module.scss"
import { fetchPreMemberAdd } from "../../store/preMemberAdd" import { fetchPreMemberAdd } from "../../store/preVolunteerAdd"
import { AppDispatch, AppState } from "../../store" import { AppDispatch, AppState } from "../../store"
interface Props { interface Props {
@ -142,7 +142,7 @@ const RegisterForm = ({ dispatch }: Props): JSX.Element => {
Certains bénévoles sont visiteurs le samedi ou le dimanche pour vivre le Certains bénévoles sont visiteurs le samedi ou le dimanche pour vivre le
festival de l&apos;intérieur. Les deux jours avant et le jour après le festival de l&apos;intérieur. Les deux jours avant et le jour après le
festival, ceux qui le peuvent viennent préparer et ranger. Bref, chacun festival, ceux qui le peuvent viennent préparer et ranger. Bref, chacun
participe à la hauteur de ses envies et disponibilités ! participe à la hauteur de ses wishes et disponibilités !
</p> </p>
<p> <p>
Le samedi soir quand les visiteurs sont partis, nous prolongeons la fête en Le samedi soir quand les visiteurs sont partis, nous prolongeons la fête en
@ -228,7 +228,7 @@ const RegisterForm = ({ dispatch }: Props): JSX.Element => {
<textarea <textarea
name="message" name="message"
id="message" id="message"
placeholder="Des petits mots sympas, questions, envies, des infos sur toi, des compétences dont tu aimerais te servir... ou rien de tout ça et nous en discuterons au téléphone :)" placeholder="Des petits mots sympas, questions, wishes, des infos sur toi, des compétences dont tu aimerais te servir... ou rien de tout ça et nous en discuterons au téléphone :)"
value={comment} value={comment}
onChange={onCommentChanged} onChange={onCommentChanged}
/> />

View File

@ -4,20 +4,20 @@
import { render } from "@testing-library/react" import { render } from "@testing-library/react"
import { MemoryRouter } from "react-router-dom" import { MemoryRouter } from "react-router-dom"
import MembreInfo from "../index" import VolunteerInfo from "../index"
describe("<MembreInfo />", () => { describe("<VolunteerInfo />", () => {
it("renders", () => { it("renders", () => {
const tree = render( const tree = render(
<MemoryRouter> <MemoryRouter>
<MembreInfo <VolunteerInfo
item={{ item={{
id: 1, id: 1,
firstname: "Aupeix", firstname: "Aupeix",
lastname: "Amélie", lastname: "Amélie",
email: "pakouille.lakouille@yahoo.fr", email: "pakouille.lakouille@yahoo.fr",
mobile: "0675650392", mobile: "0675650392",
photo: "images/membres/$taille/amélie_aupeix.jpg", photo: "images/volunteers/$taille/amélie_aupeix.jpg",
food: "Végétarien", food: "Végétarien",
adult: 1, adult: 1,
privileges: 0, privileges: 0,

View File

@ -1,11 +1,11 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP // Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`<MembreInfo /> renders 1`] = ` exports[`<VolunteerInfo /> renders 1`] = `
<div <div
class="MembreCard" class="VolunteerCard"
> >
<h4> <h4>
Membre Info Volunteer Info
</h4> </h4>
<ul> <ul>
<li> <li>

View File

@ -0,0 +1,20 @@
import { memo } from "react"
import { Volunteer } from "../../services/volunteers"
import styles from "./styles.module.scss"
interface Props {
item: Volunteer
}
const VolunteerInfo = ({ item }: Props) => (
<div className={styles.VolunteerCard}>
<h4>Volunteer Info</h4>
<ul>
<li>Prénom: {item.firstname}</li>
<li>Nom: {item.lastname}</li>
</ul>
</div>
)
export default memo(VolunteerInfo)

View File

@ -1,4 +1,4 @@
.membre-card { .volunteer-card {
ul { ul {
padding-left: 17px; padding-left: 17px;
} }

View File

@ -4,13 +4,13 @@
import { render } from "@testing-library/react" import { render } from "@testing-library/react"
import { MemoryRouter } from "react-router-dom" import { MemoryRouter } from "react-router-dom"
import MembreList from "../index" import VolunteerList from "../index"
describe("<MembreList />", () => { describe("<VolunteerList />", () => {
it("renders", () => { it("renders", () => {
const tree = render( const tree = render(
<MemoryRouter> <MemoryRouter>
<MembreList <VolunteerList
items={[ items={[
{ {
id: 1, id: 1,
@ -18,7 +18,7 @@ describe("<MembreList />", () => {
lastname: "Amélie", lastname: "Amélie",
email: "pakouille.lakouille@yahoo.fr", email: "pakouille.lakouille@yahoo.fr",
mobile: "0675650392", mobile: "0675650392",
photo: "images/membres/$taille/amélie_aupeix.jpg", photo: "images/volunteers/$taille/amélie_aupeix.jpg",
food: "Végétarien", food: "Végétarien",
adult: 1, adult: 1,
privileges: 0, privileges: 0,

View File

@ -1,16 +1,16 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP // Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`<MembreList /> renders 1`] = ` exports[`<VolunteerList /> renders 1`] = `
<div <div
class="user-list" class="user-list"
> >
<h4> <h4>
Membre List Volunteer List
</h4> </h4>
<ul> <ul>
<li> <li>
<a <a
href="/Membre/1" href="/Volunteer/1"
> >
<b> <b>
Aupeix Aupeix

View File

@ -1,20 +1,20 @@
import { memo } from "react" import { memo } from "react"
import { Link } from "react-router-dom" import { Link } from "react-router-dom"
import { Membre } from "../../services/membres" import { Volunteer } from "../../services/volunteers"
import styles from "./styles.module.scss" import styles from "./styles.module.scss"
interface Props { interface Props {
items: Membre[] items: Volunteer[]
} }
const MembreList = ({ items }: Props) => ( const VolunteerList = ({ items }: Props) => (
<div className={styles["user-list"]}> <div className={styles["user-list"]}>
<h4>Membre List</h4> <h4>Volunteer List</h4>
<ul> <ul>
{items.map(({ id, lastname, firstname }) => ( {items.map(({ id, lastname, firstname }) => (
<li key={id}> <li key={id}>
<Link to={`/Membre/${id}`}> <Link to={`/Volunteer/${id}`}>
<b>{firstname}</b> {lastname} <b>{firstname}</b> {lastname}
</Link> </Link>
</li> </li>
@ -23,4 +23,4 @@ const MembreList = ({ items }: Props) => (
</div> </div>
) )
export default memo(MembreList) export default memo(VolunteerList)

View File

@ -4,22 +4,22 @@
import { render } from "@testing-library/react" import { render } from "@testing-library/react"
import { MemoryRouter } from "react-router-dom" import { MemoryRouter } from "react-router-dom"
import MembreSet from "../index" import VolunteerSet from "../index"
describe("<SetMembre />", () => { describe("<SetVolunteer />", () => {
it("renders", () => { it("renders", () => {
const dispatch = jest.fn() const dispatch = jest.fn()
const tree = render( const tree = render(
<MemoryRouter> <MemoryRouter>
<MembreSet <VolunteerSet
dispatch={dispatch} dispatch={dispatch}
membre={{ volunteer={{
id: 1, id: 1,
firstname: "Aupeix", firstname: "Aupeix",
lastname: "Amélie", lastname: "Amélie",
email: "pakouille.lakouille@yahoo.fr", email: "pakouille.lakouille@yahoo.fr",
mobile: "0675650392", mobile: "0675650392",
photo: "images/membres/$taille/amélie_aupeix.jpg", photo: "images/volunteers/$taille/amélie_aupeix.jpg",
food: "Végétarien", food: "Végétarien",
adult: 1, adult: 1,
privileges: 0, privileges: 0,

View File

@ -1,11 +1,11 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP // Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`<SetMembre /> renders 1`] = ` exports[`<SetVolunteer /> renders 1`] = `
<section <section
class="MembreList" class="VolunteerList"
> >
<h2> <h2>
Modifier un membre Modifier un volunteer
</h2> </h2>
<form> <form>
<label <label

View File

@ -3,19 +3,19 @@ import { toast } from "react-toastify"
import { AppDispatch } from "../../store" import { AppDispatch } from "../../store"
import { fetchMembreSet } from "../../store/membreSet" import { fetchVolunteerSet } from "../../store/volunteerSet"
import { Membre } from "../../services/membres" import { Volunteer } from "../../services/volunteers"
import styles from "./styles.module.scss" import styles from "./styles.module.scss"
interface Props { interface Props {
dispatch: AppDispatch dispatch: AppDispatch
membre: Membre volunteer: Volunteer
} }
const MembreSet = ({ dispatch, membre }: Props) => { const VolunteerSet = ({ dispatch, volunteer }: Props) => {
const [firstname, setFirstname] = useState(membre.firstname) const [firstname, setFirstname] = useState(volunteer.firstname)
const [lastname, setName] = useState(membre.lastname) const [lastname, setName] = useState(volunteer.lastname)
const [adult, setAdult] = useState(membre.adult) const [adult, setAdult] = useState(volunteer.adult)
const onFirstnameChanged = (e: React.ChangeEvent<HTMLInputElement>) => const onFirstnameChanged = (e: React.ChangeEvent<HTMLInputElement>) =>
setFirstname(e.target.value) setFirstname(e.target.value)
@ -25,8 +25,8 @@ const MembreSet = ({ dispatch, membre }: Props) => {
const onSavePostClicked = () => { const onSavePostClicked = () => {
if (firstname && lastname) { if (firstname && lastname) {
dispatch( dispatch(
fetchMembreSet({ fetchVolunteerSet({
...membre, ...volunteer,
firstname, firstname,
lastname, lastname,
adult, adult,
@ -45,8 +45,8 @@ const MembreSet = ({ dispatch, membre }: Props) => {
} }
} }
return ( return (
<section className={styles.MembreList}> <section className={styles.VolunteerList}>
<h2>Modifier un membre</h2> <h2>Modifier un volunteer</h2>
<form> <form>
<label htmlFor="postFirstname"> <label htmlFor="postFirstname">
Prénom: Prénom:
@ -85,4 +85,4 @@ const MembreSet = ({ dispatch, membre }: Props) => {
</section> </section>
) )
} }
export default memo(MembreSet) export default memo(VolunteerSet)

View File

@ -4,14 +4,14 @@
import { render } from "@testing-library/react" import { render } from "@testing-library/react"
import { MemoryRouter } from "react-router-dom" import { MemoryRouter } from "react-router-dom"
import AddEnvie from "../index" import WishAdd from "../index"
describe("<AddEnvie />", () => { describe("<WishAdd />", () => {
it("renders", () => { it("renders", () => {
const dispatch = jest.fn() const dispatch = jest.fn()
const tree = render( const tree = render(
<MemoryRouter> <MemoryRouter>
<AddEnvie dispatch={dispatch} /> <WishAdd dispatch={dispatch} />
</MemoryRouter> </MemoryRouter>
).container.firstChild ).container.firstChild

View File

@ -1,11 +1,11 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP // Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`<AddEnvie /> renders 1`] = ` exports[`<WishAdd /> renders 1`] = `
<section <section
class="EnvieList" class="WishList"
> >
<h2> <h2>
Ajouter une nouvelle envie Ajouter une nouvelle wish
</h2> </h2>
<form> <form>
<label <label

View File

@ -3,13 +3,13 @@ import { toast } from "react-toastify"
import styles from "./styles.module.scss" import styles from "./styles.module.scss"
import { AppDispatch } from "../../store" import { AppDispatch } from "../../store"
import { fetchEnvieAdd } from "../../store/envieAdd" import { fetchWishAdd } from "../../store/wishAdd"
interface Props { interface Props {
dispatch: AppDispatch dispatch: AppDispatch
} }
const AddEnvie = ({ dispatch }: Props) => { const WishAdd = ({ dispatch }: Props) => {
const [domain, setDomain] = useState("") const [domain, setDomain] = useState("")
const [wish, setWish] = useState("") const [wish, setWish] = useState("")
const [details, setDetails] = useState("") const [details, setDetails] = useState("")
@ -28,7 +28,7 @@ const AddEnvie = ({ dispatch }: Props) => {
const onSavePostClicked = () => { const onSavePostClicked = () => {
if (domain && wish) { if (domain && wish) {
dispatch( dispatch(
fetchEnvieAdd({ fetchWishAdd({
domain, domain,
wish, wish,
details, details,
@ -43,7 +43,7 @@ const AddEnvie = ({ dispatch }: Props) => {
setTeams([""]) setTeams([""])
setAddedDate("") setAddedDate("")
} else { } else {
toast.warning("Il faut au moins préciser un domain et l'envie", { toast.warning("Il faut au moins préciser un domain et l'wish", {
position: "top-center", position: "top-center",
autoClose: 6000, autoClose: 6000,
hideProgressBar: true, hideProgressBar: true,
@ -55,8 +55,8 @@ const AddEnvie = ({ dispatch }: Props) => {
} }
} }
return ( return (
<section className={styles.EnvieList}> <section className={styles.WishList}>
<h2>Ajouter une nouvelle envie</h2> <h2>Ajouter une nouvelle wish</h2>
<form> <form>
<label htmlFor="postDomain"> <label htmlFor="postDomain">
Domaine: Domaine:
@ -108,4 +108,4 @@ const AddEnvie = ({ dispatch }: Props) => {
</section> </section>
) )
} }
export default memo(AddEnvie) export default memo(WishAdd)

View File

@ -1,9 +1,9 @@
import MembreList from "./MembreList" import VolunteerList from "./VolunteerList"
import JeuJavList from "./JeuJavList" import JavGameList from "./JavGameList"
import MembreInfo from "./MembreInfo" import VolunteerInfo from "./VolunteerInfo"
import MembreSet from "./MembreSet" import VolunteerSet from "./VolunteerSet"
import ErrorBoundary from "./ErrorBoundary" import ErrorBoundary from "./ErrorBoundary"
import Loading from "./Loading" import Loading from "./Loading"
import AddEnvie from "./AddEnvie" import WishAdd from "./WishAdd"
export { MembreList, JeuJavList, MembreInfo, MembreSet, ErrorBoundary, Loading, AddEnvie } export { VolunteerList, JavGameList, VolunteerInfo, VolunteerSet, ErrorBoundary, Loading, WishAdd }

View File

@ -4,9 +4,9 @@ import { useDispatch, useSelector, shallowEqual } from "react-redux"
import { Helmet } from "react-helmet" import { Helmet } from "react-helmet"
import { AppState, AppThunk, EntitiesRequest } from "../../store" import { AppState, AppThunk, EntitiesRequest } from "../../store"
import { fetchJeuJavListIfNeed } from "../../store/jeuJavList" import { fetchJavGameListIfNeed } from "../../store/javGameList"
import { fetchEnvieListIfNeed } from "../../store/envieList" import { fetchWishListIfNeed } from "../../store/wishList"
import { JeuJavList, AddEnvie } from "../../components" import { JavGameList, WishAdd } from "../../components"
import styles from "./styles.module.scss" import styles from "./styles.module.scss"
export type Props = RouteComponentProps export type Props = RouteComponentProps
@ -30,7 +30,7 @@ function useList<Entity>(
if (readyStatus === "failure") return <p>Oops, Failed to load list!</p> if (readyStatus === "failure") return <p>Oops, Failed to load list!</p>
return <JeuJavList ids={ids} /> return <JavGameList ids={ids} />
} }
} }
@ -39,9 +39,9 @@ const Home: FC<Props> = (): JSX.Element => {
return ( return (
<div className={styles.home}> <div className={styles.home}>
<Helmet title="Home" /> <Helmet title="Home" />
<AddEnvie dispatch={dispatch} /> <WishAdd dispatch={dispatch} />
{/* {useList((state: AppState) => state.envieList, fetchEnvieListifNeed)()} */} {/* {useList((state: AppState) => state.wishList, fetchWishListifNeed)()} */}
{useList((state: AppState) => state.jeuJavList, fetchJeuJavListIfNeed)()} {useList((state: AppState) => state.javGameList, fetchJavGameListIfNeed)()}
{/* <button type="button" onClick={() => setList([{id: 3, joueurs: 4, duree: 5, description: "abcd"}])}> {/* <button type="button" onClick={() => setList([{id: 3, joueurs: 4, duree: 5, description: "abcd"}])}>
Set list! Set list!
</button> */} </button> */}
@ -51,8 +51,8 @@ const Home: FC<Props> = (): JSX.Element => {
// Fetch server-side data here // Fetch server-side data here
export const loadData = (): AppThunk[] => [ export const loadData = (): AppThunk[] => [
fetchEnvieListIfNeed(), fetchWishListIfNeed(),
fetchJeuJavListIfNeed(), fetchJavGameListIfNeed(),
// More pre-fetched actions... // More pre-fetched actions...
] ]

View File

@ -4,40 +4,40 @@ import { useDispatch, useSelector, shallowEqual } from "react-redux"
import { Helmet } from "react-helmet" import { Helmet } from "react-helmet"
import { AppState, AppThunk } from "../../store" import { AppState, AppThunk } from "../../store"
import { fetchMembreIfNeed } from "../../store/membre" import { fetchVolunteerIfNeed } from "../../store/volunteer"
import { MembreInfo, MembreSet } from "../../components" import { VolunteerInfo, VolunteerSet } from "../../components"
import styles from "./styles.module.scss" import styles from "./styles.module.scss"
export type Props = RouteComponentProps<{ id: string }> export type Props = RouteComponentProps<{ id: string }>
const MembrePage = ({ match }: Props): JSX.Element => { const VolunteerPage = ({ match }: Props): JSX.Element => {
const { id: rawId } = match.params const { id: rawId } = match.params
const id = +rawId const id = +rawId
const dispatch = useDispatch() const dispatch = useDispatch()
const membre = useSelector((state: AppState) => state.membre, shallowEqual) const volunteer = useSelector((state: AppState) => state.volunteer, shallowEqual)
useEffect(() => { useEffect(() => {
dispatch(fetchMembreIfNeed(id)) dispatch(fetchVolunteerIfNeed(id))
}, [dispatch, id]) }, [dispatch, id])
const renderInfo = () => { const renderInfo = () => {
const membreInfo = membre const volunteerInfo = volunteer
if (!membreInfo || membreInfo.readyStatus === "request") return <p>Loading...</p> if (!volunteerInfo || volunteerInfo.readyStatus === "request") return <p>Loading...</p>
if (membreInfo.readyStatus === "failure" || !membreInfo.entity) if (volunteerInfo.readyStatus === "failure" || !volunteerInfo.entity)
return <p>Oops! Failed to load data.</p> return <p>Oops! Failed to load data.</p>
return ( return (
<div> <div>
<MembreInfo item={membreInfo.entity} /> <VolunteerInfo item={volunteerInfo.entity} />
<MembreSet dispatch={dispatch} membre={membreInfo.entity} /> <VolunteerSet dispatch={dispatch} volunteer={volunteerInfo.entity} />
</div> </div>
) )
} }
return ( return (
<div className={styles.membre}> <div className={styles.volunteer}>
<Helmet title="User Info" /> <Helmet title="User Info" />
{renderInfo()} {renderInfo()}
</div> </div>
@ -48,6 +48,6 @@ interface LoadDataArgs {
params: { id: number } params: { id: number }
} }
export const loadData = ({ params }: LoadDataArgs): AppThunk[] => [fetchMembreIfNeed(params.id)] export const loadData = ({ params }: LoadDataArgs): AppThunk[] => [fetchVolunteerIfNeed(params.id)]
export default memo(MembrePage) export default memo(VolunteerPage)

View File

@ -1,15 +1,15 @@
import loadable from "@loadable/component" import loadable from "@loadable/component"
import { Loading, ErrorBoundary } from "../../components" import { Loading, ErrorBoundary } from "../../components"
import { Props, loadData } from "./MembrePage" import { Props, loadData } from "./VolunteerPage"
const MembrePage = loadable(() => import("./MembrePage"), { const VolunteerPage = loadable(() => import("./VolunteerPage"), {
fallback: <Loading />, fallback: <Loading />,
}) })
export default (props: Props): JSX.Element => ( export default (props: Props): JSX.Element => (
<ErrorBoundary> <ErrorBoundary>
<MembrePage {...props} /> <VolunteerPage {...props} />
</ErrorBoundary> </ErrorBoundary>
) )
export { loadData } export { loadData }

View File

@ -1,3 +1,3 @@
.membre { .volunteer {
padding: 0 15px; padding: 0 15px;
} }

View File

@ -2,7 +2,7 @@ import { RouteConfig } from "react-router-config"
import App from "../app" import App from "../app"
import AsyncHome, { loadData as loadHomeData } from "../pages/Home" import AsyncHome, { loadData as loadHomeData } from "../pages/Home"
import AsyncMembrePage, { loadData as loadMembrePageData } from "../pages/MembrePage" import AsyncVolunteerPage, { loadData as loadVolunteerPageData } from "../pages/VolunteerPage"
import Login from "../pages/Login" import Login from "../pages/Login"
import Register from "../pages/Register" import Register from "../pages/Register"
import NotFound from "../pages/NotFound" import NotFound from "../pages/NotFound"
@ -17,9 +17,9 @@ export default [
component: Register, component: Register,
}, },
{ {
path: "/MembrePage/:id", path: "/VolunteerPage/:id",
component: AsyncMembrePage, component: AsyncVolunteerPage,
loadData: loadMembrePageData, loadData: loadVolunteerPageData,
}, },
{ {
path: "/login", path: "/login",

View File

@ -9,7 +9,14 @@ const CRED_PATH = path.resolve(process.cwd(), "access/gsheets.json")
export type ElementWithId = unknown & { id: number } export type ElementWithId = unknown & { id: number }
export default function getAccessors< export const sheetNames: { [name: string]: string } = {
JavGames: "Jeux JAV",
Volunteers: "Membres",
PreVolunteers: "PreMembres",
Wishes: "Envies d'aider",
}
export function getAccessors<
// eslint-disable-next-line @typescript-eslint/ban-types // eslint-disable-next-line @typescript-eslint/ban-types
ElementNoId extends object, ElementNoId extends object,
Element extends ElementNoId & ElementWithId Element extends ElementNoId & ElementWithId
@ -52,10 +59,10 @@ export default function getAccessors<
}) })
} }
async function get(membreId: number): Promise<Element | undefined> { async function get(volunteerId: number): Promise<Element | undefined> {
// No need to addDBOperation here, since listGet does it already // No need to addDBOperation here, since listGet does it already
const list = await listGet() const list = await listGet()
return list.find((element) => element.id === membreId) return list.find((element) => element.id === volunteerId)
} }
async function setList(elements: Element[]): Promise<true | undefined> { async function setList(elements: Element[]): Promise<true | undefined> {

View File

@ -1,15 +0,0 @@
import getExpressAccessors from "./expressAccessors"
import { Envie, EnvieWithoutId, translationEnvie } from "../../services/envies"
const { listGetRequest, getRequest, setRequest, addRequest } = getExpressAccessors<
EnvieWithoutId,
Envie
>("Envies d'aider", new Envie(), translationEnvie)
export const envieListGet = listGetRequest()
export const envieGet = getRequest()
export const envieAdd = addRequest()
export const envieSet = setRequest()

View File

@ -1,5 +1,5 @@
import { Request, Response, NextFunction } from "express" import { Request, Response, NextFunction } from "express"
import getAccessors, { ElementWithId } from "./accessors" import { ElementWithId, getAccessors } from "./accessors"
export default function getExpressAccessors< export default function getExpressAccessors<
// eslint-disable-next-line @typescript-eslint/ban-types // eslint-disable-next-line @typescript-eslint/ban-types

View File

@ -0,0 +1,16 @@
import getExpressAccessors from "./expressAccessors"
import { sheetNames } from "./accessors"
import { JavGame, JavGameWithoutId, translationJavGame } from "../../services/javGames"
const { listGetRequest, getRequest, setRequest, addRequest } = getExpressAccessors<
JavGameWithoutId,
JavGame
>(sheetNames.JavGames, new JavGame(), translationJavGame)
export const javGameListGet = listGetRequest()
export const javGameGet = getRequest()
export const javGameAdd = addRequest()
export const javGameSet = setRequest()

View File

@ -1,15 +0,0 @@
import getExpressAccessors from "./expressAccessors"
import { JeuJav, JeuJavWithoutId, translationJeuJav } from "../../services/jeuxJav"
const { listGetRequest, getRequest, setRequest, addRequest } = getExpressAccessors<
JeuJavWithoutId,
JeuJav
>("Jeux JAV", new JeuJav(), translationJeuJav)
export const jeuJavListGet = listGetRequest()
export const jeuJavGet = getRequest()
export const jeuJavAdd = addRequest()
export const jeuJavSet = setRequest()

View File

@ -1,15 +0,0 @@
import getExpressAccessors from "./expressAccessors"
import { Membre, MembreWithoutId, translationMember } from "../../services/membres"
const { listGetRequest, getRequest, setRequest, addRequest } = getExpressAccessors<
MembreWithoutId,
Membre
>("Membres", new Membre(), translationMember)
export const membreListGet = listGetRequest()
export const membreGet = getRequest()
export const membreAdd = addRequest()
export const membreSet = setRequest()

View File

@ -1,10 +1,11 @@
import getExpressAccessors from "./expressAccessors" import getExpressAccessors from "./expressAccessors"
import { PreMember, PreMemberWithoutId, translationPreMember } from "../../services/preMembers" import { sheetNames } from "./accessors"
import { PreMember, PreMemberWithoutId, translationPreMember } from "../../services/preVolunteers"
const { listGetRequest, getRequest, setRequest, addRequest } = getExpressAccessors< const { listGetRequest, getRequest, setRequest, addRequest } = getExpressAccessors<
PreMemberWithoutId, PreMemberWithoutId,
PreMember PreMember
>("PreMembres", new PreMember(), translationPreMember) >(sheetNames.PreVolunteers, new PreMember(), translationPreMember)
export const preMemberListGet = listGetRequest() export const preMemberListGet = listGetRequest()

View File

@ -0,0 +1,16 @@
import getExpressAccessors from "./expressAccessors"
import { sheetNames } from "./accessors"
import { Volunteer, VolunteerWithoutId, translationMember } from "../../services/volunteers"
const { listGetRequest, getRequest, setRequest, addRequest } = getExpressAccessors<
VolunteerWithoutId,
Volunteer
>(sheetNames.Volunteers, new Volunteer(), translationMember)
export const volunteerListGet = listGetRequest()
export const volunteerGet = getRequest()
export const volunteerAdd = addRequest()
export const volunteerSet = setRequest()

View File

@ -0,0 +1,16 @@
import getExpressAccessors from "./expressAccessors"
import { sheetNames } from "./accessors"
import { Wish, WishWithoutId, translationWish } from "../../services/wishes"
const { listGetRequest, getRequest, setRequest, addRequest } = getExpressAccessors<
WishWithoutId,
Wish
>(sheetNames.Wishes, new Wish(), translationWish)
export const wishListGet = listGetRequest()
export const wishGet = getRequest()
export const wishAdd = addRequest()
export const wishSet = setRequest()

View File

@ -16,10 +16,10 @@ import ssr from "./ssr"
import certbotRouter from "../routes/certbot" import certbotRouter from "../routes/certbot"
import { secure } from "./secure" import { secure } from "./secure"
import { jeuJavListGet } from "./gsheets/jeuJav" import { javGameListGet } from "./gsheets/javGames"
import { envieListGet, envieAdd } from "./gsheets/envies" import { wishListGet, wishAdd } from "./gsheets/wishes"
import { preMemberAdd } from "./gsheets/preMembers" import { preMemberAdd } from "./gsheets/preVolunteers"
import { membreGet, membreSet } from "./gsheets/membres" import { volunteerGet, volunteerSet } from "./gsheets/volunteers"
import loginHandler from "./userManagement/login" import loginHandler from "./userManagement/login"
import config from "../config" import config from "../config"
@ -54,14 +54,14 @@ app.post("/api/user/login", loginHandler)
* APIs * APIs
*/ */
// Google Sheets API // Google Sheets API
app.get("/JeuJavListGet", jeuJavListGet) app.get("/JavGameListGet", javGameListGet)
app.get("/EnvieListGet", envieListGet) app.get("/WishListGet", wishListGet)
app.post("/EnvieAdd", envieAdd) app.post("/WishAdd", wishAdd)
app.post("/PreMemberAdd", preMemberAdd) app.post("/PreMemberAdd", preMemberAdd)
// Secured APIs // Secured APIs
app.get("/MembreGet", secure as RequestHandler, membreGet) app.get("/VolunteerGet", secure as RequestHandler, volunteerGet)
app.post("/MembreSet", secure as RequestHandler, membreSet) app.post("/VolunteerSet", secure as RequestHandler, volunteerSet)
// Use React server-side rendering middleware // Use React server-side rendering middleware
app.get("*", ssr) app.get("*", ssr)

View File

@ -3,11 +3,12 @@
*/ */
import _ from "lodash" import _ from "lodash"
import { getAccessors } from "../../gsheets/accessors"
import { login } from "../login" import { login } from "../login"
// Could do a full test with: wget --header='Content-Type:application/json' --post-data='{"email":"pikiou.sub@gmail.com","password":"mot de passe"}' http://localhost:3000/api/user/login // Could do a full test with: wget --header='Content-Type:application/json' --post-data='{"email":"pikiou.sub@gmail.com","password":"mot de passe"}' http://localhost:3000/api/user/login
// Full test with Bearer: wget --header='Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyIjoicGlraW91c3ViQGdlYWlsLmNvbSIsInBlcm1pc3Npb25zIjpbXSwiaWF0IjoxNjM4MjUzODgzLCJleHAiOjE2Mzg4NTg2ODN9.MknJ4NfcVlgW2ODeimfwZI1a4z8asdEXtHwHgViy6c4' http://localhost:3000/MembreGet?id=1 // Full test with Bearer: wget --header='Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyIjoicGlraW91c3ViQGdlYWlsLmNvbSIsInBlcm1pc3Npb25zIjpbXSwiaWF0IjoxNjM4MjUzODgzLCJleHAiOjE2Mzg4NTg2ODN9.MknJ4NfcVlgW2ODeimfwZI1a4z8asdEXtHwHgViy6c4' http://localhost:3000/VolunteerGet?id=1
const mockUser = { const mockUser = {
email: "my.email@gmail.com", email: "my.email@gmail.com",
@ -15,15 +16,19 @@ const mockUser = {
firstname: "monPrénom", firstname: "monPrénom",
} }
jest.mock("../../gsheets/accessors", () => () => ({ jest.mock("../../gsheets/accessors")
listGet: () => [mockUser],
}))
describe("login with", () => { describe("login with", () => {
beforeAll(() => {
;(getAccessors as jest.Mock).mockImplementation(() => ({
listGet: () => [mockUser],
}))
})
it("right password", async () => { it("right password", async () => {
const res = await login("my.email@gmail.com", "12345678") const res = await login("my.email@gmail.com", "12345678")
expect(_.omit(res, "jwt")).toEqual({ expect(_.omit(res, "jwt")).toEqual({
membre: { volunteer: {
firstname: mockUser.firstname, firstname: mockUser.firstname,
}, },
}) })

View File

@ -1,17 +1,15 @@
import { Request, Response, NextFunction } from "express" import { Request, Response, NextFunction } from "express"
import bcrypt from "bcrypt" import bcrypt from "bcrypt"
import { import {
Membre, Volunteer,
MemberLogin, MemberLogin,
emailRegexp, emailRegexp,
passwordMinLength, passwordMinLength,
translationMember, translationMember,
} from "../../services/membres" } from "../../services/volunteers"
import getAccessors from "../gsheets/accessors" import { getAccessors, sheetNames } from "../gsheets/accessors"
import { getJwt } from "../secure" import { getJwt } from "../secure"
const { listGet } = getAccessors("Membres", new Membre(), translationMember)
export default async function loginHandler( export default async function loginHandler(
request: Request, request: Request,
response: Response, response: Response,
@ -33,6 +31,8 @@ export default async function loginHandler(
} }
export async function login(rawEmail: string, rawPassword: string): Promise<MemberLogin> { export async function login(rawEmail: string, rawPassword: string): Promise<MemberLogin> {
const { listGet } = getAccessors(sheetNames.Volunteers, new Volunteer(), translationMember)
const email = rawEmail.replace(/^\s*/, "").replace(/\s*$/, "") const email = rawEmail.replace(/^\s*/, "").replace(/\s*$/, "")
if (!emailRegexp.test(email)) { if (!emailRegexp.test(email)) {
throw Error("Email invalid") throw Error("Email invalid")
@ -46,13 +46,13 @@ export async function login(rawEmail: string, rawPassword: string): Promise<Memb
throw Error("Mot de passe trop court") throw Error("Mot de passe trop court")
} }
const membres: Membre[] = await listGet() const volunteers: Volunteer[] = await listGet()
const membre = membres.find((m) => m.email === email) const volunteer = volunteers.find((m) => m.email === email)
if (!membre) { if (!volunteer) {
throw Error("Cet email ne correspond à aucun utilisateur") throw Error("Cet email ne correspond à aucun utilisateur")
} }
const passwordMatch = await bcrypt.compare(password, membre.password.replace(/^\$2y/, "$2a")) const passwordMatch = await bcrypt.compare(password, volunteer.password.replace(/^\$2y/, "$2a"))
if (!passwordMatch) { if (!passwordMatch) {
throw Error("Mauvais mot de passe pour cet email") throw Error("Mauvais mot de passe pour cet email")
} }
@ -60,8 +60,8 @@ export async function login(rawEmail: string, rawPassword: string): Promise<Memb
const jwt = await getJwt(email) const jwt = await getJwt(email)
return { return {
membre: { volunteer: {
firstname: membre.firstname, firstname: volunteer.firstname,
}, },
jwt, jwt,
} }

View File

@ -75,7 +75,7 @@ export function listGet<Element>(
export function add<ElementNoId extends object, Element extends ElementNoId & ElementWithId>( export function add<ElementNoId extends object, Element extends ElementNoId & ElementWithId>(
elementName: string, elementName: string,
translation: ElementTranslation translation: ElementTranslation
): (membreWithoutId: ElementNoId) => Promise<{ ): (volunteerWithoutId: ElementNoId) => Promise<{
data?: Element data?: Element
error?: Error error?: Error
}> { }> {
@ -83,12 +83,13 @@ export function add<ElementNoId extends object, Element extends ElementNoId & El
data?: Element data?: Element
error?: Error error?: Error
} }
return async (membreWithoutId: ElementNoId): Promise<ElementGetResponse> => { return async (volunteerWithoutId: ElementNoId): Promise<ElementGetResponse> => {
try { try {
const invertedTranslationWithoutId = _.invert(_.omit(translation, "id")) const invertedTranslationWithoutId = _.invert(_.omit(translation, "id"))
const frenchDataWithoutId = _.mapValues( const frenchDataWithoutId = _.mapValues(
invertedTranslationWithoutId, invertedTranslationWithoutId,
(englishProp: string, _frenchProp: string) => (membreWithoutId as any)[englishProp] (englishProp: string, _frenchProp: string) =>
(volunteerWithoutId as any)[englishProp]
) )
const { data } = await axios.post( const { data } = await axios.post(
@ -114,7 +115,7 @@ export function add<ElementNoId extends object, Element extends ElementNoId & El
export function set<Element>( export function set<Element>(
elementName: string, elementName: string,
translation: ElementTranslation translation: ElementTranslation
): (membre: Element) => Promise<{ ): (volunteer: Element) => Promise<{
data?: Element data?: Element
error?: Error error?: Error
}> { }> {
@ -122,12 +123,12 @@ export function set<Element>(
data?: Element data?: Element
error?: Error error?: Error
} }
return async (membre: Element): Promise<ElementGetResponse> => { return async (volunteer: Element): Promise<ElementGetResponse> => {
try { try {
const invertedTranslation = _.invert(translation) const invertedTranslation = _.invert(translation)
const frenchData = _.mapValues( const frenchData = _.mapValues(
invertedTranslation, invertedTranslation,
(englishProp: string) => (membre as any)[englishProp] (englishProp: string) => (volunteer as any)[englishProp]
) )
const { data } = await axios.post( const { data } = await axios.post(

View File

@ -1,36 +0,0 @@
import { get, listGet, add, set } from "./accessors"
export class Envie {
id = 0
domain = ""
wish = ""
details = ""
teams: string[] = []
addedDate = ""
}
export const translationEnvie: { [k in keyof Envie]: string } = {
id: "id",
domain: "domaine",
wish: "envies",
details: "precisions",
teams: "equipes",
addedDate: "dateAjout",
}
const elementName = "Envie"
export type EnvieWithoutId = Omit<Envie, "id">
export const envieGet = get<Envie>(elementName, translationEnvie)
export const envieListGet = listGet<Envie>(elementName, translationEnvie)
export const envieAdd = add<EnvieWithoutId, Envie>(elementName, translationEnvie)
export const envieSet = set<Envie>(elementName, translationEnvie)

View File

@ -1,6 +1,6 @@
import { get, listGet, add, set } from "./accessors" import { get, listGet, add, set } from "./accessors"
export class JeuJav { export class JavGame {
id = 0 id = 0
title = "" title = ""
@ -32,7 +32,7 @@ export class JeuJav {
bggPhoto = "" bggPhoto = ""
} }
export const translationJeuJav: { [k in keyof JeuJav]: string } = { export const translationJavGame: { [k in keyof JavGame]: string } = {
id: "id", id: "id",
title: "titre", title: "titre",
author: "auteur", author: "auteur",
@ -50,14 +50,14 @@ export const translationJeuJav: { [k in keyof JeuJav]: string } = {
bggPhoto: "bggPhoto", bggPhoto: "bggPhoto",
} }
const elementName = "JeuJav" const elementName = "JavGame"
export type JeuJavWithoutId = Omit<JeuJav, "id"> export type JavGameWithoutId = Omit<JavGame, "id">
export const jeuJavGet = get<JeuJav>(elementName, translationJeuJav) export const javGameGet = get<JavGame>(elementName, translationJavGame)
export const jeuJavListGet = listGet<JeuJav>(elementName, translationJeuJav) export const javGameListGet = listGet<JavGame>(elementName, translationJavGame)
export const jeuJavAdd = add<JeuJavWithoutId, JeuJav>(elementName, translationJeuJav) export const javGameAdd = add<JavGameWithoutId, JavGame>(elementName, translationJavGame)
export const jeuJavSet = set<JeuJav>(elementName, translationJeuJav) export const javGameSet = set<JavGame>(elementName, translationJavGame)

View File

@ -1,6 +1,6 @@
import { get, listGet, add, set } from "./accessors" import { get, listGet, add, set } from "./accessors"
export class Membre { export class Volunteer {
id = 0 id = 0
lastname = "" lastname = ""
@ -28,7 +28,7 @@ export class Membre {
password = "" password = ""
} }
export const translationMember: { [k in keyof Membre]: string } = { export const translationMember: { [k in keyof Volunteer]: string } = {
id: "id", id: "id",
lastname: "nom", lastname: "nom",
firstname: "prenom", firstname: "prenom",
@ -44,26 +44,26 @@ export const translationMember: { [k in keyof Membre]: string } = {
password: "passe", password: "passe",
} }
const elementName = "Membre" const elementName = "Volunteer"
export const emailRegexp = export const emailRegexp =
/^(([^<>()[\].,;:\s@"]+(\.[^<>()[\].,;:\s@"]+)*)|(".+"))@(([^<>()[\].,;:\s@"]+\.)+[^<>()[\].,;:\s@"]{2,})$/i /^(([^<>()[\].,;:\s@"]+(\.[^<>()[\].,;:\s@"]+)*)|(".+"))@(([^<>()[\].,;:\s@"]+\.)+[^<>()[\].,;:\s@"]{2,})$/i
export const passwordMinLength = 4 export const passwordMinLength = 4
export interface MemberLogin { export interface MemberLogin {
membre?: { volunteer?: {
firstname: string firstname: string
} }
jwt?: string jwt?: string
error?: string error?: string
} }
export type MembreWithoutId = Omit<Membre, "id"> export type VolunteerWithoutId = Omit<Volunteer, "id">
export const membreGet = get<Membre>(elementName, translationMember) export const volunteerGet = get<Volunteer>(elementName, translationMember)
export const membreListGet = listGet<Membre>(elementName, translationMember) export const volunteerListGet = listGet<Volunteer>(elementName, translationMember)
export const membreAdd = add<MembreWithoutId, Membre>(elementName, translationMember) export const volunteerAdd = add<VolunteerWithoutId, Volunteer>(elementName, translationMember)
export const membreSet = set<Membre>(elementName, translationMember) export const volunteerSet = set<Volunteer>(elementName, translationMember)

36
src/services/wishes.ts Normal file
View File

@ -0,0 +1,36 @@
import { get, listGet, add, set } from "./accessors"
export class Wish {
id = 0
domain = ""
wish = ""
details = ""
teams: string[] = []
addedDate = ""
}
export const translationWish: { [k in keyof Wish]: string } = {
id: "id",
domain: "domaine",
wish: "wishes",
details: "precisions",
teams: "equipes",
addedDate: "dateAjout",
}
const elementName = "Wish"
export type WishWithoutId = Omit<Wish, "id">
export const wishGet = get<Wish>(elementName, translationWish)
export const wishListGet = listGet<Wish>(elementName, translationWish)
export const wishAdd = add<WishWithoutId, Wish>(elementName, translationWish)
export const wishSet = set<Wish>(elementName, translationWish)

View File

@ -2,14 +2,14 @@ import axios from "axios"
import _ from "lodash" import _ from "lodash"
import mockStore from "../../utils/mockStore" import mockStore from "../../utils/mockStore"
import JeuJavList, { import JavGameList, {
initialState, initialState,
getRequesting, getRequesting,
getSuccess, getSuccess,
getFailure, getFailure,
fetchJeuJavList, fetchJavGameList,
} from "../jeuJavList" } from "../javGameList"
import { JeuJav } from "../../services/jeuxJav" import { JavGame } from "../../services/javGames"
jest.mock("axios") jest.mock("axios")
@ -33,7 +33,7 @@ const mockFrenchData: any[] = [
ean: "3421272101313", ean: "3421272101313",
}, },
] ]
const mockEnglishData: JeuJav[] = [ const mockEnglishData: JavGame[] = [
{ {
id: 5, id: 5,
title: "6 qui prend!", title: "6 qui prend!",
@ -55,14 +55,14 @@ const mockEnglishData: JeuJav[] = [
] ]
const mockError = "Oops! Something went wrong." const mockError = "Oops! Something went wrong."
describe("JeuJavList reducer", () => { describe("JavGameList reducer", () => {
it("should handle initial state", () => { it("should handle initial state", () => {
// @ts-expect-error // @ts-expect-error
expect(JeuJavList(undefined, {})).toEqual(initialState) expect(JavGameList(undefined, {})).toEqual(initialState)
}) })
it("should handle requesting correctly", () => { it("should handle requesting correctly", () => {
expect(JeuJavList(undefined, { type: getRequesting.type })).toEqual({ expect(JavGameList(undefined, { type: getRequesting.type })).toEqual({
readyStatus: "request", readyStatus: "request",
ids: [], ids: [],
entities: {}, entities: {},
@ -70,16 +70,18 @@ describe("JeuJavList reducer", () => {
}) })
it("should handle success correctly", () => { it("should handle success correctly", () => {
expect(JeuJavList(undefined, { type: getSuccess.type, payload: mockEnglishData })).toEqual({ expect(JavGameList(undefined, { type: getSuccess.type, payload: mockEnglishData })).toEqual(
...initialState, {
readyStatus: "success", ...initialState,
ids: _.map(mockEnglishData, "id"), readyStatus: "success",
entities: _.keyBy(mockEnglishData, "id"), ids: _.map(mockEnglishData, "id"),
}) entities: _.keyBy(mockEnglishData, "id"),
}
)
}) })
it("should handle failure correctly", () => { it("should handle failure correctly", () => {
expect(JeuJavList(undefined, { type: getFailure.type, payload: mockError })).toEqual({ expect(JavGameList(undefined, { type: getFailure.type, payload: mockError })).toEqual({
...initialState, ...initialState,
readyStatus: "failure", readyStatus: "failure",
error: mockError, error: mockError,
@ -87,8 +89,8 @@ describe("JeuJavList reducer", () => {
}) })
}) })
describe("JeuJavList action", () => { describe("JavGameList action", () => {
it("fetches JeuJav list successful", async () => { it("fetches JavGame list successful", async () => {
const { dispatch, getActions } = mockStore() const { dispatch, getActions } = mockStore()
const expectedActions = [ const expectedActions = [
{ type: getRequesting.type, payload: undefined }, { type: getRequesting.type, payload: undefined },
@ -98,11 +100,11 @@ describe("JeuJavList action", () => {
// @ts-expect-error // @ts-expect-error
axios.get.mockResolvedValue({ data: mockFrenchData }) axios.get.mockResolvedValue({ data: mockFrenchData })
await dispatch(fetchJeuJavList()) await dispatch(fetchJavGameList())
expect(getActions()).toEqual(expectedActions) expect(getActions()).toEqual(expectedActions)
}) })
it("fetches JeuJav list failed", async () => { it("fetches JavGame list failed", async () => {
const { dispatch, getActions } = mockStore() const { dispatch, getActions } = mockStore()
const expectedActions = [ const expectedActions = [
{ type: getRequesting.type }, { type: getRequesting.type },
@ -112,7 +114,7 @@ describe("JeuJavList action", () => {
// @ts-expect-error // @ts-expect-error
axios.get.mockRejectedValue({ message: mockError }) axios.get.mockRejectedValue({ message: mockError })
await dispatch(fetchJeuJavList()) await dispatch(fetchJavGameList())
expect(getActions()).toEqual(expectedActions) expect(getActions()).toEqual(expectedActions)
}) })
}) })

View File

@ -1,8 +1,14 @@
import axios from "axios" import axios from "axios"
import mockStore from "../../utils/mockStore" import mockStore from "../../utils/mockStore"
import membre, { getRequesting, getSuccess, getFailure, fetchMembre, initialState } from "../membre" import volunteer, {
import { Membre } from "../../services/membres" getRequesting,
getSuccess,
getFailure,
fetchVolunteer,
initialState,
} from "../volunteer"
import { Volunteer } from "../../services/volunteers"
jest.mock("axios") jest.mock("axios")
@ -12,7 +18,7 @@ const mockFrenchData: any = {
prenom: "Amélie", prenom: "Amélie",
mail: "pakouille.lakouille@yahoo.fr", mail: "pakouille.lakouille@yahoo.fr",
telephone: "0675650392", telephone: "0675650392",
photo: "images/membres/$taille/amélie_aupeix.jpg", photo: "images/volunteers/$taille/amélie_aupeix.jpg",
alimentation: "Végétarien", alimentation: "Végétarien",
majeur: 1, majeur: 1,
privilege: 0, privilege: 0,
@ -22,13 +28,13 @@ const mockFrenchData: any = {
passe: "$2y$10$fSxY9AIuxSiEjwF.J3eXGubIxUPlobkyRrNIal8ASimSjNj4SR.9O", passe: "$2y$10$fSxY9AIuxSiEjwF.J3eXGubIxUPlobkyRrNIal8ASimSjNj4SR.9O",
} }
const mockEnglishData: Membre = { const mockEnglishData: Volunteer = {
id: 1, id: 1,
lastname: "Aupeix", lastname: "Aupeix",
firstname: "Amélie", firstname: "Amélie",
email: "pakouille.lakouille@yahoo.fr", email: "pakouille.lakouille@yahoo.fr",
mobile: "0675650392", mobile: "0675650392",
photo: "images/membres/$taille/amélie_aupeix.jpg", photo: "images/volunteers/$taille/amélie_aupeix.jpg",
food: "Végétarien", food: "Végétarien",
adult: 1, adult: 1,
privileges: 0, privileges: 0,
@ -40,21 +46,21 @@ const mockEnglishData: Membre = {
const { id } = mockEnglishData const { id } = mockEnglishData
const mockError = "Oops! Something went wrong." const mockError = "Oops! Something went wrong."
describe("membre reducer", () => { describe("volunteer reducer", () => {
it("should handle initial state correctly", () => { it("should handle initial state correctly", () => {
// @ts-expect-error // @ts-expect-error
expect(membre(undefined, {})).toEqual(initialState) expect(volunteer(undefined, {})).toEqual(initialState)
}) })
it("should handle requesting correctly", () => { it("should handle requesting correctly", () => {
expect(membre(undefined, { type: getRequesting.type, payload: id })).toEqual({ expect(volunteer(undefined, { type: getRequesting.type, payload: id })).toEqual({
readyStatus: "request", readyStatus: "request",
}) })
}) })
it("should handle success correctly", () => { it("should handle success correctly", () => {
expect( expect(
membre(undefined, { volunteer(undefined, {
type: getSuccess.type, type: getSuccess.type,
payload: mockEnglishData, payload: mockEnglishData,
}) })
@ -63,7 +69,7 @@ describe("membre reducer", () => {
it("should handle failure correctly", () => { it("should handle failure correctly", () => {
expect( expect(
membre(undefined, { volunteer(undefined, {
type: getFailure.type, type: getFailure.type,
payload: mockError, payload: mockError,
}) })
@ -71,8 +77,8 @@ describe("membre reducer", () => {
}) })
}) })
describe("membre action", () => { describe("volunteer action", () => {
it("fetches membre data successful", async () => { it("fetches volunteer data successful", async () => {
const { dispatch, getActions } = mockStore() const { dispatch, getActions } = mockStore()
const expectedActions = [ const expectedActions = [
{ type: getRequesting.type, payload: undefined }, { type: getRequesting.type, payload: undefined },
@ -82,11 +88,11 @@ describe("membre action", () => {
// @ts-expect-error // @ts-expect-error
axios.get.mockResolvedValue({ data: mockFrenchData }) axios.get.mockResolvedValue({ data: mockFrenchData })
await dispatch(fetchMembre(id)) await dispatch(fetchVolunteer(id))
expect(getActions()).toEqual(expectedActions) expect(getActions()).toEqual(expectedActions)
}) })
it("fetches membre data failed", async () => { it("fetches volunteer data failed", async () => {
const { dispatch, getActions } = mockStore() const { dispatch, getActions } = mockStore()
const expectedActions = [ const expectedActions = [
{ type: getRequesting.type }, { type: getRequesting.type },
@ -96,7 +102,7 @@ describe("membre action", () => {
// @ts-expect-error // @ts-expect-error
axios.get.mockRejectedValue({ message: mockError }) axios.get.mockRejectedValue({ message: mockError })
await dispatch(fetchMembre(id)) await dispatch(fetchVolunteer(id))
expect(getActions()).toEqual(expectedActions) expect(getActions()).toEqual(expectedActions)
}) })
}) })

View File

@ -2,14 +2,14 @@ import axios from "axios"
import _ from "lodash" import _ from "lodash"
import mockStore from "../../utils/mockStore" import mockStore from "../../utils/mockStore"
import membreList, { import volunteerList, {
initialState, initialState,
getRequesting, getRequesting,
getSuccess, getSuccess,
getFailure, getFailure,
fetchMembreList, fetchVolunteerList,
} from "../membreList" } from "../volunteerList"
import { Membre } from "../../services/membres" import { Volunteer } from "../../services/volunteers"
jest.mock("axios") jest.mock("axios")
@ -20,7 +20,7 @@ const mockFrenchData: any[] = [
prenom: "Amélie", prenom: "Amélie",
mail: "pakouille.lakouille@yahoo.fr", mail: "pakouille.lakouille@yahoo.fr",
telephone: "0675650392", telephone: "0675650392",
photo: "images/membres/$taille/amélie_aupeix.jpg", photo: "images/volunteers/$taille/amélie_aupeix.jpg",
alimentation: "Végétarien", alimentation: "Végétarien",
majeur: 1, majeur: 1,
privilege: 0, privilege: 0,
@ -31,14 +31,14 @@ const mockFrenchData: any[] = [
}, },
] ]
const mockEnglishData: Membre[] = [ const mockEnglishData: Volunteer[] = [
{ {
id: 1, id: 1,
lastname: "Aupeix", lastname: "Aupeix",
firstname: "Amélie", firstname: "Amélie",
email: "pakouille.lakouille@yahoo.fr", email: "pakouille.lakouille@yahoo.fr",
mobile: "0675650392", mobile: "0675650392",
photo: "images/membres/$taille/amélie_aupeix.jpg", photo: "images/volunteers/$taille/amélie_aupeix.jpg",
food: "Végétarien", food: "Végétarien",
adult: 1, adult: 1,
privileges: 0, privileges: 0,
@ -50,14 +50,14 @@ const mockEnglishData: Membre[] = [
] ]
const mockError = "Oops! Something went wrong." const mockError = "Oops! Something went wrong."
describe("membreList reducer", () => { describe("volunteerList reducer", () => {
it("should handle initial state", () => { it("should handle initial state", () => {
// @ts-expect-error // @ts-expect-error
expect(membreList(undefined, {})).toEqual(initialState) expect(volunteerList(undefined, {})).toEqual(initialState)
}) })
it("should handle requesting correctly", () => { it("should handle requesting correctly", () => {
expect(membreList(undefined, { type: getRequesting.type })).toEqual({ expect(volunteerList(undefined, { type: getRequesting.type })).toEqual({
readyStatus: "request", readyStatus: "request",
ids: [], ids: [],
entities: {}, entities: {},
@ -65,7 +65,9 @@ describe("membreList reducer", () => {
}) })
it("should handle success correctly", () => { it("should handle success correctly", () => {
expect(membreList(undefined, { type: getSuccess.type, payload: mockEnglishData })).toEqual({ expect(
volunteerList(undefined, { type: getSuccess.type, payload: mockEnglishData })
).toEqual({
...initialState, ...initialState,
readyStatus: "success", readyStatus: "success",
ids: _.map(mockEnglishData, "id"), ids: _.map(mockEnglishData, "id"),
@ -74,7 +76,7 @@ describe("membreList reducer", () => {
}) })
it("should handle failure correctly", () => { it("should handle failure correctly", () => {
expect(membreList(undefined, { type: getFailure.type, payload: mockError })).toEqual({ expect(volunteerList(undefined, { type: getFailure.type, payload: mockError })).toEqual({
...initialState, ...initialState,
readyStatus: "failure", readyStatus: "failure",
error: mockError, error: mockError,
@ -82,8 +84,8 @@ describe("membreList reducer", () => {
}) })
}) })
describe("membreList action", () => { describe("volunteerList action", () => {
it("fetches membre list successful", async () => { it("fetches volunteer list successful", async () => {
const { dispatch, getActions } = mockStore() const { dispatch, getActions } = mockStore()
const expectedActions = [ const expectedActions = [
{ type: getRequesting.type, payload: undefined }, { type: getRequesting.type, payload: undefined },
@ -93,11 +95,11 @@ describe("membreList action", () => {
// @ts-expect-error // @ts-expect-error
axios.get.mockResolvedValue({ data: mockFrenchData }) axios.get.mockResolvedValue({ data: mockFrenchData })
await dispatch(fetchMembreList()) await dispatch(fetchVolunteerList())
expect(getActions()).toEqual(expectedActions) expect(getActions()).toEqual(expectedActions)
}) })
it("fetches membre list failed", async () => { it("fetches volunteer list failed", async () => {
const { dispatch, getActions } = mockStore() const { dispatch, getActions } = mockStore()
const expectedActions = [ const expectedActions = [
{ type: getRequesting.type }, { type: getRequesting.type },
@ -107,7 +109,7 @@ describe("membreList action", () => {
// @ts-expect-error // @ts-expect-error
axios.get.mockRejectedValue({ message: mockError }) axios.get.mockRejectedValue({ message: mockError })
await dispatch(fetchMembreList()) await dispatch(fetchVolunteerList())
expect(getActions()).toEqual(expectedActions) expect(getActions()).toEqual(expectedActions)
}) })
}) })

View File

@ -1,38 +0,0 @@
import { PayloadAction, createSlice, createEntityAdapter } from "@reduxjs/toolkit"
import { StateRequest, toastError, toastSuccess, elementAddFetch } from "./utils"
import { Envie, envieAdd } from "../services/envies"
const envieAdapter = createEntityAdapter<Envie>()
const envieAddSlice = createSlice({
name: "addEnvie",
initialState: envieAdapter.getInitialState({
readyStatus: "idle",
} as StateRequest),
reducers: {
getRequesting: (state) => {
state.readyStatus = "request"
},
getSuccess: (state, { payload }: PayloadAction<Envie>) => {
state.readyStatus = "success"
envieAdapter.addOne(state, payload)
},
getFailure: (state, { payload }: PayloadAction<string>) => {
state.readyStatus = "failure"
state.error = payload
},
},
})
export default envieAddSlice.reducer
export const { getRequesting, getSuccess, getFailure } = envieAddSlice.actions
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 !")
)

View File

@ -1,46 +0,0 @@
import { PayloadAction, createSlice, createEntityAdapter } from "@reduxjs/toolkit"
import { StateRequest, toastError, elementListFetch } from "./utils"
import { Envie, envieListGet } from "../services/envies"
import { AppThunk, AppState } from "."
const envieAdapter = createEntityAdapter<Envie>()
const envieList = createSlice({
name: "getEnvieList",
initialState: envieAdapter.getInitialState({
readyStatus: "idle",
} as StateRequest),
reducers: {
getRequesting: (state) => {
state.readyStatus = "request"
},
getSuccess: (state, { payload }: PayloadAction<Envie[]>) => {
state.readyStatus = "success"
envieAdapter.setAll(state, payload)
},
getFailure: (state, { payload }: PayloadAction<string>) => {
state.readyStatus = "failure"
state.error = payload
},
},
})
export default envieList.reducer
export const { getRequesting, getSuccess, getFailure } = envieList.actions
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"
export const fetchEnvieListIfNeed = (): AppThunk => (dispatch, getState) => {
if (shouldFetchEnvieList(getState())) return dispatch(fetchEnvieList())
return null
}

48
src/store/javGameList.ts Normal file
View File

@ -0,0 +1,48 @@
import { PayloadAction, createSlice, createEntityAdapter } from "@reduxjs/toolkit"
import { StateRequest, toastError, elementListFetch } from "./utils"
import { JavGame, javGameListGet } from "../services/javGames"
import { AppThunk, AppState } from "."
const javGameAdapter = createEntityAdapter<JavGame>()
export const initialState = javGameAdapter.getInitialState({
readyStatus: "idle",
} as StateRequest)
const javGameList = createSlice({
name: "javGameList",
initialState,
reducers: {
getRequesting: (state) => {
state.readyStatus = "request"
},
getSuccess: (state, { payload }: PayloadAction<JavGame[]>) => {
state.readyStatus = "success"
javGameAdapter.setAll(state, payload)
},
getFailure: (state, { payload }: PayloadAction<string>) => {
state.readyStatus = "failure"
state.error = payload
},
},
})
export default javGameList.reducer
export const { getRequesting, getSuccess, getFailure } = javGameList.actions
export const fetchJavGameList = elementListFetch(
javGameListGet,
getRequesting,
getSuccess,
getFailure,
(error: Error) => toastError(`Erreur lors du chargement des jeux JAV: ${error.message}`)
)
const shouldFetchJavGameList = (state: AppState) => state.javGameList.readyStatus !== "success"
export const fetchJavGameListIfNeed = (): AppThunk => (dispatch, getState) => {
if (shouldFetchJavGameList(getState())) return dispatch(fetchJavGameList())
return null
}

View File

@ -1,48 +0,0 @@
import { PayloadAction, createSlice, createEntityAdapter } from "@reduxjs/toolkit"
import { StateRequest, toastError, elementListFetch } from "./utils"
import { JeuJav, jeuJavListGet } from "../services/jeuxJav"
import { AppThunk, AppState } from "."
const jeuJavAdapter = createEntityAdapter<JeuJav>()
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 = 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"
export const fetchJeuJavListIfNeed = (): AppThunk => (dispatch, getState) => {
if (shouldFetchJeuJavList(getState())) return dispatch(fetchJeuJavList())
return null
}

View File

@ -1,51 +0,0 @@
import { PayloadAction, createSlice } from "@reduxjs/toolkit"
import { StateRequest, toastError, elementFetch } from "./utils"
import { Membre, membreGet } from "../services/membres"
import { AppThunk, AppState } from "."
type StateMembre = { entity?: Membre } & StateRequest
export const initialState: StateMembre = {
readyStatus: "idle",
}
const membre = createSlice({
name: "membre",
initialState,
reducers: {
getRequesting: (_) => ({
readyStatus: "request",
}),
getSuccess: (_, { payload }: PayloadAction<Membre>) => ({
readyStatus: "success",
entity: payload,
}),
getFailure: (_, { payload }: PayloadAction<string>) => ({
readyStatus: "failure",
error: payload,
}),
},
})
export default membre.reducer
export const { getRequesting, getSuccess, getFailure } = membre.actions
export const fetchMembre = elementFetch(
membreGet,
getRequesting,
getSuccess,
getFailure,
(error: Error) => toastError(`Erreur lors du chargement d'un membre: ${error.message}`)
)
const shouldFetchMembre = (state: AppState, id: number) =>
state.membre.readyStatus !== "success" || (state.membre.entity && state.membre.entity.id !== id)
export const fetchMembreIfNeed =
(id: number): AppThunk =>
(dispatch, getState) => {
if (shouldFetchMembre(getState(), id)) return dispatch(fetchMembre(id))
return null
}

View File

@ -1,38 +0,0 @@
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 !")
)

View File

@ -1,48 +0,0 @@
import { PayloadAction, createSlice, createEntityAdapter } from "@reduxjs/toolkit"
import { StateRequest, toastError, elementListFetch } from "./utils"
import { Membre, membreListGet } from "../services/membres"
import { AppThunk, AppState } from "."
const membreAdapter = createEntityAdapter<Membre>()
export const initialState = membreAdapter.getInitialState({
readyStatus: "idle",
} as StateRequest)
const membreList = createSlice({
name: "membreList",
initialState,
reducers: {
getRequesting: (state) => {
state.readyStatus = "request"
},
getSuccess: (state, { payload }: PayloadAction<Membre[]>) => {
state.readyStatus = "success"
membreAdapter.setAll(state, payload)
},
getFailure: (state, { payload }: PayloadAction<string>) => {
state.readyStatus = "failure"
state.error = payload
},
},
})
export default membreList.reducer
export const { getRequesting, getSuccess, getFailure } = membreList.actions
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"
export const fetchMembreListIfNeed = (): AppThunk => (dispatch, getState) => {
if (shouldFetchMembreList(getState())) return dispatch(fetchMembreList())
return null
}

View File

@ -1,7 +1,7 @@
import { PayloadAction, createSlice, createEntityAdapter } from "@reduxjs/toolkit" import { PayloadAction, createSlice, createEntityAdapter } from "@reduxjs/toolkit"
import { StateRequest, elementAddFetch } from "./utils" import { StateRequest, elementAddFetch } from "./utils"
import { PreMember, preMemberAdd } from "../services/preMembers" import { PreMember, preMemberAdd } from "../services/preVolunteers"
const preMemberAdapter = createEntityAdapter<PreMember>() const preMemberAdapter = createEntityAdapter<PreMember>()

View File

@ -1,25 +1,25 @@
import { History } from "history" import { History } from "history"
import { connectRouter } from "connected-react-router" import { connectRouter } from "connected-react-router"
import envieAdd from "./envieAdd" import wishAdd from "./wishAdd"
import envieList from "./envieList" import wishList from "./wishList"
import jeuJavList from "./jeuJavList" import javGameList from "./javGameList"
import membre from "./membre" import volunteer from "./volunteer"
import membreAdd from "./membreAdd" import volunteerAdd from "./volunteerAdd"
import membreList from "./membreList" import volunteerList from "./volunteerList"
import membreSet from "./membreSet" import volunteerSet from "./volunteerSet"
import preMemberAdd from "./preMemberAdd" import preMemberAdd from "./preVolunteerAdd"
// 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
export default (history: History) => ({ export default (history: History) => ({
envieAdd, wishAdd,
envieList, wishList,
jeuJavList, javGameList,
membre, volunteer,
membreAdd, volunteerAdd,
membreList, volunteerList,
membreSet, volunteerSet,
preMemberAdd, preMemberAdd,
router: connectRouter(history) as any, router: connectRouter(history) as any,
// Register more reducers... // Register more reducers...

View File

@ -64,7 +64,7 @@ export function elementFetch<Element>(
} }
export function elementAddFetch<Element>( export function elementAddFetch<Element>(
elementAddService: (membreWithoutId: Omit<Element, "id">) => Promise<{ elementAddService: (volunteerWithoutId: Omit<Element, "id">) => Promise<{
data?: Element | undefined data?: Element | undefined
error?: Error | undefined error?: Error | undefined
}>, }>,
@ -77,12 +77,12 @@ export function elementAddFetch<Element>(
successMessage: () => void = () => { successMessage: () => void = () => {
/* Meant to be empty */ /* Meant to be empty */
} }
): (membreWithoutId: Omit<Element, "id">) => AppThunk { ): (volunteerWithoutId: Omit<Element, "id">) => AppThunk {
return (membreWithoutId: Omit<Element, "id">): AppThunk => return (volunteerWithoutId: Omit<Element, "id">): AppThunk =>
async (dispatch) => { async (dispatch) => {
dispatch(getRequesting()) dispatch(getRequesting())
const { error, data } = await elementAddService(membreWithoutId) const { error, data } = await elementAddService(volunteerWithoutId)
if (error) { if (error) {
dispatch(getFailure(error.message)) dispatch(getFailure(error.message))
@ -125,7 +125,7 @@ export function elementListFetch<Element>(
} }
export function elementSet<Element>( export function elementSet<Element>(
elementSetService: (membre: Element) => Promise<{ elementSetService: (volunteer: Element) => Promise<{
data?: Element | undefined data?: Element | undefined
error?: Error | undefined error?: Error | undefined
}>, }>,

52
src/store/volunteer.ts Normal file
View File

@ -0,0 +1,52 @@
import { PayloadAction, createSlice } from "@reduxjs/toolkit"
import { StateRequest, toastError, elementFetch } from "./utils"
import { Volunteer, volunteerGet } from "../services/volunteers"
import { AppThunk, AppState } from "."
type StateVolunteer = { entity?: Volunteer } & StateRequest
export const initialState: StateVolunteer = {
readyStatus: "idle",
}
const volunteer = createSlice({
name: "volunteer",
initialState,
reducers: {
getRequesting: (_) => ({
readyStatus: "request",
}),
getSuccess: (_, { payload }: PayloadAction<Volunteer>) => ({
readyStatus: "success",
entity: payload,
}),
getFailure: (_, { payload }: PayloadAction<string>) => ({
readyStatus: "failure",
error: payload,
}),
},
})
export default volunteer.reducer
export const { getRequesting, getSuccess, getFailure } = volunteer.actions
export const fetchVolunteer = elementFetch(
volunteerGet,
getRequesting,
getSuccess,
getFailure,
(error: Error) => toastError(`Erreur lors du chargement d'un volunteer: ${error.message}`)
)
const shouldFetchVolunteer = (state: AppState, id: number) =>
state.volunteer.readyStatus !== "success" ||
(state.volunteer.entity && state.volunteer.entity.id !== id)
export const fetchVolunteerIfNeed =
(id: number): AppThunk =>
(dispatch, getState) => {
if (shouldFetchVolunteer(getState(), id)) return dispatch(fetchVolunteer(id))
return null
}

38
src/store/volunteerAdd.ts Normal file
View File

@ -0,0 +1,38 @@
import { PayloadAction, createSlice, createEntityAdapter } from "@reduxjs/toolkit"
import { StateRequest, toastError, toastSuccess, elementAddFetch } from "./utils"
import { Volunteer, volunteerAdd } from "../services/volunteers"
const volunteerAdapter = createEntityAdapter<Volunteer>()
const volunteerAddSlice = createSlice({
name: "addVolunteer",
initialState: volunteerAdapter.getInitialState({
readyStatus: "idle",
} as StateRequest),
reducers: {
getRequesting: (state) => {
state.readyStatus = "request"
},
getSuccess: (state, { payload }: PayloadAction<Volunteer>) => {
state.readyStatus = "success"
volunteerAdapter.addOne(state, payload)
},
getFailure: (state, { payload }: PayloadAction<string>) => {
state.readyStatus = "failure"
state.error = payload
},
},
})
export default volunteerAddSlice.reducer
export const { getRequesting, getSuccess, getFailure } = volunteerAddSlice.actions
export const fetchVolunteerAdd = elementAddFetch(
volunteerAdd,
getRequesting,
getSuccess,
getFailure,
(error: Error) => toastError(`Erreur lors de l'ajout d'une volunteer: ${error.message}`),
() => toastSuccess("Volunteer ajoutée !")
)

View File

@ -0,0 +1,48 @@
import { PayloadAction, createSlice, createEntityAdapter } from "@reduxjs/toolkit"
import { StateRequest, toastError, elementListFetch } from "./utils"
import { Volunteer, volunteerListGet } from "../services/volunteers"
import { AppThunk, AppState } from "."
const volunteerAdapter = createEntityAdapter<Volunteer>()
export const initialState = volunteerAdapter.getInitialState({
readyStatus: "idle",
} as StateRequest)
const volunteerList = createSlice({
name: "volunteerList",
initialState,
reducers: {
getRequesting: (state) => {
state.readyStatus = "request"
},
getSuccess: (state, { payload }: PayloadAction<Volunteer[]>) => {
state.readyStatus = "success"
volunteerAdapter.setAll(state, payload)
},
getFailure: (state, { payload }: PayloadAction<string>) => {
state.readyStatus = "failure"
state.error = payload
},
},
})
export default volunteerList.reducer
export const { getRequesting, getSuccess, getFailure } = volunteerList.actions
export const fetchVolunteerList = elementListFetch(
volunteerListGet,
getRequesting,
getSuccess,
getFailure,
(error: Error) => toastError(`Erreur lors du chargement des volunteers: ${error.message}`)
)
const shouldFetchVolunteerList = (state: AppState) => state.volunteerList.readyStatus !== "success"
export const fetchVolunteerListIfNeed = (): AppThunk => (dispatch, getState) => {
if (shouldFetchVolunteerList(getState())) return dispatch(fetchVolunteerList())
return null
}

View File

@ -1,22 +1,22 @@
import { PayloadAction, createSlice, createEntityAdapter } from "@reduxjs/toolkit" import { PayloadAction, createSlice, createEntityAdapter } from "@reduxjs/toolkit"
import { StateRequest, toastError, toastSuccess, elementSet } from "./utils" import { StateRequest, toastError, toastSuccess, elementSet } from "./utils"
import { Membre, membreSet } from "../services/membres" import { Volunteer, volunteerSet } from "../services/volunteers"
const membreAdapter = createEntityAdapter<Membre>() const volunteerAdapter = createEntityAdapter<Volunteer>()
const membreSetSlice = createSlice({ const volunteerSetSlice = createSlice({
name: "membreSet", name: "volunteerSet",
initialState: membreAdapter.getInitialState({ initialState: volunteerAdapter.getInitialState({
readyStatus: "idle", readyStatus: "idle",
} as StateRequest), } as StateRequest),
reducers: { reducers: {
getRequesting: (state) => { getRequesting: (state) => {
state.readyStatus = "request" state.readyStatus = "request"
}, },
getSuccess: (state, { payload }: PayloadAction<Membre>) => { getSuccess: (state, { payload }: PayloadAction<Volunteer>) => {
state.readyStatus = "success" state.readyStatus = "success"
membreAdapter.setOne(state, payload) volunteerAdapter.setOne(state, payload)
}, },
getFailure: (state, { payload }: PayloadAction<string>) => { getFailure: (state, { payload }: PayloadAction<string>) => {
state.readyStatus = "failure" state.readyStatus = "failure"
@ -25,14 +25,14 @@ const membreSetSlice = createSlice({
}, },
}) })
export default membreSetSlice.reducer export default volunteerSetSlice.reducer
export const { getRequesting, getSuccess, getFailure } = membreSetSlice.actions export const { getRequesting, getSuccess, getFailure } = volunteerSetSlice.actions
export const fetchMembreSet = elementSet( export const fetchVolunteerSet = elementSet(
membreSet, volunteerSet,
getRequesting, getRequesting,
getSuccess, getSuccess,
getFailure, getFailure,
(error: Error) => toastError(`Erreur lors de la modification d'un membre: ${error.message}`), (error: Error) => toastError(`Erreur lors de la modification d'un volunteer: ${error.message}`),
() => toastSuccess("Membre modifié !") () => toastSuccess("Volunteer modifié !")
) )

38
src/store/wishAdd.ts Normal file
View File

@ -0,0 +1,38 @@
import { PayloadAction, createSlice, createEntityAdapter } from "@reduxjs/toolkit"
import { StateRequest, toastError, toastSuccess, elementAddFetch } from "./utils"
import { Wish, wishAdd } from "../services/wishes"
const wishAdapter = createEntityAdapter<Wish>()
const wishAddSlice = createSlice({
name: "addWish",
initialState: wishAdapter.getInitialState({
readyStatus: "idle",
} as StateRequest),
reducers: {
getRequesting: (state) => {
state.readyStatus = "request"
},
getSuccess: (state, { payload }: PayloadAction<Wish>) => {
state.readyStatus = "success"
wishAdapter.addOne(state, payload)
},
getFailure: (state, { payload }: PayloadAction<string>) => {
state.readyStatus = "failure"
state.error = payload
},
},
})
export default wishAddSlice.reducer
export const { getRequesting, getSuccess, getFailure } = wishAddSlice.actions
export const fetchWishAdd = elementAddFetch(
wishAdd,
getRequesting,
getSuccess,
getFailure,
(error: Error) => toastError(`Erreur lors de l'ajout d'une wish: ${error.message}`),
() => toastSuccess("Wish ajoutée !")
)

46
src/store/wishList.ts Normal file
View File

@ -0,0 +1,46 @@
import { PayloadAction, createSlice, createEntityAdapter } from "@reduxjs/toolkit"
import { StateRequest, toastError, elementListFetch } from "./utils"
import { Wish, wishListGet } from "../services/wishes"
import { AppThunk, AppState } from "."
const wishAdapter = createEntityAdapter<Wish>()
const wishList = createSlice({
name: "getWishList",
initialState: wishAdapter.getInitialState({
readyStatus: "idle",
} as StateRequest),
reducers: {
getRequesting: (state) => {
state.readyStatus = "request"
},
getSuccess: (state, { payload }: PayloadAction<Wish[]>) => {
state.readyStatus = "success"
wishAdapter.setAll(state, payload)
},
getFailure: (state, { payload }: PayloadAction<string>) => {
state.readyStatus = "failure"
state.error = payload
},
},
})
export default wishList.reducer
export const { getRequesting, getSuccess, getFailure } = wishList.actions
export const fetchWishList = elementListFetch(
wishListGet,
getRequesting,
getSuccess,
getFailure,
(error: Error) => toastError(`Erreur lors du chargement des wishes: ${error.message}`)
)
const shouldFetchWishList = (state: AppState) => state.wishList.readyStatus !== "success"
export const fetchWishListIfNeed = (): AppThunk => (dispatch, getState) => {
if (shouldFetchWishList(getState())) return dispatch(fetchWishList())
return null
}