-
-
+
+
+
-
+
+
+
+ {sendingElement}
+ {sendSuccess}
+ {sendError}
diff --git a/src/components/RegisterForm/styles.module.scss b/src/components/RegisterForm/styles.module.scss
index ad6fd57..41736ad 100755
--- a/src/components/RegisterForm/styles.module.scss
+++ b/src/components/RegisterForm/styles.module.scss
@@ -16,6 +16,10 @@
}
}
+.lightTitle {
+ font-weight: normal;
+}
+
.formLine {
padding: 5px 0;
@@ -48,4 +52,25 @@
margin-top: 10px;
padding: 5px 0;
text-align: center;
+
+ [disabled="true"] {
+ background-color: #333333c0;
+ color: #cccccce7;
+ }
+}
+
+.formReactions {
+ margin-top: 3px;
+ padding: 5px 0;
+ text-align: center;
+
+ .sending {
+ color: rgb(0, 0, 255);
+ }
+ .success {
+ color: rgb(0, 133, 0);
+ }
+ .error {
+ color: rgb(255, 0, 0);
+ }
}
diff --git a/src/config/prod.ts b/src/config/prod.ts
index 1108dd1..555e14e 100755
--- a/src/config/prod.ts
+++ b/src/config/prod.ts
@@ -1,5 +1,7 @@
-const PORT = 4000
-const API_URL = __DEV__ || __LOCAL__ ? `http://localhost:${PORT}` : "https://fo.parisestludique.fr"
+const PROTOCOL = (typeof window !== "undefined" && window?.location?.protocol) || "http:"
+const PORT = 4000 + (PROTOCOL === "https:" ? 2 : 0)
+const API_URL =
+ __DEV__ || __LOCAL__ ? `${PROTOCOL}//localhost:${PORT}` : `${PROTOCOL}//fo.parisestludique.fr`
export default {
PORT,
diff --git a/src/pages/Home/__tests__/Home.tsx b/src/pages/Home/__tests__/Home.tsx
deleted file mode 100755
index 529b8d8..0000000
--- a/src/pages/Home/__tests__/Home.tsx
+++ /dev/null
@@ -1,79 +0,0 @@
-/**
- * @jest-environment jsdom
- */
-import { render } from "@testing-library/react"
-import { MemoryRouter } from "react-router-dom"
-
-import { fetchJeuJavListIfNeed } from "../../../store/jeuJavList"
-import mockStore from "../../../utils/mockStore"
-import Home from "../Home"
-
-describe("
", () => {
- const renderHelper = (reducer = { readyStatus: "idle" }) => {
- const { dispatch, ProviderWithStore } = mockStore({ jeuJavList: reducer })
- const { container } = render(
-
-
- {/*
- @ts-expect-error */}
-
-
-
- )
-
- return { dispatch, firstChild: container.firstChild }
- }
-
- it("should fetch data when page loaded", () => {
- const { dispatch } = renderHelper()
-
- expect(dispatch).toHaveBeenCalledTimes(1)
- expect(dispatch.mock.calls[0][0].toString()).toBe(fetchJeuJavListIfNeed().toString())
- })
-
- it("renders the loading status if data invalid", () => {
- expect(renderHelper().firstChild).toMatchSnapshot()
- })
-
- it("renders the loading status if requesting data", () => {
- const reducer = { readyStatus: "request" }
-
- expect(renderHelper(reducer).firstChild).toMatchSnapshot()
- })
-
- it("renders an error if loading failed", () => {
- const reducer = { readyStatus: "failure" }
-
- expect(renderHelper(reducer).firstChild).toMatchSnapshot()
- })
-
- it("renders the
if loading was successful", () => {
- const reducer = {
- readyStatus: "success",
- ids: [5],
- entities: {
- "5": {
- id: 5,
- titre: "6 qui prend!",
- auteur: "Wolfgang Kramer",
- editeur: "(uncredited) , Design Edge , B",
- minJoueurs: 2,
- maxJoueurs: 10,
- duree: 45,
- type: "Ambiance",
- poufpaf: "0-9-2/6-qui-prend-6-nimmt",
- photo: "https://cf.geekdo-images.com/thumb/img/lzczxR5cw7an7tRWeHdOrRtLyes=/fit-in/200x150/pic772547.jpg",
- bggPhoto: "",
- bggId: 432,
- exemplaires: 1,
- dispoPret: 1,
- nonRangee: 0,
- horodatage: "0000-00-00",
- ean: "3421272101313",
- },
- },
- }
-
- expect(renderHelper(reducer).firstChild).toMatchSnapshot()
- })
-})
diff --git a/src/pages/Home/__tests__/__snapshots__/Home.tsx.snap b/src/pages/Home/__tests__/__snapshots__/Home.tsx.snap
deleted file mode 100644
index 688463e..0000000
--- a/src/pages/Home/__tests__/__snapshots__/Home.tsx.snap
+++ /dev/null
@@ -1,313 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`
renders an error if loading failed 1`] = `
-
-
-
- Ajouter une nouvelle envie
-
-
-
-
- Oops, Failed to load list!
-
-
-`;
-
-exports[`
renders the
if loading was successful 1`] = `
-
-
-
-
- Jeux JAV
-
-
- -
- 6 qui prend!
- - [
- 432
- ]
-
-
-
-
-`;
-
-exports[`
renders the loading status if data invalid 1`] = `
-
-`;
-
-exports[`
renders the loading status if requesting data 1`] = `
-
-`;
diff --git a/src/pages/MembrePage/__tests__/MembrePage.tsx b/src/pages/MembrePage/__tests__/MembrePage.tsx
deleted file mode 100755
index 6853edd..0000000
--- a/src/pages/MembrePage/__tests__/MembrePage.tsx
+++ /dev/null
@@ -1,72 +0,0 @@
-/**
- * @jest-environment jsdom
- */
-import { render } from "@testing-library/react"
-import { MemoryRouter } from "react-router-dom"
-
-import { fetchMembreIfNeed } from "../../../store/membre"
-import mockStore from "../../../utils/mockStore"
-import MembrePage from "../MembrePage"
-
-describe("
", () => {
- const mockData = {
- id: 1,
- nom: "Aupeix",
- prenom: "Amélie",
- mail: "pakouille.lakouille@yahoo.fr",
- telephone: "0675650392",
- photo: "images/membres/$taille/amélie_aupeix.jpg",
- alimentation: "Végétarien",
- majeur: 1,
- privilege: 0,
- actif: 0,
- commentaire: "",
- horodatage: "0000-00-00",
- passe: "$2y$10$fSxY9AIuxSiEjwF.J3eXGubIxUPlobkyRrNIal8ASimSjNj4SR.9O",
- }
- const { id } = mockData
-
- const renderHelper = (reducer = {}) => {
- const { dispatch, ProviderWithStore } = mockStore({ membre: reducer })
- const { container } = render(
-
-
- {/*
- @ts-expect-error */}
-
-
-
- )
-
- return { dispatch, firstChild: container.firstChild }
- }
-
- it("should fetch data when page loaded", () => {
- const { dispatch } = renderHelper()
-
- expect(dispatch).toHaveBeenCalledTimes(1)
- expect(dispatch.mock.calls[0][0].toString()).toBe(fetchMembreIfNeed(id).toString())
- })
-
- it("renders the loading status if data invalid", () => {
- expect(renderHelper().firstChild).toMatchSnapshot()
- })
-
- it("renders the loading status if requesting data", () => {
- const reducer = { readyStatus: "request" }
-
- expect(renderHelper(reducer).firstChild).toMatchSnapshot()
- })
-
- it("renders an error if loading failed", () => {
- const reducer = { readyStatus: "failure" }
-
- expect(renderHelper(reducer).firstChild).toMatchSnapshot()
- })
-
- it("renders the
if loading was successful", () => {
- const reducer = { readyStatus: "success", entity: mockData }
-
- expect(renderHelper(reducer).firstChild).toMatchSnapshot()
- })
-})
diff --git a/src/pages/MembrePage/__tests__/__snapshots__/MembrePage.tsx.snap b/src/pages/MembrePage/__tests__/__snapshots__/MembrePage.tsx.snap
deleted file mode 100644
index 9b5121d..0000000
--- a/src/pages/MembrePage/__tests__/__snapshots__/MembrePage.tsx.snap
+++ /dev/null
@@ -1,104 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`
renders an error if loading failed 1`] = `
-
-
- Oops! Failed to load data.
-
-
-`;
-
-exports[`
renders the
if loading was successful 1`] = `
-
-
-
-
- Membre Info
-
-
- -
- Prénom:
- Amélie
-
- -
- Nom:
- Aupeix
-
-
-
-
-
-
-`;
-
-exports[`
renders the loading status if data invalid 1`] = `
-
-
- Oops! Failed to load data.
-
-
-`;
-
-exports[`
renders the loading status if requesting data 1`] = `
-
-`;
diff --git a/src/pages/Register/RegisterPage.tsx b/src/pages/Register/RegisterPage.tsx
index b6651b3..539917f 100644
--- a/src/pages/Register/RegisterPage.tsx
+++ b/src/pages/Register/RegisterPage.tsx
@@ -1,18 +1,22 @@
import { RouteComponentProps } from "react-router-dom"
-import React, { memo } from "react"
+import { useDispatch } from "react-redux"
+import { FC, memo } from "react"
import { Helmet } from "react-helmet"
import styles from "./styles.module.scss"
import RegisterForm from "../../components/RegisterForm/RegisterForm"
export type Props = RouteComponentProps
-const RegisterPage: React.FC
= (): JSX.Element => (
-
-
-
-
+const RegisterPage: FC
= (): JSX.Element => {
+ const dispatch = useDispatch()
+ return (
+
-
-)
+ )
+}
export default memo(RegisterPage)
diff --git a/src/routes/index.ts b/src/routes/index.ts
index 9663b56..c3e5d9f 100755
--- a/src/routes/index.ts
+++ b/src/routes/index.ts
@@ -13,6 +13,7 @@ export default [
routes: [
{
path: "/",
+ exact: true,
component: Register,
},
{
@@ -26,7 +27,6 @@ export default [
},
{
path: "/register",
- exact: true,
component: AsyncHome,
loadData: loadHomeData,
},
diff --git a/src/server/gsheets/accessors.ts b/src/server/gsheets/accessors.ts
index 5decfd6..1bb328d 100644
--- a/src/server/gsheets/accessors.ts
+++ b/src/server/gsheets/accessors.ts
@@ -13,7 +13,12 @@ export default function getAccessors<
// eslint-disable-next-line @typescript-eslint/ban-types
ElementNoId extends object,
Element extends ElementNoId & ElementWithId
->(sheetName: string, specimen: Element): any {
+>(sheetName: string, specimen: Element, translation: { [k in keyof Element]: string }): any {
+ const frenchSpecimen = _.mapValues(
+ _.invert(translation),
+ (englishProp: string) => (specimen as any)[englishProp]
+ ) as Element
+
const addDBOperation = DBManager(sheetName)
async function listGet(): Promise
{
@@ -27,10 +32,13 @@ export default function getAccessors<
if (!rows[0]) {
throw new Error(`No column types defined in sheet ${sheetName}`)
}
- const types = _.pick(rows[0], Object.keys(specimen)) as Record
+ const types = _.pick(rows[0], Object.values(translation)) as Record<
+ keyof Element,
+ string
+ >
rows.shift()
rows.forEach((row) => {
- const stringifiedElement = _.pick(row, Object.keys(specimen)) as Record<
+ const stringifiedElement = _.pick(row, Object.values(translation)) as Record<
keyof Element,
string
>
@@ -274,7 +282,7 @@ export default function getAccessors<
}
return element
},
- JSON.parse(JSON.stringify(specimen))
+ JSON.parse(JSON.stringify(frenchSpecimen))
)
return fullElement
}
@@ -365,7 +373,7 @@ export default function getAccessors<
return stringifiedElement
},
- JSON.parse(JSON.stringify(element))
+ JSON.parse(JSON.stringify(frenchSpecimen))
)
return rawElement
diff --git a/src/server/gsheets/envies.ts b/src/server/gsheets/envies.ts
index 25a21a2..edc9553 100644
--- a/src/server/gsheets/envies.ts
+++ b/src/server/gsheets/envies.ts
@@ -1,10 +1,10 @@
import getExpressAccessors from "./expressAccessors"
-import { Envie, EnvieWithoutId } from "../../services/envies"
+import { Envie, EnvieWithoutId, translationEnvie } from "../../services/envies"
const { listGetRequest, getRequest, setRequest, addRequest } = getExpressAccessors<
EnvieWithoutId,
Envie
->("Envies d'aider", new Envie())
+>("Envies d'aider", new Envie(), translationEnvie)
export const envieListGet = listGetRequest()
diff --git a/src/server/gsheets/expressAccessors.ts b/src/server/gsheets/expressAccessors.ts
index ae6d86c..36342b2 100644
--- a/src/server/gsheets/expressAccessors.ts
+++ b/src/server/gsheets/expressAccessors.ts
@@ -5,8 +5,8 @@ export default function getExpressAccessors<
// eslint-disable-next-line @typescript-eslint/ban-types
ElementNoId extends object,
Element extends ElementNoId & ElementWithId
->(sheetName: string, specimen: Element): any {
- const { get, listGet, add, set } = getAccessors(sheetName, specimen)
+>(sheetName: string, specimen: Element, translation: { [k in keyof Element]: string }): any {
+ const { get, listGet, add, set } = getAccessors(sheetName, specimen, translation)
function listGetRequest() {
return async (
diff --git a/src/server/gsheets/jeuJav.ts b/src/server/gsheets/jeuJav.ts
index 50a55dd..21e22da 100644
--- a/src/server/gsheets/jeuJav.ts
+++ b/src/server/gsheets/jeuJav.ts
@@ -1,10 +1,10 @@
import getExpressAccessors from "./expressAccessors"
-import { JeuJav, JeuJavWithoutId } from "../../services/jeuxJav"
+import { JeuJav, JeuJavWithoutId, translationJeuJav } from "../../services/jeuxJav"
const { listGetRequest, getRequest, setRequest, addRequest } = getExpressAccessors<
JeuJavWithoutId,
JeuJav
->("Jeux JAV", new JeuJav())
+>("Jeux JAV", new JeuJav(), translationJeuJav)
export const jeuJavListGet = listGetRequest()
diff --git a/src/server/gsheets/membres.ts b/src/server/gsheets/membres.ts
index 04a7919..01d3d8e 100644
--- a/src/server/gsheets/membres.ts
+++ b/src/server/gsheets/membres.ts
@@ -1,10 +1,10 @@
import getExpressAccessors from "./expressAccessors"
-import { Membre, MembreWithoutId } from "../../services/membres"
+import { Membre, MembreWithoutId, translationMember } from "../../services/membres"
const { listGetRequest, getRequest, setRequest, addRequest } = getExpressAccessors<
MembreWithoutId,
Membre
->("Membres", new Membre())
+>("Membres", new Membre(), translationMember)
export const membreListGet = listGetRequest()
diff --git a/src/server/gsheets/preMembers.ts b/src/server/gsheets/preMembers.ts
new file mode 100644
index 0000000..02d2a08
--- /dev/null
+++ b/src/server/gsheets/preMembers.ts
@@ -0,0 +1,15 @@
+import getExpressAccessors from "./expressAccessors"
+import { PreMember, PreMemberWithoutId, translationPreMember } from "../../services/preMembers"
+
+const { listGetRequest, getRequest, setRequest, addRequest } = getExpressAccessors<
+ PreMemberWithoutId,
+ PreMember
+>("PreMembres", new PreMember(), translationPreMember)
+
+export const preMemberListGet = listGetRequest()
+
+export const preMemberGet = getRequest()
+
+export const preMemberAdd = addRequest()
+
+export const preMemberSet = setRequest()
diff --git a/src/server/index.ts b/src/server/index.ts
index 581cf4c..0564706 100755
--- a/src/server/index.ts
+++ b/src/server/index.ts
@@ -18,6 +18,7 @@ import certbotRouter from "../routes/certbot"
import { secure } from "./secure"
import { jeuJavListGet } from "./gsheets/jeuJav"
import { envieListGet, envieAdd } from "./gsheets/envies"
+import { preMemberAdd } from "./gsheets/preMembers"
import { membreGet, membreSet } from "./gsheets/membres"
import loginHandler from "./userManagement/login"
import config from "../config"
@@ -56,6 +57,7 @@ app.post("/api/user/login", loginHandler)
app.get("/JeuJavListGet", jeuJavListGet)
app.get("/EnvieListGet", envieListGet)
app.post("/EnvieAdd", envieAdd)
+app.post("/PreMemberAdd", preMemberAdd)
// Secured APIs
app.get("/MembreGet", secure as RequestHandler, membreGet)
diff --git a/src/server/userManagement/__tests__/login.tsx b/src/server/userManagement/__tests__/login.tsx
index 1f67ed2..4c78758 100755
--- a/src/server/userManagement/__tests__/login.tsx
+++ b/src/server/userManagement/__tests__/login.tsx
@@ -10,9 +10,9 @@ import { login } from "../login"
// Full test with Bearer: wget --header='Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyIjoicGlraW91c3ViQGdlYWlsLmNvbSIsInBlcm1pc3Npb25zIjpbXSwiaWF0IjoxNjM4MjUzODgzLCJleHAiOjE2Mzg4NTg2ODN9.MknJ4NfcVlgW2ODeimfwZI1a4z8asdEXtHwHgViy6c4' http://localhost:3000/MembreGet?id=1
const mockUser = {
- mail: "my.email@gmail.com",
- passe: "$2y$10$cuKFHEow2IVSZSPtoVsw6uZFNFOOP/v1V7fubbyvrxhZdsnxLHr.2",
- prenom: "monPrénom",
+ email: "my.email@gmail.com",
+ password: "$2y$10$cuKFHEow2IVSZSPtoVsw6uZFNFOOP/v1V7fubbyvrxhZdsnxLHr.2",
+ firstname: "monPrénom",
}
jest.mock("../../gsheets/accessors", () => () => ({
@@ -24,7 +24,7 @@ describe("login with", () => {
const res = await login("my.email@gmail.com", "12345678")
expect(_.omit(res, "jwt")).toEqual({
membre: {
- prenom: mockUser.prenom,
+ firstname: mockUser.firstname,
},
})
expect(res.jwt).toBeDefined()
diff --git a/src/server/userManagement/login.ts b/src/server/userManagement/login.ts
index 3f4eda2..c50e741 100644
--- a/src/server/userManagement/login.ts
+++ b/src/server/userManagement/login.ts
@@ -1,10 +1,16 @@
import { Request, Response, NextFunction } from "express"
import bcrypt from "bcrypt"
-import { Membre, MemberLogin, emailRegexp, passwordMinLength } from "../../services/membres"
+import {
+ Membre,
+ MemberLogin,
+ emailRegexp,
+ passwordMinLength,
+ translationMember,
+} from "../../services/membres"
import getAccessors from "../gsheets/accessors"
import { getJwt } from "../secure"
-const { listGet } = getAccessors("Membres", new Membre())
+const { listGet } = getAccessors("Membres", new Membre(), translationMember)
export default async function loginHandler(
request: Request,
@@ -41,12 +47,12 @@ export async function login(rawEmail: string, rawPassword: string): Promise m.mail === email)
+ const membre = membres.find((m) => m.email === email)
if (!membre) {
throw Error("Cet email ne correspond à aucun utilisateur")
}
- const passwordMatch = await bcrypt.compare(password, membre.passe.replace(/^\$2y/, "$2a"))
+ const passwordMatch = await bcrypt.compare(password, membre.password.replace(/^\$2y/, "$2a"))
if (!passwordMatch) {
throw Error("Mauvais mot de passe pour cet email")
}
@@ -55,7 +61,7 @@ export async function login(rawEmail: string, rawPassword: string): Promise(elementName: string): (id: number) => Promise<{
+export type ElementTranslation = { [englishProp: string]: string }
+
+export function get(
+ elementName: string,
+ translation: ElementTranslation
+): (id: number) => Promise<{
data?: Element
error?: Error
}> {
@@ -19,14 +25,24 @@ export function get(elementName: string): (id: number) => Promise<{
...axiosConfig,
params: { id },
})
- return { data }
+ if (!data) {
+ return { data }
+ }
+ const englishData = _.mapValues(
+ translation,
+ (frenchProp: string) => data[frenchProp]
+ ) as Element
+ return { data: englishData }
} catch (error) {
return { error: error as Error }
}
}
}
-export function listGet(elementName: string): () => Promise<{
+export function listGet(
+ elementName: string,
+ translation: ElementTranslation
+): () => Promise<{
data?: Element[]
error?: Error
}> {
@@ -37,7 +53,18 @@ export function listGet(elementName: string): () => Promise<{
return async (): Promise => {
try {
const { data } = await axios.get(`${config.API_URL}/${elementName}ListGet`, axiosConfig)
- return { data }
+ if (!data) {
+ return { data }
+ }
+
+ const englishDataList = data.map(
+ (frenchData: any) =>
+ _.mapValues(
+ translation,
+ (frenchProp: string) => frenchData[frenchProp]
+ ) as Element
+ )
+ return { data: englishDataList }
} catch (error) {
return { error: error as Error }
}
@@ -46,7 +73,8 @@ export function listGet(elementName: string): () => Promise<{
// eslint-disable-next-line @typescript-eslint/ban-types
export function add(
- elementName: string
+ elementName: string,
+ translation: ElementTranslation
): (membreWithoutId: ElementNoId) => Promise<{
data?: Element
error?: Error
@@ -57,19 +85,36 @@ export function add => {
try {
+ const invertedTranslationWithoutId = _.invert(_.omit(translation, "id"))
+ const frenchDataWithoutId = _.mapValues(
+ invertedTranslationWithoutId,
+ (englishProp: string, _frenchProp: string) => (membreWithoutId as any)[englishProp]
+ )
+
const { data } = await axios.post(
`${config.API_URL}/${elementName}Add`,
- membreWithoutId,
+ frenchDataWithoutId,
axiosConfig
)
- return { data }
+ if (!data) {
+ return { data }
+ }
+
+ const englishData = _.mapValues(
+ translation,
+ (frenchProp: string) => data[frenchProp]
+ ) as Element
+ return { data: englishData }
} catch (error) {
return { error: error as Error }
}
}
}
-export function set(elementName: string): (membre: Element) => Promise<{
+export function set(
+ elementName: string,
+ translation: ElementTranslation
+): (membre: Element) => Promise<{
data?: Element
error?: Error
}> {
@@ -79,12 +124,26 @@ export function set(elementName: string): (membre: Element) => Promise<
}
return async (membre: Element): Promise => {
try {
+ const invertedTranslation = _.invert(translation)
+ const frenchData = _.mapValues(
+ invertedTranslation,
+ (englishProp: string) => (membre as any)[englishProp]
+ )
+
const { data } = await axios.post(
`${config.API_URL}/${elementName}Set`,
- membre,
+ frenchData,
axiosConfig
)
- return { data }
+ if (!data) {
+ return { data }
+ }
+
+ const englishData = _.mapValues(
+ translation,
+ (frenchProp: string) => data[frenchProp]
+ ) as Element
+ return { data: englishData }
} catch (error) {
return { error: error as Error }
}
diff --git a/src/services/envies.ts b/src/services/envies.ts
index 69a9579..95a3c6c 100644
--- a/src/services/envies.ts
+++ b/src/services/envies.ts
@@ -3,23 +3,34 @@ import { get, listGet, add, set } from "./accessors"
export class Envie {
id = 0
- domaine = ""
+ domain = ""
- envies = ""
+ wish = ""
- precisions = ""
+ details = ""
- equipes: string[] = []
+ teams: string[] = []
- dateAjout = ""
+ 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
-export const envieGet = get("Envie")
+export const envieGet = get(elementName, translationEnvie)
-export const envieListGet = listGet("Envie")
+export const envieListGet = listGet(elementName, translationEnvie)
-export const envieAdd = add("Envie")
+export const envieAdd = add(elementName, translationEnvie)
-export const envieSet = set("Envie")
+export const envieSet = set(elementName, translationEnvie)
diff --git a/src/services/jeuxJav.ts b/src/services/jeuxJav.ts
index 0c9e118..4cde5cf 100644
--- a/src/services/jeuxJav.ts
+++ b/src/services/jeuxJav.ts
@@ -3,17 +3,17 @@ import { get, listGet, add, set } from "./accessors"
export class JeuJav {
id = 0
- titre = ""
+ title = ""
- auteur = ""
+ author = ""
- editeur = ""
+ editor = ""
- minJoueurs = 0
+ playersMin = 0
- maxJoueurs = 0
+ playersMax = 0
- duree = 0
+ duration = 0
type: "Ambiance" | "Famille" | "Expert" | "" = ""
@@ -21,23 +21,43 @@ export class JeuJav {
bggId = 0
- exemplaires = 1
+ copies = 1
- dispoPret = 0
+ lendAvailability = 0
- nonRangee = 0
+ notStored = 0
ean = ""
bggPhoto = ""
}
+export const translationJeuJav: { [k in keyof JeuJav]: string } = {
+ id: "id",
+ title: "titre",
+ author: "auteur",
+ editor: "editeur",
+ playersMin: "minJoueurs",
+ playersMax: "maxJoueurs",
+ duration: "duree",
+ type: "type",
+ poufpaf: "poufpaf",
+ bggId: "bggId",
+ copies: "exemplaires",
+ lendAvailability: "dispoPret",
+ notStored: "nonRangee",
+ ean: "ean",
+ bggPhoto: "bggPhoto",
+}
+
+const elementName = "JeuJav"
+
export type JeuJavWithoutId = Omit
-export const jeuJavGet = get("JeuJav")
+export const jeuJavGet = get(elementName, translationJeuJav)
-export const jeuJavListGet = listGet("JeuJav")
+export const jeuJavListGet = listGet(elementName, translationJeuJav)
-export const jeuJavAdd = add("JeuJav")
+export const jeuJavAdd = add(elementName, translationJeuJav)
-export const jeuJavSet = set("JeuJav")
+export const jeuJavSet = set(elementName, translationJeuJav)
diff --git a/src/services/membres.ts b/src/services/membres.ts
index d15a21c..0590595 100644
--- a/src/services/membres.ts
+++ b/src/services/membres.ts
@@ -3,38 +3,56 @@ import { get, listGet, add, set } from "./accessors"
export class Membre {
id = 0
- nom = ""
+ lastname = ""
- prenom = ""
+ firstname = ""
- mail = ""
+ email = ""
- telephone = ""
+ mobile = ""
photo = ""
- alimentation = ""
+ food = ""
- majeur = 1
+ adult = 1
- privilege = 0
+ privileges = 0
- actif = 0
+ active = 0
- commentaire = ""
+ comment = ""
- horodatage = ""
+ timestamp = ""
- passe = ""
+ password = ""
}
+export const translationMember: { [k in keyof Membre]: string } = {
+ id: "id",
+ lastname: "nom",
+ firstname: "prenom",
+ email: "mail",
+ mobile: "telephone",
+ photo: "photo",
+ food: "alimentation",
+ adult: "majeur",
+ privileges: "privilege",
+ active: "actif",
+ comment: "commentaire",
+ timestamp: "horodatage",
+ password: "passe",
+}
+
+const elementName = "Membre"
+
export const emailRegexp =
/^(([^<>()[\].,;:\s@"]+(\.[^<>()[\].,;:\s@"]+)*)|(".+"))@(([^<>()[\].,;:\s@"]+\.)+[^<>()[\].,;:\s@"]{2,})$/i
export const passwordMinLength = 4
export interface MemberLogin {
membre?: {
- prenom: string
+ firstname: string
}
jwt?: string
error?: string
@@ -42,10 +60,10 @@ export interface MemberLogin {
export type MembreWithoutId = Omit
-export const membreGet = get("Membre")
+export const membreGet = get(elementName, translationMember)
-export const membreListGet = listGet("Membre")
+export const membreListGet = listGet(elementName, translationMember)
-export const membreAdd = add("Membre")
+export const membreAdd = add(elementName, translationMember)
-export const membreSet = set("Membre")
+export const membreSet = set(elementName, translationMember)
diff --git a/src/services/preMembers.ts b/src/services/preMembers.ts
new file mode 100644
index 0000000..38944af
--- /dev/null
+++ b/src/services/preMembers.ts
@@ -0,0 +1,39 @@
+import { get, listGet, add, set } from "./accessors"
+
+export class PreMember {
+ id = 0
+
+ firstname = ""
+
+ lastname = ""
+
+ email = ""
+
+ mobile = ""
+
+ alreadyVolunteer = false
+
+ comment = ""
+}
+
+export const translationPreMember: { [k in keyof PreMember]: string } = {
+ id: "id",
+ firstname: "prenom",
+ lastname: "nom",
+ email: "email",
+ mobile: "telephone",
+ alreadyVolunteer: "dejaBenevole",
+ comment: "commentaire",
+}
+
+const elementName = "PreMember"
+
+export type PreMemberWithoutId = Omit
+
+export const preMemberGet = get(elementName, translationPreMember)
+
+export const preMemberListGet = listGet(elementName, translationPreMember)
+
+export const preMemberAdd = add(elementName, translationPreMember)
+
+export const preMemberSet = set(elementName, translationPreMember)
diff --git a/src/store/__tests__/jeuJavList.ts b/src/store/__tests__/jeuJavList.ts
index 0f4159c..28604f2 100644
--- a/src/store/__tests__/jeuJavList.ts
+++ b/src/store/__tests__/jeuJavList.ts
@@ -1,4 +1,5 @@
import axios from "axios"
+import _ from "lodash"
import mockStore from "../../utils/mockStore"
import JeuJavList, {
@@ -8,11 +9,12 @@ import JeuJavList, {
getFailure,
fetchJeuJavList,
} from "../jeuJavList"
+import { JeuJav } from "../../services/jeuxJav"
jest.mock("axios")
-const mockData = {
- "5": {
+const mockFrenchData: any[] = [
+ {
id: 5,
titre: "6 qui prend!",
auteur: "Wolfgang Kramer",
@@ -22,16 +24,35 @@ const mockData = {
duree: 45,
type: "Ambiance",
poufpaf: "0-9-2/6-qui-prend-6-nimmt",
- photo: "https://cf.geekdo-images.com/thumb/img/lzczxR5cw7an7tRWeHdOrRtLyes=/fit-in/200x150/pic772547.jpg",
- bggPhoto: "",
+ bggPhoto:
+ "https://cf.geekdo-images.com/thumb/img/lzczxR5cw7an7tRWeHdOrRtLyes=/fit-in/200x150/pic772547.jpg",
bggId: 432,
exemplaires: 1,
dispoPret: 1,
nonRangee: 0,
- horodatage: "0000-00-00",
ean: "3421272101313",
},
-}
+]
+const mockEnglishData: JeuJav[] = [
+ {
+ id: 5,
+ title: "6 qui prend!",
+ author: "Wolfgang Kramer",
+ editor: "(uncredited) , Design Edge , B",
+ playersMin: 2,
+ playersMax: 10,
+ duration: 45,
+ type: "Ambiance",
+ poufpaf: "0-9-2/6-qui-prend-6-nimmt",
+ bggPhoto:
+ "https://cf.geekdo-images.com/thumb/img/lzczxR5cw7an7tRWeHdOrRtLyes=/fit-in/200x150/pic772547.jpg",
+ bggId: 432,
+ copies: 1,
+ lendAvailability: 1,
+ notStored: 0,
+ ean: "3421272101313",
+ },
+]
const mockError = "Oops! Something went wrong."
describe("JeuJavList reducer", () => {
@@ -49,11 +70,11 @@ describe("JeuJavList reducer", () => {
})
it("should handle success correctly", () => {
- expect(JeuJavList(undefined, { type: getSuccess.type, payload: mockData })).toEqual({
+ expect(JeuJavList(undefined, { type: getSuccess.type, payload: mockEnglishData })).toEqual({
...initialState,
readyStatus: "success",
- ids: [5],
- entities: mockData,
+ ids: _.map(mockEnglishData, "id"),
+ entities: _.keyBy(mockEnglishData, "id"),
})
})
@@ -70,12 +91,12 @@ describe("JeuJavList action", () => {
it("fetches JeuJav list successful", async () => {
const { dispatch, getActions } = mockStore()
const expectedActions = [
- { type: getRequesting.type },
- { type: getSuccess.type, payload: mockData },
+ { type: getRequesting.type, payload: undefined },
+ { type: getSuccess.type, payload: mockEnglishData },
]
// @ts-expect-error
- axios.get.mockResolvedValue({ data: mockData })
+ axios.get.mockResolvedValue({ data: mockFrenchData })
await dispatch(fetchJeuJavList())
expect(getActions()).toEqual(expectedActions)
diff --git a/src/store/__tests__/membre.ts b/src/store/__tests__/membre.ts
index a6600e1..8a99ac9 100644
--- a/src/store/__tests__/membre.ts
+++ b/src/store/__tests__/membre.ts
@@ -2,10 +2,11 @@ import axios from "axios"
import mockStore from "../../utils/mockStore"
import membre, { getRequesting, getSuccess, getFailure, fetchMembre, initialState } from "../membre"
+import { Membre } from "../../services/membres"
jest.mock("axios")
-const mockData = {
+const mockFrenchData: any = {
id: 1,
nom: "Aupeix",
prenom: "Amélie",
@@ -20,7 +21,23 @@ const mockData = {
horodatage: "0000-00-00",
passe: "$2y$10$fSxY9AIuxSiEjwF.J3eXGubIxUPlobkyRrNIal8ASimSjNj4SR.9O",
}
-const { id } = mockData
+
+const mockEnglishData: Membre = {
+ id: 1,
+ lastname: "Aupeix",
+ firstname: "Amélie",
+ email: "pakouille.lakouille@yahoo.fr",
+ mobile: "0675650392",
+ photo: "images/membres/$taille/amélie_aupeix.jpg",
+ food: "Végétarien",
+ adult: 1,
+ privileges: 0,
+ active: 0,
+ comment: "",
+ timestamp: "0000-00-00",
+ password: "$2y$10$fSxY9AIuxSiEjwF.J3eXGubIxUPlobkyRrNIal8ASimSjNj4SR.9O",
+}
+const { id } = mockEnglishData
const mockError = "Oops! Something went wrong."
describe("membre reducer", () => {
@@ -39,9 +56,9 @@ describe("membre reducer", () => {
expect(
membre(undefined, {
type: getSuccess.type,
- payload: mockData,
+ payload: mockEnglishData,
})
- ).toEqual({ readyStatus: "success", entity: mockData })
+ ).toEqual({ readyStatus: "success", entity: mockEnglishData })
})
it("should handle failure correctly", () => {
@@ -58,12 +75,12 @@ describe("membre action", () => {
it("fetches membre data successful", async () => {
const { dispatch, getActions } = mockStore()
const expectedActions = [
- { type: getRequesting.type },
- { type: getSuccess.type, payload: mockData },
+ { type: getRequesting.type, payload: undefined },
+ { type: getSuccess.type, payload: mockEnglishData },
]
// @ts-expect-error
- axios.get.mockResolvedValue({ data: mockData })
+ axios.get.mockResolvedValue({ data: mockFrenchData })
await dispatch(fetchMembre(id))
expect(getActions()).toEqual(expectedActions)
diff --git a/src/store/__tests__/membreList.ts b/src/store/__tests__/membreList.ts
index 64bea3c..2d1d5fe 100644
--- a/src/store/__tests__/membreList.ts
+++ b/src/store/__tests__/membreList.ts
@@ -1,4 +1,5 @@
import axios from "axios"
+import _ from "lodash"
import mockStore from "../../utils/mockStore"
import membreList, {
@@ -8,11 +9,12 @@ import membreList, {
getFailure,
fetchMembreList,
} from "../membreList"
+import { Membre } from "../../services/membres"
jest.mock("axios")
-const mockData = {
- "1": {
+const mockFrenchData: any[] = [
+ {
id: 1,
nom: "Aupeix",
prenom: "Amélie",
@@ -27,7 +29,25 @@ const mockData = {
horodatage: "0000-00-00",
passe: "$2y$10$fSxY9AIuxSiEjwF.J3eXGubIxUPlobkyRrNIal8ASimSjNj4SR.9O",
},
-}
+]
+
+const mockEnglishData: Membre[] = [
+ {
+ id: 1,
+ lastname: "Aupeix",
+ firstname: "Amélie",
+ email: "pakouille.lakouille@yahoo.fr",
+ mobile: "0675650392",
+ photo: "images/membres/$taille/amélie_aupeix.jpg",
+ food: "Végétarien",
+ adult: 1,
+ privileges: 0,
+ active: 0,
+ comment: "",
+ timestamp: "0000-00-00",
+ password: "$2y$10$fSxY9AIuxSiEjwF.J3eXGubIxUPlobkyRrNIal8ASimSjNj4SR.9O",
+ },
+]
const mockError = "Oops! Something went wrong."
describe("membreList reducer", () => {
@@ -45,11 +65,11 @@ describe("membreList reducer", () => {
})
it("should handle success correctly", () => {
- expect(membreList(undefined, { type: getSuccess.type, payload: mockData })).toEqual({
+ expect(membreList(undefined, { type: getSuccess.type, payload: mockEnglishData })).toEqual({
...initialState,
readyStatus: "success",
- ids: [1],
- entities: mockData,
+ ids: _.map(mockEnglishData, "id"),
+ entities: _.keyBy(mockEnglishData, "id"),
})
})
@@ -66,12 +86,12 @@ describe("membreList action", () => {
it("fetches membre list successful", async () => {
const { dispatch, getActions } = mockStore()
const expectedActions = [
- { type: getRequesting.type },
- { type: getSuccess.type, payload: mockData },
+ { type: getRequesting.type, payload: undefined },
+ { type: getSuccess.type, payload: mockEnglishData },
]
// @ts-expect-error
- axios.get.mockResolvedValue({ data: mockData })
+ axios.get.mockResolvedValue({ data: mockFrenchData })
await dispatch(fetchMembreList())
expect(getActions()).toEqual(expectedActions)
diff --git a/src/store/preMemberAdd.ts b/src/store/preMemberAdd.ts
new file mode 100644
index 0000000..f085cd0
--- /dev/null
+++ b/src/store/preMemberAdd.ts
@@ -0,0 +1,38 @@
+import { PayloadAction, createSlice, createEntityAdapter } from "@reduxjs/toolkit"
+
+import { StateRequest, elementAddFetch } from "./utils"
+import { PreMember, preMemberAdd } from "../services/preMembers"
+
+const preMemberAdapter = createEntityAdapter()
+
+const preMemberAddSlice = createSlice({
+ name: "addPreMember",
+ initialState: preMemberAdapter.getInitialState({
+ readyStatus: "idle",
+ } as StateRequest),
+ reducers: {
+ getRequesting: (state) => {
+ state.readyStatus = "request"
+ },
+ getSuccess: (state, { payload }: PayloadAction) => {
+ state.readyStatus = "success"
+ preMemberAdapter.addOne(state, payload)
+ },
+ getFailure: (state, { payload }: PayloadAction) => {
+ state.readyStatus = "failure"
+ state.error = payload
+ },
+ },
+})
+
+export default preMemberAddSlice.reducer
+export const { getRequesting, getSuccess, getFailure } = preMemberAddSlice.actions
+
+export const fetchPreMemberAdd = elementAddFetch(
+ preMemberAdd,
+ getRequesting,
+ getSuccess,
+ getFailure,
+ () => null,
+ () => null
+)
diff --git a/src/store/rootReducer.ts b/src/store/rootReducer.ts
index 795f428..22cbcbc 100644
--- a/src/store/rootReducer.ts
+++ b/src/store/rootReducer.ts
@@ -8,6 +8,7 @@ import membre from "./membre"
import membreAdd from "./membreAdd"
import membreList from "./membreList"
import membreSet from "./membreSet"
+import preMemberAdd from "./preMemberAdd"
// Use inferred return type for making correctly Redux types
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
@@ -19,6 +20,7 @@ export default (history: History) => ({
membreAdd,
membreList,
membreSet,
+ preMemberAdd,
router: connectRouter(history) as any,
// Register more reducers...
})
diff --git a/src/store/utils.ts b/src/store/utils.ts
index 7ba6f82..4de6241 100644
--- a/src/store/utils.ts
+++ b/src/store/utils.ts
@@ -23,7 +23,7 @@ export function toastError(message: string): void {
export function toastSuccess(message: string): void {
toast.success(message, {
position: "top-center",
- autoClose: 3000,
+ autoClose: 5000,
hideProgressBar: true,
closeOnClick: true,
pauseOnHover: true,
diff --git a/webpack/server.config.ts b/webpack/server.config.ts
index 06c04ab..cea8955 100644
--- a/webpack/server.config.ts
+++ b/webpack/server.config.ts
@@ -31,6 +31,7 @@ const config: Configuration = {
}),
new webpack.DefinePlugin({
localStorage: { getItem: () => null, setItem: () => null, removeItem: () => null },
+ "location.protocol": "http:",
}),
],
}