diff --git a/gsheetsTest.ts b/gsheetsTest.ts index a7d6917..a6c1362 100644 --- a/gsheetsTest.ts +++ b/gsheetsTest.ts @@ -313,7 +313,7 @@ function formulaSafe(value: string): string { export { SCOPES } class Test { - envieId = 5 + id = 5 envies = "" @@ -348,7 +348,7 @@ class Test { async function testGSheetAPi(): Promise { const dataset: Test[] = [ { - envieId: 1, + id: 1, envies: "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"), ignore: true, @@ -362,7 +362,7 @@ async function testGSheetAPi(): Promise { tictactoe: [true, false, true, false, false, true], }, { - envieId: 5, + id: 5, envies: "Créer de jolies pages webs", dateAjout: new Date("2021-10-18T22:00:00.000Z"), ignore: false, @@ -372,7 +372,7 @@ async function testGSheetAPi(): Promise { tictactoe: [], }, { - envieId: 6, + id: 6, envies: "Modérer un salon Discord", dateAjout: new Date("2021-10-18T22:00:00.000Z"), ignore: true, diff --git a/src/components/Info/__tests__/Info.tsx b/src/components/Info/__tests__/Info.tsx deleted file mode 100755 index cf7d6df..0000000 --- a/src/components/Info/__tests__/Info.tsx +++ /dev/null @@ -1,27 +0,0 @@ -/** - * @jest-environment jsdom - */ -import { render } from "@testing-library/react" -import { MemoryRouter } from "react-router-dom" - -import Info from "../index" - -describe("", () => { - it("renders", () => { - const tree = render( - - - - ).container.firstChild - - expect(tree).toMatchSnapshot() - }) -}) diff --git a/src/components/Info/__tests__/__snapshots__/Info.tsx.snap b/src/components/Info/__tests__/__snapshots__/Info.tsx.snap deleted file mode 100644 index 2f68eb7..0000000 --- a/src/components/Info/__tests__/__snapshots__/Info.tsx.snap +++ /dev/null @@ -1,29 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[` renders 1`] = ` -
-

- User Info -

-
    -
  • - Name: - PeL -
  • -
  • - Phone: - +886 0970... -
  • -
  • - Email: - forceoranj@gmail.com -
  • -
  • - Website: - https://www.parisestludique.fr -
  • -
-
-`; diff --git a/src/components/Info/index.tsx b/src/components/Info/index.tsx deleted file mode 100755 index 5414c32..0000000 --- a/src/components/Info/index.tsx +++ /dev/null @@ -1,22 +0,0 @@ -import { memo } from "react" - -import { User } from "../../services/jsonPlaceholder" -import styles from "./styles.module.scss" - -interface Props { - item: User -} - -const Info = ({ item }: Props) => ( -
-

User Info

-
    -
  • Name: {item.name}
  • -
  • Phone: {item.phone}
  • -
  • Email: {item.email}
  • -
  • Website: {item.website}
  • -
-
-) - -export default memo(Info) diff --git a/src/components/JeuJavList/__tests__/JeuJavList.tsx b/src/components/JeuJavList/__tests__/JeuJavList.tsx index 01fdedd..d7d4fd8 100644 --- a/src/components/JeuJavList/__tests__/JeuJavList.tsx +++ b/src/components/JeuJavList/__tests__/JeuJavList.tsx @@ -5,7 +5,7 @@ import { render } from "@testing-library/react" import { MemoryRouter } from "react-router-dom" import mockStore from "../../../utils/mockStore" -import List from "../index" +import JeuJavList from "../index" describe("", () => { const renderHelper = (reducer = { readyStatus: "idle" }) => { @@ -13,7 +13,7 @@ describe("", () => { const { container } = render( - + ) diff --git a/src/components/JeuJavList/index.tsx b/src/components/JeuJavList/index.tsx index 5dddc83..0c7e034 100644 --- a/src/components/JeuJavList/index.tsx +++ b/src/components/JeuJavList/index.tsx @@ -10,7 +10,7 @@ interface Props { ids: EntityId[] } -const List = ({ ids }: Props) => { +const JeuJavList = ({ ids }: Props) => { const { entities: jeuxJav } = useSelector((state: AppState) => state.jeuJavList, shallowEqual) return (
@@ -33,4 +33,4 @@ const List = ({ ids }: Props) => { ) } -export default memo(List) +export default memo(JeuJavList) diff --git a/src/components/List/__tests__/List.tsx b/src/components/List/__tests__/List.tsx deleted file mode 100755 index cdac75e..0000000 --- a/src/components/List/__tests__/List.tsx +++ /dev/null @@ -1,29 +0,0 @@ -/** - * @jest-environment jsdom - */ -import { render } from "@testing-library/react" -import { MemoryRouter } from "react-router-dom" - -import List from "../index" - -describe("", () => { - it("renders", () => { - const tree = render( - - - - ).container.firstChild - - expect(tree).toMatchSnapshot() - }) -}) diff --git a/src/components/List/__tests__/__snapshots__/List.tsx.snap b/src/components/List/__tests__/__snapshots__/List.tsx.snap deleted file mode 100644 index 1b0d049..0000000 --- a/src/components/List/__tests__/__snapshots__/List.tsx.snap +++ /dev/null @@ -1,20 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[` renders 1`] = ` -
-

- User List -

- -
-`; diff --git a/src/components/List/index.tsx b/src/components/List/index.tsx deleted file mode 100755 index 2d557f1..0000000 --- a/src/components/List/index.tsx +++ /dev/null @@ -1,24 +0,0 @@ -import { memo } from "react" -import { Link } from "react-router-dom" - -import { User } from "../../services/jsonPlaceholder" -import styles from "./styles.module.scss" - -interface Props { - items: User[] -} - -const List = ({ items }: Props) => ( -
-

User List

-
    - {items.map(({ membreId, name }) => ( -
  • - {name} -
  • - ))} -
-
-) - -export default memo(List) diff --git a/src/components/MembreInfo/__tests__/MembreInfo.tsx b/src/components/MembreInfo/__tests__/MembreInfo.tsx new file mode 100755 index 0000000..95175a8 --- /dev/null +++ b/src/components/MembreInfo/__tests__/MembreInfo.tsx @@ -0,0 +1,35 @@ +/** + * @jest-environment jsdom + */ +import { render } from "@testing-library/react" +import { MemoryRouter } from "react-router-dom" + +import MembreInfo from "../index" + +describe("", () => { + it("renders", () => { + const tree = render( + + + + ).container.firstChild + + expect(tree).toMatchSnapshot() + }) +}) diff --git a/src/components/MembreInfo/__tests__/__snapshots__/MembreInfo.tsx.snap b/src/components/MembreInfo/__tests__/__snapshots__/MembreInfo.tsx.snap new file mode 100644 index 0000000..21bcad2 --- /dev/null +++ b/src/components/MembreInfo/__tests__/__snapshots__/MembreInfo.tsx.snap @@ -0,0 +1,21 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[` renders 1`] = ` +
+

+ Membre Info +

+
    +
  • + Prénom: + Amélie +
  • +
  • + Nom: + Aupeix +
  • +
+
+`; diff --git a/src/components/MembreInfo/index.tsx b/src/components/MembreInfo/index.tsx new file mode 100755 index 0000000..77fc51c --- /dev/null +++ b/src/components/MembreInfo/index.tsx @@ -0,0 +1,20 @@ +import { memo } from "react" + +import { Membre } from "../../services/membres" +import styles from "./styles.module.scss" + +interface Props { + item: Membre +} + +const MembreInfo = ({ item }: Props) => ( +
+

Membre Info

+
    +
  • Prénom: {item.prenom}
  • +
  • Nom: {item.nom}
  • +
+
+) + +export default memo(MembreInfo) diff --git a/src/components/Info/styles.module.scss b/src/components/MembreInfo/styles.module.scss similarity index 87% rename from src/components/Info/styles.module.scss rename to src/components/MembreInfo/styles.module.scss index 7394dff..d3a8829 100755 --- a/src/components/Info/styles.module.scss +++ b/src/components/MembreInfo/styles.module.scss @@ -1,4 +1,4 @@ -.user-card { +.membre-card { ul { padding-left: 17px; diff --git a/src/components/MembreList/__tests__/MembreList.tsx b/src/components/MembreList/__tests__/MembreList.tsx new file mode 100755 index 0000000..ad4db98 --- /dev/null +++ b/src/components/MembreList/__tests__/MembreList.tsx @@ -0,0 +1,37 @@ +/** + * @jest-environment jsdom + */ +import { render } from "@testing-library/react" +import { MemoryRouter } from "react-router-dom" + +import MembreList from "../index" + +describe("", () => { + it("renders", () => { + const tree = render( + + + + ).container.firstChild + + expect(tree).toMatchSnapshot() + }) +}) diff --git a/src/components/MembreList/__tests__/__snapshots__/MembreList.tsx.snap b/src/components/MembreList/__tests__/__snapshots__/MembreList.tsx.snap new file mode 100644 index 0000000..20010c7 --- /dev/null +++ b/src/components/MembreList/__tests__/__snapshots__/MembreList.tsx.snap @@ -0,0 +1,24 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[` renders 1`] = ` +
+

+ Membre List +

+ +
+`; diff --git a/src/components/MembreList/index.tsx b/src/components/MembreList/index.tsx new file mode 100755 index 0000000..ab6376a --- /dev/null +++ b/src/components/MembreList/index.tsx @@ -0,0 +1,26 @@ +import { memo } from "react" +import { Link } from "react-router-dom" + +import { Membre } from "../../services/membres" +import styles from "./styles.module.scss" + +interface Props { + items: Membre[] +} + +const MembreList = ({ items }: Props) => ( +
+

Membre List

+
    + {items.map(({ id, nom, prenom }) => ( +
  • + + {prenom} {nom} + +
  • + ))} +
+
+) + +export default memo(MembreList) diff --git a/src/components/List/styles.module.scss b/src/components/MembreList/styles.module.scss similarity index 100% rename from src/components/List/styles.module.scss rename to src/components/MembreList/styles.module.scss diff --git a/src/components/index.ts b/src/components/index.ts index c28f862..5696608 100755 --- a/src/components/index.ts +++ b/src/components/index.ts @@ -1,8 +1,8 @@ -import List from "./List" +import MembreList from "./MembreList" import JeuJavList from "./JeuJavList" -import Info from "./Info" +import MembreInfo from "./MembreInfo" import ErrorBoundary from "./ErrorBoundary" import Loading from "./Loading" import AddEnvie from "./AddEnvie" -export { List, JeuJavList, Info, ErrorBoundary, Loading, AddEnvie } +export { MembreList, JeuJavList, MembreInfo, ErrorBoundary, Loading, AddEnvie } diff --git a/src/gsheets/envies.ts b/src/gsheets/envies.ts index dbe7c13..dcf21ee 100644 --- a/src/gsheets/envies.ts +++ b/src/gsheets/envies.ts @@ -23,7 +23,7 @@ export const addEnvie = async ( _next: NextFunction ): Promise => { try { - const envie = await add("Envies d'aider", "envieId", request.body) + const envie = await add("Envies d'aider", "id", request.body) if (envie) { response.status(200).json(envie) } diff --git a/src/gsheets/membres.ts b/src/gsheets/membres.ts new file mode 100644 index 0000000..2257db2 --- /dev/null +++ b/src/gsheets/membres.ts @@ -0,0 +1,47 @@ +import { Request, Response, NextFunction } from "express" +import { getList, get, add } from "./utils" +import { Membre, MembreWithoutId } from "../services/membres" + +export const getMembreList = async ( + _request: Request, + response: Response, + _next: NextFunction +): Promise => { + try { + const list = await getList("Membres", new Membre()) + if (list) { + response.status(200).json(list) + } + } catch (e: unknown) { + response.status(400).json(e) + } +} + +export const getMembre = async ( + request: Request, + response: Response, + _next: NextFunction +): Promise => { + try { + const id = parseInt(request.query.id as string, 10) || -1 + const membre = await get("Membres", id, new Membre()) + response.status(200).json(membre) + } catch (e: unknown) { + response.status(400).json(e) + } +} + +export const addMembre = async ( + request: Request, + response: Response, + _next: NextFunction +): Promise => { + try { + const membre = await add("Membres", "membreId", request.body) + if (membre) { + response.status(200).json(membre) + } + } catch (e: unknown) { + response.status(400).json(e) + } +} diff --git a/src/gsheets/utils.ts b/src/gsheets/utils.ts index 7227be4..be3f60b 100644 --- a/src/gsheets/utils.ts +++ b/src/gsheets/utils.ts @@ -6,8 +6,10 @@ import { GoogleSpreadsheet, GoogleSpreadsheetWorksheet } from "google-spreadshee const SCOPES = ["https://www.googleapis.com/auth/spreadsheets"] const CRED_PATH = path.resolve(process.cwd(), "access/gsheets.json") +type ElementWithId = unknown & { id: number } + // eslint-disable-next-line @typescript-eslint/ban-types -export async function getList( +export async function getList( sheetName: string, specimen: Element ): Promise { @@ -37,7 +39,17 @@ export async function getList( } // eslint-disable-next-line @typescript-eslint/ban-types -export async function setList( +export async function get( + sheetName: string, + membreId: number, + specimen: Element +): Promise { + const list = await getList(sheetName, specimen) + return list.find((element) => element.id === membreId) +} + +// eslint-disable-next-line @typescript-eslint/ban-types +export async function setList( sheetName: string, elements: Element[] ): Promise { @@ -90,7 +102,7 @@ export async function setList( } // eslint-disable-next-line @typescript-eslint/ban-types -export async function add( +export async function add( sheetName: string, idFieldName: string, partialElement: Partial diff --git a/src/pages/MembrePage/MembrePage.tsx b/src/pages/MembrePage/MembrePage.tsx new file mode 100755 index 0000000..5ac2190 --- /dev/null +++ b/src/pages/MembrePage/MembrePage.tsx @@ -0,0 +1,48 @@ +import { useEffect, memo } from "react" +import { RouteComponentProps } from "react-router-dom" +import { useDispatch, useSelector, shallowEqual } from "react-redux" +import { Helmet } from "react-helmet" + +import { AppState, AppThunk } from "../../store" +import { fetchMembreDataIfNeed } from "../../store/membre" +import { MembreInfo } from "../../components" +import styles from "./styles.module.scss" + +export type Props = RouteComponentProps<{ id: string }> + +const MembrePage = ({ match }: Props): JSX.Element => { + const { id: rawId } = match.params + const id = +rawId + const dispatch = useDispatch() + const membre = useSelector((state: AppState) => state.membre, shallowEqual) + + useEffect(() => { + dispatch(fetchMembreDataIfNeed(id)) + }, [dispatch, id]) + + const renderInfo = () => { + const membreInfo = membre + + if (!membreInfo || membreInfo.readyStatus === "request") return

Loading...

+ + if (membreInfo.readyStatus === "failure" || !membreInfo.entity) + return

Oops! Failed to load data.

+ + return + } + + return ( +
+ + {renderInfo()} +
+ ) +} + +interface LoadDataArgs { + params: { id: number } +} + +export const loadData = ({ params }: LoadDataArgs): AppThunk[] => [fetchMembreDataIfNeed(params.id)] + +export default memo(MembrePage) diff --git a/src/pages/UserInfo/__tests__/UserInfo.tsx b/src/pages/MembrePage/__tests__/MembrePage.tsx similarity index 56% rename from src/pages/UserInfo/__tests__/UserInfo.tsx rename to src/pages/MembrePage/__tests__/MembrePage.tsx index 84b07df..d0d770e 100755 --- a/src/pages/UserInfo/__tests__/UserInfo.tsx +++ b/src/pages/MembrePage/__tests__/MembrePage.tsx @@ -4,27 +4,36 @@ import { render } from "@testing-library/react" import { MemoryRouter } from "react-router-dom" +import { fetchMembreDataIfNeed } from "../../../store/membre" import mockStore from "../../../utils/mockStore" -import UserInfo from "../UserInfo" +import MembrePage from "../MembrePage" -describe("", () => { +describe("", () => { const mockData = { - memberId: 1, - name: "PeL", - phone: "+886 0970...", - email: "forceoranj@gmail.com", - website: "https://www.parisestludique.fr", + 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 { memberId } = mockData + const { id } = mockData const renderHelper = (reducer = {}) => { - const { dispatch, ProviderWithStore } = mockStore({ userData: reducer }) + const { dispatch, ProviderWithStore } = mockStore({ membre: reducer }) const { container } = render( {/* @ts-expect-error */} - + ) @@ -32,6 +41,13 @@ describe("", () => { 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(fetchMembreDataIfNeed(id).toString()) + }) + it("renders the loading status if data invalid", () => { expect(renderHelper().firstChild).toMatchSnapshot() }) diff --git a/src/pages/MembrePage/__tests__/__snapshots__/MembrePage.tsx.snap b/src/pages/MembrePage/__tests__/__snapshots__/MembrePage.tsx.snap new file mode 100644 index 0000000..87be62a --- /dev/null +++ b/src/pages/MembrePage/__tests__/__snapshots__/MembrePage.tsx.snap @@ -0,0 +1,55 @@ +// 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`] = ` +
+

+ Loading... +

+
+`; diff --git a/src/pages/UserInfo/index.tsx b/src/pages/MembrePage/index.tsx similarity index 63% rename from src/pages/UserInfo/index.tsx rename to src/pages/MembrePage/index.tsx index 808540e..073d7da 100755 --- a/src/pages/UserInfo/index.tsx +++ b/src/pages/MembrePage/index.tsx @@ -1,15 +1,15 @@ import loadable from "@loadable/component" import { Loading, ErrorBoundary } from "../../components" -import { Props, loadData } from "./UserInfo" +import { Props, loadData } from "./MembrePage" -const UserInfo = loadable(() => import("./UserInfo"), { +const MembrePage = loadable(() => import("./MembrePage"), { fallback: , }) export default (props: Props): JSX.Element => ( - + ) export { loadData } diff --git a/src/pages/UserInfo/styles.module.scss b/src/pages/MembrePage/styles.module.scss similarity index 65% rename from src/pages/UserInfo/styles.module.scss rename to src/pages/MembrePage/styles.module.scss index e1bb4d4..dee30cc 100755 --- a/src/pages/UserInfo/styles.module.scss +++ b/src/pages/MembrePage/styles.module.scss @@ -1,3 +1,3 @@ -.UserInfo { +.Membre { padding: 0 15px; } diff --git a/src/pages/UserInfo/UserInfo.tsx b/src/pages/UserInfo/UserInfo.tsx deleted file mode 100755 index f3a795a..0000000 --- a/src/pages/UserInfo/UserInfo.tsx +++ /dev/null @@ -1,48 +0,0 @@ -import { useEffect, memo } from "react" -import { RouteComponentProps } from "react-router-dom" -import { useDispatch, useSelector, shallowEqual } from "react-redux" -import { Helmet } from "react-helmet" - -import { AppState, AppThunk } from "../../store" -import { fetchUserDataIfNeed } from "../../store/userData" -import { Info } from "../../components" -import styles from "./styles.module.scss" - -export type Props = RouteComponentProps<{ memberId: string }> - -const UserInfo = ({ match }: Props): JSX.Element => { - const { memberId: rawId } = match.params - const id = +rawId - const dispatch = useDispatch() - const userData = useSelector((state: AppState) => state.userData, shallowEqual) - - useEffect(() => { - dispatch(fetchUserDataIfNeed(id)) - }, [dispatch, id]) - - const renderInfo = () => { - const userInfo = userData - - if (!userInfo || userInfo.readyStatus === "request") return

Loading...

- - if (userInfo.readyStatus === "failure" || !userInfo.entity) - return

Oops! Failed to load data.

- - return - } - - return ( -
- - {renderInfo()} -
- ) -} - -interface LoadDataArgs { - params: { id: number } -} - -export const loadData = ({ params }: LoadDataArgs): AppThunk[] => [fetchUserDataIfNeed(params.id)] - -export default memo(UserInfo) diff --git a/src/pages/UserInfo/__tests__/__snapshots__/UserInfo.tsx.snap b/src/pages/UserInfo/__tests__/__snapshots__/UserInfo.tsx.snap deleted file mode 100644 index 6116bd8..0000000 --- a/src/pages/UserInfo/__tests__/__snapshots__/UserInfo.tsx.snap +++ /dev/null @@ -1,63 +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`] = ` -
-
-

- User Info -

-
    -
  • - Name: - PeL -
  • -
  • - Phone: - +886 0970... -
  • -
  • - Email: - forceoranj@gmail.com -
  • -
  • - Website: - https://www.parisestludique.fr -
  • -
-
-
-`; - -exports[` renders the loading status if data invalid 1`] = ` -
-

- Oops! Failed to load data. -

-
-`; - -exports[` renders the loading status if requesting data 1`] = ` -
-

- Loading... -

-
-`; diff --git a/src/routes/index.ts b/src/routes/index.ts index bf2ff20..c2fdd6c 100755 --- a/src/routes/index.ts +++ b/src/routes/index.ts @@ -2,7 +2,7 @@ import { RouteConfig } from "react-router-config" import App from "../app" import AsyncHome, { loadData as loadHomeData } from "../pages/Home" -import AsyncUserInfo, { loadData as loadUserInfoData } from "../pages/UserInfo" +import AsyncMembrePage, { loadData as loadMembrePageData } from "../pages/MembrePage" import NotFound from "../pages/NotFound" export default [ @@ -16,9 +16,9 @@ export default [ loadData: loadHomeData, // Add your pre-fetch method here }, { - path: "/UserInfo/:id", - component: AsyncUserInfo, - loadData: loadUserInfoData, + path: "/MembrePage/:id", + component: AsyncMembrePage, + loadData: loadMembrePageData, }, { component: NotFound, diff --git a/src/server/index.ts b/src/server/index.ts index 7f33eb6..280470c 100755 --- a/src/server/index.ts +++ b/src/server/index.ts @@ -12,6 +12,7 @@ import ssr from "./ssr" import { getJeuJavList } from "../gsheets/jeuJav" import { getEnvieList, addEnvie } from "../gsheets/envies" +import { getMembre } from "../gsheets/membres" import config from "../config" const app = express() @@ -33,8 +34,9 @@ if (__DEV__) devServer(app) // Google Sheets requests app.use(express.json()) -app.get("/JeuJav", getJeuJavList) +app.get("/JeuJavList", getJeuJavList) app.get("/GetEnvieList", getEnvieList) +app.get("/GetMembre", getMembre) app.post("/AddEnvie", addEnvie) // Use React server-side rendering middleware diff --git a/src/services/envies.ts b/src/services/envies.ts index d9f03ff..f032192 100644 --- a/src/services/envies.ts +++ b/src/services/envies.ts @@ -3,7 +3,7 @@ import axios from "axios" import config from "../config" export class Envie { - envieId = 0 + id = 0 domaine = "" @@ -15,7 +15,7 @@ export class Envie { dateAjout = "" } -export type EnvieWithoutId = Omit +export type EnvieWithoutId = Omit export interface GetEnvieListResponse { data?: Envie[] diff --git a/src/services/jeuJav.ts b/src/services/jeuJav.ts index 1d9499a..3a32ceb 100644 --- a/src/services/jeuJav.ts +++ b/src/services/jeuJav.ts @@ -3,7 +3,7 @@ import axios from "axios" import config from "../config" export class JeuJav { - jeuId = 0 + id = 0 titre = "" @@ -46,7 +46,7 @@ export interface JeuJavData { export const getJeuJavList = async (): Promise => { try { - const { data } = await axios.get(`${config.API_URL}/JeuJav`) + const { data } = await axios.get(`${config.API_URL}/JeuJavList`) return { data } } catch (error) { return { error: error as Error } @@ -55,7 +55,7 @@ export const getJeuJavList = async (): Promise => { export const getJeuJavData = async (id: string): Promise => { try { - const { data } = await axios.get(`${config.API_URL}/users/${id}`) + const { data } = await axios.get(`${config.API_URL}/JeuJav`, { params: { id } }) return { data } } catch (error) { return { error: error as Error } diff --git a/src/services/jsonPlaceholder.ts b/src/services/jsonPlaceholder.ts deleted file mode 100644 index ffd8bb8..0000000 --- a/src/services/jsonPlaceholder.ts +++ /dev/null @@ -1,37 +0,0 @@ -import axios from "axios" - -export interface User { - membreId: number - name: string - phone: string - email: string - website: string -} - -interface UserList { - data?: User[] - error?: Error -} - -interface UserData { - data?: User - error?: Error -} - -export const getUserList = async (): Promise => { - try { - const { data } = await axios.get(`https://jsonplaceholder.typicode.com/users`) - return { data } - } catch (error) { - return { error: error as Error } - } -} - -export const getUserData = async (id: number): Promise => { - try { - const { data } = await axios.get(`https://jsonplaceholder.typicode.com/users/${id}`) - return { data } - } catch (error) { - return { error: error as Error } - } -} diff --git a/src/services/membres.ts b/src/services/membres.ts new file mode 100644 index 0000000..cece7f0 --- /dev/null +++ b/src/services/membres.ts @@ -0,0 +1,71 @@ +import axios from "axios" + +import config from "../config" + +export class Membre { + id = 0 + + nom = "" + + prenom = "" + + mail = "" + + telephone = "" + + photo = "" + + alimentation = "" + + majeur = 1 + + privilege = 0 + + actif = 0 + + commentaire = "" + + horodatage = "" + + passe = "" +} +export type MembreWithoutId = Omit + +export interface GetMembreListResponse { + data?: Membre[] + error?: Error +} +export const getMembreList = async (): Promise => { + try { + const { data } = await axios.get(`${config.API_URL}/GetMembreList`) + return { data } + } catch (error) { + return { error: error as Error } + } +} + +export interface GetMembreResponse { + data?: Membre + error?: Error +} +export const getMembre = async (id: number): Promise => { + try { + const { data } = await axios.get(`${config.API_URL}/GetMembre`, { params: { id } }) + return { data } + } catch (error) { + return { error: error as Error } + } +} + +export interface AddMembreResponse { + data?: Membre + error?: Error +} +export const addMembre = async (membreWithoutId: MembreWithoutId): Promise => { + try { + const { data } = await axios.post(`${config.API_URL}/AddMembre`, membreWithoutId) + return { data } + } catch (error) { + return { error: error as Error } + } +} diff --git a/src/store/__tests__/jeuJavList.ts b/src/store/__tests__/jeuJavList.ts index 0a6d383..0f4159c 100644 --- a/src/store/__tests__/jeuJavList.ts +++ b/src/store/__tests__/jeuJavList.ts @@ -13,7 +13,7 @@ jest.mock("axios") const mockData = { "5": { - jeuId: 5, + id: 5, titre: "6 qui prend!", auteur: "Wolfgang Kramer", editeur: "(uncredited) , Design Edge , B", diff --git a/src/store/__tests__/userData.ts b/src/store/__tests__/membre.ts similarity index 62% rename from src/store/__tests__/userData.ts rename to src/store/__tests__/membre.ts index a30d5d4..3eb1bec 100644 --- a/src/store/__tests__/userData.ts +++ b/src/store/__tests__/membre.ts @@ -1,41 +1,49 @@ import axios from "axios" import mockStore from "../../utils/mockStore" -import userData, { +import membre, { getRequesting, getSuccess, getFailure, - fetchUserData, + fetchMembreData, initialState, -} from "../userData" +} from "../membre" jest.mock("axios") const mockData = { - membreId: 1, - name: "PeL", - phone: "+886 0970...", - email: "forceoranj@gmail.com", - website: "https://www.parisestludique.fr", + 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 { membreId } = mockData +const { id } = mockData const mockError = "Oops! Something went wrong." -describe("userData reducer", () => { +describe("membre reducer", () => { it("should handle initial state correctly", () => { // @ts-expect-error - expect(userData(undefined, {})).toEqual(initialState) + expect(membre(undefined, {})).toEqual(initialState) }) it("should handle requesting correctly", () => { - expect(userData(undefined, { type: getRequesting.type, payload: membreId })).toEqual({ + expect(membre(undefined, { type: getRequesting.type, payload: id })).toEqual({ readyStatus: "request", }) }) it("should handle success correctly", () => { expect( - userData(undefined, { + membre(undefined, { type: getSuccess.type, payload: mockData, }) @@ -44,7 +52,7 @@ describe("userData reducer", () => { it("should handle failure correctly", () => { expect( - userData(undefined, { + membre(undefined, { type: getFailure.type, payload: mockError, }) @@ -52,8 +60,8 @@ describe("userData reducer", () => { }) }) -describe("userData action", () => { - it("fetches user data successful", async () => { +describe("membre action", () => { + it("fetches membre data successful", async () => { const { dispatch, getActions } = mockStore() const expectedActions = [ { type: getRequesting.type }, @@ -63,11 +71,11 @@ describe("userData action", () => { // @ts-expect-error axios.get.mockResolvedValue({ data: mockData }) - await dispatch(fetchUserData(membreId)) + await dispatch(fetchMembreData(id)) expect(getActions()).toEqual(expectedActions) }) - it("fetches user data failed", async () => { + it("fetches membre data failed", async () => { const { dispatch, getActions } = mockStore() const expectedActions = [ { type: getRequesting.type }, @@ -77,7 +85,7 @@ describe("userData action", () => { // @ts-expect-error axios.get.mockRejectedValue({ message: mockError }) - await dispatch(fetchUserData(membreId)) + await dispatch(fetchMembreData(id)) expect(getActions()).toEqual(expectedActions) }) }) diff --git a/src/store/__tests__/userList.ts b/src/store/__tests__/membreList.ts similarity index 58% rename from src/store/__tests__/userList.ts rename to src/store/__tests__/membreList.ts index 3e1c4ca..64bea3c 100644 --- a/src/store/__tests__/userList.ts +++ b/src/store/__tests__/membreList.ts @@ -1,35 +1,43 @@ import axios from "axios" import mockStore from "../../utils/mockStore" -import userList, { +import membreList, { initialState, getRequesting, getSuccess, getFailure, - fetchUserList, -} from "../userList" + fetchMembreList, +} from "../membreList" jest.mock("axios") const mockData = { "1": { - membreId: 1, - name: "PeL", - phone: "+886 0970...", - email: "forceoranj@gmail.com", - website: "https://www.parisestludique.fr", + 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 mockError = "Oops! Something went wrong." -describe("userList reducer", () => { +describe("membreList reducer", () => { it("should handle initial state", () => { // @ts-expect-error - expect(userList(undefined, {})).toEqual(initialState) + expect(membreList(undefined, {})).toEqual(initialState) }) it("should handle requesting correctly", () => { - expect(userList(undefined, { type: getRequesting.type })).toEqual({ + expect(membreList(undefined, { type: getRequesting.type })).toEqual({ readyStatus: "request", ids: [], entities: {}, @@ -37,7 +45,7 @@ describe("userList reducer", () => { }) it("should handle success correctly", () => { - expect(userList(undefined, { type: getSuccess.type, payload: mockData })).toEqual({ + expect(membreList(undefined, { type: getSuccess.type, payload: mockData })).toEqual({ ...initialState, readyStatus: "success", ids: [1], @@ -46,7 +54,7 @@ describe("userList reducer", () => { }) it("should handle failure correctly", () => { - expect(userList(undefined, { type: getFailure.type, payload: mockError })).toEqual({ + expect(membreList(undefined, { type: getFailure.type, payload: mockError })).toEqual({ ...initialState, readyStatus: "failure", error: mockError, @@ -54,8 +62,8 @@ describe("userList reducer", () => { }) }) -describe("userList action", () => { - it("fetches user list successful", async () => { +describe("membreList action", () => { + it("fetches membre list successful", async () => { const { dispatch, getActions } = mockStore() const expectedActions = [ { type: getRequesting.type }, @@ -65,11 +73,11 @@ describe("userList action", () => { // @ts-expect-error axios.get.mockResolvedValue({ data: mockData }) - await dispatch(fetchUserList()) + await dispatch(fetchMembreList()) expect(getActions()).toEqual(expectedActions) }) - it("fetches user list failed", async () => { + it("fetches membre list failed", async () => { const { dispatch, getActions } = mockStore() const expectedActions = [ { type: getRequesting.type }, @@ -79,7 +87,7 @@ describe("userList action", () => { // @ts-expect-error axios.get.mockRejectedValue({ message: mockError }) - await dispatch(fetchUserList()) + await dispatch(fetchMembreList()) expect(getActions()).toEqual(expectedActions) }) }) diff --git a/src/store/envieAdd.ts b/src/store/envieAdd.ts index aafbbbb..03fbaff 100644 --- a/src/store/envieAdd.ts +++ b/src/store/envieAdd.ts @@ -6,7 +6,7 @@ import { Envie, EnvieWithoutId, addEnvie } from "../services/envies" import { AppThunk } from "." const envieAdapter = createEntityAdapter({ - selectId: (envie) => envie.envieId, + selectId: (envie) => envie.id, }) const envieAdd = createSlice({ diff --git a/src/store/envieList.ts b/src/store/envieList.ts index c7bcaed..807e6b8 100644 --- a/src/store/envieList.ts +++ b/src/store/envieList.ts @@ -6,7 +6,7 @@ import { Envie, getEnvieList } from "../services/envies" import { AppThunk, AppState } from "." const envieAdapter = createEntityAdapter({ - selectId: (envie) => envie.envieId, + selectId: (envie) => envie.id, }) const envieList = createSlice({ diff --git a/src/store/jeuJavList.ts b/src/store/jeuJavList.ts index 42230fc..2645fa3 100644 --- a/src/store/jeuJavList.ts +++ b/src/store/jeuJavList.ts @@ -6,7 +6,7 @@ import { JeuJav, getJeuJavList } from "../services/jeuJav" import { AppThunk, AppState } from "." const jeuJavAdapter = createEntityAdapter({ - selectId: (jeuJav) => jeuJav.jeuId, + selectId: (jeuJav) => jeuJav.id, }) export const initialState = jeuJavAdapter.getInitialState({ diff --git a/src/store/userData.ts b/src/store/membre.ts similarity index 55% rename from src/store/userData.ts rename to src/store/membre.ts index ea9f020..fc32ef4 100644 --- a/src/store/userData.ts +++ b/src/store/membre.ts @@ -2,23 +2,23 @@ import { PayloadAction, createSlice } from "@reduxjs/toolkit" import { toast } from "react-toastify" import { StateRequest } from "./utils" -import { User, getUserData } from "../services/jsonPlaceholder" +import { Membre, getMembre } from "../services/membres" import { AppThunk, AppState } from "." -type StateUser = { entity?: User } & StateRequest +type StateMembre = { entity?: Membre } & StateRequest -export const initialState: StateUser = { +export const initialState: StateMembre = { readyStatus: "idle", } -const userData = createSlice({ - name: "userData", +const membre = createSlice({ + name: "membre", initialState, reducers: { getRequesting: (_) => ({ readyStatus: "request", }), - getSuccess: (_, { payload }: PayloadAction) => ({ + getSuccess: (_, { payload }: PayloadAction) => ({ readyStatus: "success", entity: payload, }), @@ -29,19 +29,19 @@ const userData = createSlice({ }, }) -export default userData.reducer -export const { getRequesting, getSuccess, getFailure } = userData.actions +export default membre.reducer +export const { getRequesting, getSuccess, getFailure } = membre.actions -export const fetchUserData = +export const fetchMembreData = (id: number): AppThunk => async (dispatch) => { dispatch(getRequesting()) - const { error, data } = await getUserData(id) + const { error, data } = await getMembre(id) if (error) { dispatch(getFailure(error.message)) - toast.error(`Erreur lors du chargement de l'utilisateur ${id}: ${error.message}`, { + toast.error(`Erreur lors du chargement du membre ${id}: ${error.message}`, { position: "top-center", autoClose: 6000, hideProgressBar: true, @@ -51,18 +51,17 @@ export const fetchUserData = progress: undefined, }) } else { - dispatch(getSuccess(data as User)) + dispatch(getSuccess(data as Membre)) } } -const shouldFetchUserData = (state: AppState, id: number) => - state.userData.readyStatus !== "success" || - (state.userData.entity && state.userData.entity.membreId !== id) +const shouldFetchMembreData = (state: AppState, id: number) => + state.membre.readyStatus !== "success" || (state.membre.entity && state.membre.entity.id !== id) -export const fetchUserDataIfNeed = +export const fetchMembreDataIfNeed = (id: number): AppThunk => (dispatch, getState) => { - if (shouldFetchUserData(getState(), id)) return dispatch(fetchUserData(id)) + if (shouldFetchMembreData(getState(), id)) return dispatch(fetchMembreData(id)) return null } diff --git a/src/store/userList.ts b/src/store/membreList.ts similarity index 54% rename from src/store/userList.ts rename to src/store/membreList.ts index df56627..7cdcc97 100644 --- a/src/store/userList.ts +++ b/src/store/membreList.ts @@ -2,27 +2,25 @@ import { PayloadAction, createSlice, createEntityAdapter } from "@reduxjs/toolki import { toast } from "react-toastify" import { StateRequest } from "./utils" -import { User, getUserList } from "../services/jsonPlaceholder" +import { Membre, getMembreList } from "../services/membres" import { AppThunk, AppState } from "." -const userAdapter = createEntityAdapter({ - selectId: (user) => user.membreId, -}) +const membreAdapter = createEntityAdapter() -export const initialState = userAdapter.getInitialState({ +export const initialState = membreAdapter.getInitialState({ readyStatus: "idle", } as StateRequest) -const userList = createSlice({ - name: "userList", +const membreList = createSlice({ + name: "membreList", initialState, reducers: { getRequesting: (state) => { state.readyStatus = "request" }, - getSuccess: (state, { payload }: PayloadAction) => { + getSuccess: (state, { payload }: PayloadAction) => { state.readyStatus = "success" - userAdapter.setAll(state, payload) + membreAdapter.setAll(state, payload) }, getFailure: (state, { payload }: PayloadAction) => { state.readyStatus = "failure" @@ -31,13 +29,13 @@ const userList = createSlice({ }, }) -export default userList.reducer -export const { getRequesting, getSuccess, getFailure } = userList.actions +export default membreList.reducer +export const { getRequesting, getSuccess, getFailure } = membreList.actions -export const fetchUserList = (): AppThunk => async (dispatch) => { +export const fetchMembreList = (): AppThunk => async (dispatch) => { dispatch(getRequesting()) - const { error, data } = await getUserList() + const { error, data } = await getMembreList() if (error) { dispatch(getFailure(error.message)) @@ -51,14 +49,14 @@ export const fetchUserList = (): AppThunk => async (dispatch) => { progress: undefined, }) } else { - dispatch(getSuccess(data as User[])) + dispatch(getSuccess(data as Membre[])) } } -const shouldFetchUserList = (state: AppState) => state.userList.readyStatus !== "success" +const shouldFetchMembreList = (state: AppState) => state.membreList.readyStatus !== "success" -export const fetchUserListIfNeed = (): AppThunk => (dispatch, getState) => { - if (shouldFetchUserList(getState())) return dispatch(fetchUserList()) +export const fetchMembreListIfNeed = (): AppThunk => (dispatch, getState) => { + if (shouldFetchMembreList(getState())) return dispatch(fetchMembreList()) return null } diff --git a/src/store/rootReducer.ts b/src/store/rootReducer.ts index d9c22ac..a00418c 100644 --- a/src/store/rootReducer.ts +++ b/src/store/rootReducer.ts @@ -1,16 +1,16 @@ import { History } from "history" import { connectRouter } from "connected-react-router" -import userList from "./userList" -import userData from "./userData" +import membreList from "./membreList" +import membre from "./membre" import jeuJavList from "./jeuJavList" import envieList from "./envieList" // Use inferred return type for making correctly Redux types // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types export default (history: History) => ({ - userList, - userData, + membreList, + membre, jeuJavList, envieList, router: connectRouter(history) as any,