mirror of
https://github.com/Paris-est-Ludique/intranet.git
synced 2025-06-09 09:04:20 +02:00
Add gSheet specific entity write
This commit is contained in:
parent
c33b9d8f79
commit
b76fbc78ff
@ -330,20 +330,6 @@ class Test {
|
|||||||
tictactoe: boolean[] = []
|
tictactoe: boolean[] = []
|
||||||
}
|
}
|
||||||
|
|
||||||
// class Membre {
|
|
||||||
// membreId = 0
|
|
||||||
|
|
||||||
// nom = ""
|
|
||||||
|
|
||||||
// prenom = ""
|
|
||||||
|
|
||||||
// mail = ""
|
|
||||||
|
|
||||||
// telephone = ""
|
|
||||||
|
|
||||||
// photo = ""
|
|
||||||
// }
|
|
||||||
|
|
||||||
// Can't run it on every test, it requires private access to a google sheet
|
// Can't run it on every test, it requires private access to a google sheet
|
||||||
async function testGSheetAPi(): Promise<void> {
|
async function testGSheetAPi(): Promise<void> {
|
||||||
const dataset: Test[] = [
|
const dataset: Test[] = [
|
||||||
|
@ -3,7 +3,7 @@ import { toast } from "react-toastify"
|
|||||||
|
|
||||||
import { AppDispatch } from "../../store"
|
import { AppDispatch } from "../../store"
|
||||||
|
|
||||||
import { postEnvie } from "../../store/envieAdd"
|
import { sendAddEnvie } from "../../store/envieAdd"
|
||||||
import styles from "./styles.module.scss"
|
import styles from "./styles.module.scss"
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
@ -29,7 +29,7 @@ const AddEnvie = ({ dispatch }: Props) => {
|
|||||||
const onSavePostClicked = () => {
|
const onSavePostClicked = () => {
|
||||||
if (domaine && envies) {
|
if (domaine && envies) {
|
||||||
dispatch(
|
dispatch(
|
||||||
postEnvie({
|
sendAddEnvie({
|
||||||
domaine,
|
domaine,
|
||||||
envies,
|
envies,
|
||||||
precisions,
|
precisions,
|
||||||
|
37
src/components/MembreSet/__tests__/MembreSet.tsx
Normal file
37
src/components/MembreSet/__tests__/MembreSet.tsx
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
/**
|
||||||
|
* @jest-environment jsdom
|
||||||
|
*/
|
||||||
|
import { render } from "@testing-library/react"
|
||||||
|
import { MemoryRouter } from "react-router-dom"
|
||||||
|
|
||||||
|
import MembreSet from "../index"
|
||||||
|
|
||||||
|
describe("<SetMembre />", () => {
|
||||||
|
it("renders", () => {
|
||||||
|
const dispatch = jest.fn()
|
||||||
|
const tree = render(
|
||||||
|
<MemoryRouter>
|
||||||
|
<MembreSet
|
||||||
|
dispatch={dispatch}
|
||||||
|
membre={{
|
||||||
|
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",
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</MemoryRouter>
|
||||||
|
).container.firstChild
|
||||||
|
|
||||||
|
expect(tree).toMatchSnapshot()
|
||||||
|
})
|
||||||
|
})
|
@ -0,0 +1,51 @@
|
|||||||
|
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||||
|
|
||||||
|
exports[`<SetMembre /> renders 1`] = `
|
||||||
|
<section
|
||||||
|
class="MembreList"
|
||||||
|
>
|
||||||
|
<h2>
|
||||||
|
Modifier un membre
|
||||||
|
</h2>
|
||||||
|
<form>
|
||||||
|
<label
|
||||||
|
for="postPrenom"
|
||||||
|
>
|
||||||
|
Prenom:
|
||||||
|
<input
|
||||||
|
id="postPrenom"
|
||||||
|
name="postPrenom"
|
||||||
|
type="text"
|
||||||
|
value="Amélie"
|
||||||
|
/>
|
||||||
|
</label>
|
||||||
|
<label
|
||||||
|
for="postNom"
|
||||||
|
>
|
||||||
|
Nom:
|
||||||
|
<input
|
||||||
|
id="postNom"
|
||||||
|
name="postNom"
|
||||||
|
type="text"
|
||||||
|
value="Aupeix"
|
||||||
|
/>
|
||||||
|
</label>
|
||||||
|
<label
|
||||||
|
for="postMajeur"
|
||||||
|
>
|
||||||
|
Majeur:
|
||||||
|
<input
|
||||||
|
id="postMajeur"
|
||||||
|
name="postMajeur"
|
||||||
|
type="text"
|
||||||
|
value="1"
|
||||||
|
/>
|
||||||
|
</label>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
>
|
||||||
|
Save changes
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
|
</section>
|
||||||
|
`;
|
87
src/components/MembreSet/index.tsx
Normal file
87
src/components/MembreSet/index.tsx
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
import React, { useState, memo } from "react"
|
||||||
|
import { toast } from "react-toastify"
|
||||||
|
|
||||||
|
import { AppDispatch } from "../../store"
|
||||||
|
|
||||||
|
import { sendMembreSet } from "../../store/membreSet"
|
||||||
|
import { Membre } from "../../services/membres"
|
||||||
|
import styles from "./styles.module.scss"
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
dispatch: AppDispatch
|
||||||
|
membre: Membre
|
||||||
|
}
|
||||||
|
|
||||||
|
const MembreSet = ({ dispatch, membre }: Props) => {
|
||||||
|
const [prenom, setPrenom] = useState(membre.prenom)
|
||||||
|
const [nom, setNom] = useState(membre.nom)
|
||||||
|
const [majeur, setMajeur] = useState(membre.majeur)
|
||||||
|
|
||||||
|
const onPrenomChanged = (e: React.ChangeEvent<HTMLInputElement>) => setPrenom(e.target.value)
|
||||||
|
const onNomChanged = (e: React.ChangeEvent<HTMLInputElement>) => setNom(e.target.value)
|
||||||
|
const onMajeurChanged = (e: React.ChangeEvent<HTMLInputElement>) => setMajeur(+e.target.value)
|
||||||
|
|
||||||
|
const onSavePostClicked = () => {
|
||||||
|
if (prenom && nom) {
|
||||||
|
dispatch(
|
||||||
|
sendMembreSet({
|
||||||
|
...membre,
|
||||||
|
prenom,
|
||||||
|
nom,
|
||||||
|
majeur,
|
||||||
|
})
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
toast.warning("Il faut au moins préciser un prenom et un nom", {
|
||||||
|
position: "top-center",
|
||||||
|
autoClose: 6000,
|
||||||
|
hideProgressBar: true,
|
||||||
|
closeOnClick: true,
|
||||||
|
pauseOnHover: true,
|
||||||
|
draggable: true,
|
||||||
|
progress: undefined,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<section className={styles.MembreList}>
|
||||||
|
<h2>Modifier un membre</h2>
|
||||||
|
<form>
|
||||||
|
<label htmlFor="postPrenom">
|
||||||
|
Prenom:
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
id="postPrenom"
|
||||||
|
name="postPrenom"
|
||||||
|
value={prenom}
|
||||||
|
onChange={onPrenomChanged}
|
||||||
|
/>
|
||||||
|
</label>
|
||||||
|
<label htmlFor="postNom">
|
||||||
|
Nom:
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
id="postNom"
|
||||||
|
name="postNom"
|
||||||
|
value={nom}
|
||||||
|
onChange={onNomChanged}
|
||||||
|
/>
|
||||||
|
</label>
|
||||||
|
<label htmlFor="postMajeur">
|
||||||
|
Majeur:
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
id="postMajeur"
|
||||||
|
name="postMajeur"
|
||||||
|
value={majeur}
|
||||||
|
onChange={onMajeurChanged}
|
||||||
|
/>
|
||||||
|
</label>
|
||||||
|
<button type="button" onClick={onSavePostClicked}>
|
||||||
|
Save changes
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
|
</section>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
export default memo(MembreSet)
|
17
src/components/MembreSet/styles.module.scss
Normal file
17
src/components/MembreSet/styles.module.scss
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
@import "../../theme/variables";
|
||||||
|
|
||||||
|
.jav-game-list {
|
||||||
|
color: $color-white;
|
||||||
|
|
||||||
|
ul {
|
||||||
|
padding-left: 17px;
|
||||||
|
|
||||||
|
li {
|
||||||
|
margin-bottom: 0.5em;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
a {
|
||||||
|
color: $color-white;
|
||||||
|
}
|
||||||
|
}
|
@ -1,8 +1,9 @@
|
|||||||
import MembreList from "./MembreList"
|
import MembreList from "./MembreList"
|
||||||
import JeuJavList from "./JeuJavList"
|
import JeuJavList from "./JeuJavList"
|
||||||
import MembreInfo from "./MembreInfo"
|
import MembreInfo from "./MembreInfo"
|
||||||
|
import MembreSet from "./MembreSet"
|
||||||
import ErrorBoundary from "./ErrorBoundary"
|
import ErrorBoundary from "./ErrorBoundary"
|
||||||
import Loading from "./Loading"
|
import Loading from "./Loading"
|
||||||
import AddEnvie from "./AddEnvie"
|
import AddEnvie from "./AddEnvie"
|
||||||
|
|
||||||
export { MembreList, JeuJavList, MembreInfo, ErrorBoundary, Loading, AddEnvie }
|
export { MembreList, JeuJavList, MembreInfo, MembreSet, ErrorBoundary, Loading, AddEnvie }
|
||||||
|
@ -2,7 +2,7 @@ import { Request, Response, NextFunction } from "express"
|
|||||||
import { getList, add } from "./utils"
|
import { getList, add } from "./utils"
|
||||||
import { Envie, EnvieWithoutId } from "../services/envies"
|
import { Envie, EnvieWithoutId } from "../services/envies"
|
||||||
|
|
||||||
export const getEnvieList = async (
|
export const envieListGet = async (
|
||||||
_request: Request,
|
_request: Request,
|
||||||
response: Response,
|
response: Response,
|
||||||
_next: NextFunction
|
_next: NextFunction
|
||||||
@ -17,13 +17,13 @@ export const getEnvieList = async (
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const addEnvie = async (
|
export const envieAdd = async (
|
||||||
request: Request,
|
request: Request,
|
||||||
response: Response,
|
response: Response,
|
||||||
_next: NextFunction
|
_next: NextFunction
|
||||||
): Promise<void> => {
|
): Promise<void> => {
|
||||||
try {
|
try {
|
||||||
const envie = await add<EnvieWithoutId, Envie>("Envies d'aider", "id", request.body)
|
const envie = await add<EnvieWithoutId, Envie>("Envies d'aider", request.body)
|
||||||
if (envie) {
|
if (envie) {
|
||||||
response.status(200).json(envie)
|
response.status(200).json(envie)
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,7 @@ import _ from "lodash"
|
|||||||
import { getList } from "./utils"
|
import { getList } from "./utils"
|
||||||
import { JeuJav } from "../services/jeuJav"
|
import { JeuJav } from "../services/jeuJav"
|
||||||
|
|
||||||
export const getJeuJavList = async (
|
export const jeuJavListGet = async (
|
||||||
_request: Request,
|
_request: Request,
|
||||||
response: Response,
|
response: Response,
|
||||||
_next: NextFunction
|
_next: NextFunction
|
||||||
@ -18,7 +18,7 @@ export const getJeuJavList = async (
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const getJeuJavData = async (
|
export const jeuJavGet = async (
|
||||||
_request: Request,
|
_request: Request,
|
||||||
response: Response,
|
response: Response,
|
||||||
_next: NextFunction
|
_next: NextFunction
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
import { Request, Response, NextFunction } from "express"
|
import { Request, Response, NextFunction } from "express"
|
||||||
import { getList, get, add } from "./utils"
|
import { getList, get, set, add } from "./utils"
|
||||||
import { Membre, MembreWithoutId } from "../services/membres"
|
import { Membre, MembreWithoutId } from "../services/membres"
|
||||||
|
|
||||||
export const getMembreList = async (
|
export const membreListGet = async (
|
||||||
_request: Request,
|
_request: Request,
|
||||||
response: Response,
|
response: Response,
|
||||||
_next: NextFunction
|
_next: NextFunction
|
||||||
@ -17,7 +17,7 @@ export const getMembreList = async (
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const getMembre = async (
|
export const membreGet = async (
|
||||||
request: Request,
|
request: Request,
|
||||||
response: Response,
|
response: Response,
|
||||||
_next: NextFunction
|
_next: NextFunction
|
||||||
@ -31,13 +31,28 @@ export const getMembre = async (
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const addMembre = async (
|
export const membreSet = async (
|
||||||
request: Request,
|
request: Request,
|
||||||
response: Response,
|
response: Response,
|
||||||
_next: NextFunction
|
_next: NextFunction
|
||||||
): Promise<void> => {
|
): Promise<void> => {
|
||||||
try {
|
try {
|
||||||
const membre = await add<MembreWithoutId, Membre>("Membres", "membreId", request.body)
|
const envie = await set<Membre>("Membres", request.body)
|
||||||
|
if (envie) {
|
||||||
|
response.status(200).json(envie)
|
||||||
|
}
|
||||||
|
} catch (e: unknown) {
|
||||||
|
response.status(400).json(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const membreAdd = async (
|
||||||
|
request: Request,
|
||||||
|
response: Response,
|
||||||
|
_next: NextFunction
|
||||||
|
): Promise<void> => {
|
||||||
|
try {
|
||||||
|
const membre = await add<MembreWithoutId, Membre>("Membres", request.body)
|
||||||
if (membre) {
|
if (membre) {
|
||||||
response.status(200).json(membre)
|
response.status(200).json(membre)
|
||||||
}
|
}
|
||||||
|
@ -101,10 +101,38 @@ export async function setList<Element extends ElementWithId>(
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// eslint-disable-next-line @typescript-eslint/ban-types
|
||||||
|
export async function set<Element extends ElementWithId>(
|
||||||
|
sheetName: string,
|
||||||
|
element: Element
|
||||||
|
): Promise<Element | undefined> {
|
||||||
|
if (!element) {
|
||||||
|
return undefined
|
||||||
|
}
|
||||||
|
const sheet = await getGSheet(sheetName)
|
||||||
|
|
||||||
|
// Load sheet into an array of objects
|
||||||
|
const rows = await sheet.getRows()
|
||||||
|
if (!rows[0]) {
|
||||||
|
throw new Error(`No column types defined in sheet ${sheetName}`)
|
||||||
|
}
|
||||||
|
const types = _.pick(rows[0], Object.keys(element || {})) as Record<keyof Element, string>
|
||||||
|
rows.shift()
|
||||||
|
|
||||||
|
// Replace previous row
|
||||||
|
const stringifiedRow = stringifyElement(element, types)
|
||||||
|
const row = rows.find((rowItem) => +rowItem.id === element.id)
|
||||||
|
if (!row) {
|
||||||
|
return undefined
|
||||||
|
}
|
||||||
|
Object.assign(row, stringifiedRow)
|
||||||
|
await row.save()
|
||||||
|
return element
|
||||||
|
}
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/ban-types
|
// eslint-disable-next-line @typescript-eslint/ban-types
|
||||||
export async function add<ElementNoId extends object, Element extends ElementNoId & ElementWithId>(
|
export async function add<ElementNoId extends object, Element extends ElementNoId & ElementWithId>(
|
||||||
sheetName: string,
|
sheetName: string,
|
||||||
idFieldName: string,
|
|
||||||
partialElement: Partial<ElementNoId>
|
partialElement: Partial<ElementNoId>
|
||||||
): Promise<Element | undefined> {
|
): Promise<Element | undefined> {
|
||||||
if (!partialElement) {
|
if (!partialElement) {
|
||||||
@ -118,14 +146,17 @@ export async function add<ElementNoId extends object, Element extends ElementNoI
|
|||||||
throw new Error(`No column types defined in sheet ${sheetName}`)
|
throw new Error(`No column types defined in sheet ${sheetName}`)
|
||||||
}
|
}
|
||||||
const types = {
|
const types = {
|
||||||
[idFieldName]: "number",
|
id: "number",
|
||||||
...(_.pick(rows[0], Object.keys(partialElement || {})) as Record<keyof Element, string>),
|
...(_.pick(rows[0], Object.keys(partialElement || {})) as Record<
|
||||||
|
keyof ElementNoId,
|
||||||
|
string
|
||||||
|
>),
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create full element
|
// Create full element
|
||||||
rows.shift()
|
rows.shift()
|
||||||
const highestId = rows.reduce((id: number, row) => Math.max(id, +row[idFieldName] || 0), 0)
|
const highestId = rows.reduce((id: number, row) => Math.max(id, +row.id || 0), 0)
|
||||||
const element = { [idFieldName]: highestId + 1, ...partialElement } as Element
|
const element = { id: highestId + 1, ...partialElement } as Element
|
||||||
|
|
||||||
// Add element
|
// Add element
|
||||||
const stringifiedRow = stringifyElement(element, types)
|
const stringifiedRow = stringifyElement(element, types)
|
||||||
@ -241,9 +272,9 @@ function parseElement<Element extends object>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/ban-types
|
// eslint-disable-next-line @typescript-eslint/ban-types
|
||||||
function stringifyElement<Element extends object>(
|
function stringifyElement<ElementNoId extends object, Element extends ElementNoId & ElementWithId>(
|
||||||
element: Element,
|
element: Element,
|
||||||
types: Record<keyof Element, string>
|
types: { id: string } & Record<keyof ElementNoId, string>
|
||||||
): Record<keyof Element, string> {
|
): Record<keyof Element, string> {
|
||||||
const rawElement: Record<keyof Element, string> = _.reduce(
|
const rawElement: Record<keyof Element, string> = _.reduce(
|
||||||
types,
|
types,
|
||||||
|
@ -5,7 +5,7 @@ import { Helmet } from "react-helmet"
|
|||||||
|
|
||||||
import { AppState, AppThunk } from "../../store"
|
import { AppState, AppThunk } from "../../store"
|
||||||
import { fetchMembreDataIfNeed } from "../../store/membre"
|
import { fetchMembreDataIfNeed } from "../../store/membre"
|
||||||
import { MembreInfo } from "../../components"
|
import { MembreInfo, MembreSet } 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 }>
|
||||||
@ -28,7 +28,12 @@ const MembrePage = ({ match }: Props): JSX.Element => {
|
|||||||
if (membreInfo.readyStatus === "failure" || !membreInfo.entity)
|
if (membreInfo.readyStatus === "failure" || !membreInfo.entity)
|
||||||
return <p>Oops! Failed to load data.</p>
|
return <p>Oops! Failed to load data.</p>
|
||||||
|
|
||||||
return <MembreInfo item={membreInfo.entity} />
|
return (
|
||||||
|
<div>
|
||||||
|
<MembreInfo item={membreInfo.entity} />
|
||||||
|
<MembreSet dispatch={dispatch} membre={membreInfo.entity} />
|
||||||
|
</div>
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -14,6 +14,7 @@ exports[`<MembrePage /> renders the <Info /> if loading was successful 1`] = `
|
|||||||
<div
|
<div
|
||||||
class="Membre"
|
class="Membre"
|
||||||
>
|
>
|
||||||
|
<div>
|
||||||
<div
|
<div
|
||||||
class="MembreCard"
|
class="MembreCard"
|
||||||
>
|
>
|
||||||
@ -31,6 +32,54 @@ exports[`<MembrePage /> renders the <Info /> if loading was successful 1`] = `
|
|||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
<section
|
||||||
|
class="MembreList"
|
||||||
|
>
|
||||||
|
<h2>
|
||||||
|
Modifier un membre
|
||||||
|
</h2>
|
||||||
|
<form>
|
||||||
|
<label
|
||||||
|
for="postPrenom"
|
||||||
|
>
|
||||||
|
Prenom:
|
||||||
|
<input
|
||||||
|
id="postPrenom"
|
||||||
|
name="postPrenom"
|
||||||
|
type="text"
|
||||||
|
value="Amélie"
|
||||||
|
/>
|
||||||
|
</label>
|
||||||
|
<label
|
||||||
|
for="postNom"
|
||||||
|
>
|
||||||
|
Nom:
|
||||||
|
<input
|
||||||
|
id="postNom"
|
||||||
|
name="postNom"
|
||||||
|
type="text"
|
||||||
|
value="Aupeix"
|
||||||
|
/>
|
||||||
|
</label>
|
||||||
|
<label
|
||||||
|
for="postMajeur"
|
||||||
|
>
|
||||||
|
Majeur:
|
||||||
|
<input
|
||||||
|
id="postMajeur"
|
||||||
|
name="postMajeur"
|
||||||
|
type="text"
|
||||||
|
value="1"
|
||||||
|
/>
|
||||||
|
</label>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
>
|
||||||
|
Save changes
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
@ -10,9 +10,9 @@ import chalk from "chalk"
|
|||||||
import devServer from "./devServer"
|
import devServer from "./devServer"
|
||||||
import ssr from "./ssr"
|
import ssr from "./ssr"
|
||||||
|
|
||||||
import { getJeuJavList } from "../gsheets/jeuJav"
|
import { jeuJavListGet } from "../gsheets/jeuJav"
|
||||||
import { getEnvieList, addEnvie } from "../gsheets/envies"
|
import { envieListGet, envieAdd } from "../gsheets/envies"
|
||||||
import { getMembre } from "../gsheets/membres"
|
import { membreGet, membreSet } from "../gsheets/membres"
|
||||||
import config from "../config"
|
import config from "../config"
|
||||||
|
|
||||||
const app = express()
|
const app = express()
|
||||||
@ -34,10 +34,11 @@ if (__DEV__) devServer(app)
|
|||||||
|
|
||||||
// Google Sheets requests
|
// Google Sheets requests
|
||||||
app.use(express.json())
|
app.use(express.json())
|
||||||
app.get("/JeuJavList", getJeuJavList)
|
app.get("/JeuJavListGet", jeuJavListGet)
|
||||||
app.get("/GetEnvieList", getEnvieList)
|
app.get("/EnvieListGet", envieListGet)
|
||||||
app.get("/GetMembre", getMembre)
|
app.get("/MembreGet", membreGet)
|
||||||
app.post("/AddEnvie", addEnvie)
|
app.post("/MembreSet", membreSet)
|
||||||
|
app.post("/EnvieAdd", envieAdd)
|
||||||
|
|
||||||
// Use React server-side rendering middleware
|
// Use React server-side rendering middleware
|
||||||
app.get("*", ssr)
|
app.get("*", ssr)
|
||||||
|
@ -17,26 +17,26 @@ export class Envie {
|
|||||||
}
|
}
|
||||||
export type EnvieWithoutId = Omit<Envie, "id">
|
export type EnvieWithoutId = Omit<Envie, "id">
|
||||||
|
|
||||||
export interface GetEnvieListResponse {
|
export interface EnvieListGetResponse {
|
||||||
data?: Envie[]
|
data?: Envie[]
|
||||||
error?: Error
|
error?: Error
|
||||||
}
|
}
|
||||||
export const getEnvieList = async (): Promise<GetEnvieListResponse> => {
|
export const envieListGet = async (): Promise<EnvieListGetResponse> => {
|
||||||
try {
|
try {
|
||||||
const { data } = await axios.get(`${config.API_URL}/GetEnvieList`)
|
const { data } = await axios.get(`${config.API_URL}/EnvieListGet`)
|
||||||
return { data }
|
return { data }
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
return { error: error as Error }
|
return { error: error as Error }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface AddEnvieResponse {
|
export interface EnvieAddResponse {
|
||||||
data?: Envie
|
data?: Envie
|
||||||
error?: Error
|
error?: Error
|
||||||
}
|
}
|
||||||
export const addEnvie = async (envieWithoutId: EnvieWithoutId): Promise<AddEnvieResponse> => {
|
export const envieAdd = async (envieWithoutId: EnvieWithoutId): Promise<EnvieAddResponse> => {
|
||||||
try {
|
try {
|
||||||
const { data } = await axios.post(`${config.API_URL}/AddEnvie`, envieWithoutId)
|
const { data } = await axios.post(`${config.API_URL}/EnvieAdd`, envieWithoutId)
|
||||||
return { data }
|
return { data }
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
return { error: error as Error }
|
return { error: error as Error }
|
||||||
|
@ -34,28 +34,26 @@ export class JeuJav {
|
|||||||
bggPhoto = ""
|
bggPhoto = ""
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface JeuJavList {
|
export interface JeuJavListResponse {
|
||||||
data?: JeuJav[]
|
data?: JeuJav[]
|
||||||
error?: Error
|
error?: Error
|
||||||
}
|
}
|
||||||
|
export const getJeuJavList = async (): Promise<JeuJavListResponse> => {
|
||||||
|
try {
|
||||||
|
const { data } = await axios.get(`${config.API_URL}/JeuJavListGet`)
|
||||||
|
return { data }
|
||||||
|
} catch (error) {
|
||||||
|
return { error: error as Error }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export interface JeuJavData {
|
export interface JeuJavResponse {
|
||||||
data?: JeuJav
|
data?: JeuJav
|
||||||
error?: Error
|
error?: Error
|
||||||
}
|
}
|
||||||
|
export const getJeuJavData = async (id: string): Promise<JeuJavResponse> => {
|
||||||
export const getJeuJavList = async (): Promise<JeuJavList> => {
|
|
||||||
try {
|
try {
|
||||||
const { data } = await axios.get(`${config.API_URL}/JeuJavList`)
|
const { data } = await axios.get(`${config.API_URL}/JeuJavGet`, { params: { id } })
|
||||||
return { data }
|
|
||||||
} catch (error) {
|
|
||||||
return { error: error as Error }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export const getJeuJavData = async (id: string): Promise<JeuJavData> => {
|
|
||||||
try {
|
|
||||||
const { data } = await axios.get(`${config.API_URL}/JeuJav`, { params: { id } })
|
|
||||||
return { data }
|
return { data }
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
return { error: error as Error }
|
return { error: error as Error }
|
||||||
|
@ -29,41 +29,54 @@ export class Membre {
|
|||||||
|
|
||||||
passe = ""
|
passe = ""
|
||||||
}
|
}
|
||||||
export type MembreWithoutId = Omit<Membre, "membreId">
|
export type MembreWithoutId = Omit<Membre, "id">
|
||||||
|
|
||||||
export interface GetMembreListResponse {
|
export interface MembreListGetResponse {
|
||||||
data?: Membre[]
|
data?: Membre[]
|
||||||
error?: Error
|
error?: Error
|
||||||
}
|
}
|
||||||
export const getMembreList = async (): Promise<GetMembreListResponse> => {
|
export const membreListGet = async (): Promise<MembreListGetResponse> => {
|
||||||
try {
|
try {
|
||||||
const { data } = await axios.get(`${config.API_URL}/GetMembreList`)
|
const { data } = await axios.get(`${config.API_URL}/MembreListGet`)
|
||||||
return { data }
|
return { data }
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
return { error: error as Error }
|
return { error: error as Error }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface GetMembreResponse {
|
export interface MembreGetResponse {
|
||||||
data?: Membre
|
data?: Membre
|
||||||
error?: Error
|
error?: Error
|
||||||
}
|
}
|
||||||
export const getMembre = async (id: number): Promise<GetMembreResponse> => {
|
export const membreGet = async (id: number): Promise<MembreGetResponse> => {
|
||||||
try {
|
try {
|
||||||
const { data } = await axios.get(`${config.API_URL}/GetMembre`, { params: { id } })
|
const { data } = await axios.get(`${config.API_URL}/MembreGet`, { params: { id } })
|
||||||
return { data }
|
return { data }
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
return { error: error as Error }
|
return { error: error as Error }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface AddMembreResponse {
|
export interface MembreSetResponse {
|
||||||
data?: Membre
|
data?: Membre
|
||||||
error?: Error
|
error?: Error
|
||||||
}
|
}
|
||||||
export const addMembre = async (membreWithoutId: MembreWithoutId): Promise<AddMembreResponse> => {
|
export const membreSet = async (membre: Membre): Promise<MembreSetResponse> => {
|
||||||
try {
|
try {
|
||||||
const { data } = await axios.post(`${config.API_URL}/AddMembre`, membreWithoutId)
|
const { data } = await axios.post(`${config.API_URL}/MembreSet`, membre)
|
||||||
|
return { data }
|
||||||
|
} catch (error) {
|
||||||
|
return { error: error as Error }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface MembreAddResponse {
|
||||||
|
data?: Membre
|
||||||
|
error?: Error
|
||||||
|
}
|
||||||
|
export const membreAdd = async (membreWithoutId: MembreWithoutId): Promise<MembreAddResponse> => {
|
||||||
|
try {
|
||||||
|
const { data } = await axios.post(`${config.API_URL}/MembreAdd`, membreWithoutId)
|
||||||
return { data }
|
return { data }
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
return { error: error as Error }
|
return { error: error as Error }
|
||||||
|
@ -2,14 +2,14 @@ import { PayloadAction, createSlice, createEntityAdapter } from "@reduxjs/toolki
|
|||||||
import { toast } from "react-toastify"
|
import { toast } from "react-toastify"
|
||||||
|
|
||||||
import { StateRequest } from "./utils"
|
import { StateRequest } from "./utils"
|
||||||
import { Envie, EnvieWithoutId, addEnvie } from "../services/envies"
|
import { Envie, EnvieWithoutId, envieAdd } from "../services/envies"
|
||||||
import { AppThunk } from "."
|
import { AppThunk } from "."
|
||||||
|
|
||||||
const envieAdapter = createEntityAdapter<Envie>({
|
const envieAdapter = createEntityAdapter<Envie>({
|
||||||
selectId: (envie) => envie.id,
|
selectId: (envie) => envie.id,
|
||||||
})
|
})
|
||||||
|
|
||||||
const envieAdd = createSlice({
|
const envieAddSlice = createSlice({
|
||||||
name: "addEnvie",
|
name: "addEnvie",
|
||||||
initialState: envieAdapter.getInitialState({
|
initialState: envieAdapter.getInitialState({
|
||||||
readyStatus: "idle",
|
readyStatus: "idle",
|
||||||
@ -29,15 +29,15 @@ const envieAdd = createSlice({
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
export default envieAdd.reducer
|
export default envieAddSlice.reducer
|
||||||
export const { getRequesting, getSuccess, getFailure } = envieAdd.actions
|
export const { getRequesting, getSuccess, getFailure } = envieAddSlice.actions
|
||||||
|
|
||||||
export const postEnvie =
|
export const sendAddEnvie =
|
||||||
(envieWithoutId: EnvieWithoutId): AppThunk =>
|
(envieWithoutId: EnvieWithoutId): AppThunk =>
|
||||||
async (dispatch) => {
|
async (dispatch) => {
|
||||||
dispatch(getRequesting())
|
dispatch(getRequesting())
|
||||||
|
|
||||||
const { error, data } = await addEnvie(envieWithoutId)
|
const { error, data } = await envieAdd(envieWithoutId)
|
||||||
|
|
||||||
if (error) {
|
if (error) {
|
||||||
dispatch(getFailure(error.message))
|
dispatch(getFailure(error.message))
|
||||||
|
@ -2,7 +2,7 @@ import { PayloadAction, createSlice, createEntityAdapter } from "@reduxjs/toolki
|
|||||||
import { toast } from "react-toastify"
|
import { toast } from "react-toastify"
|
||||||
|
|
||||||
import { StateRequest } from "./utils"
|
import { StateRequest } from "./utils"
|
||||||
import { Envie, getEnvieList } from "../services/envies"
|
import { Envie, envieListGet } from "../services/envies"
|
||||||
import { AppThunk, AppState } from "."
|
import { AppThunk, AppState } from "."
|
||||||
|
|
||||||
const envieAdapter = createEntityAdapter<Envie>({
|
const envieAdapter = createEntityAdapter<Envie>({
|
||||||
@ -35,7 +35,7 @@ export const { getRequesting, getSuccess, getFailure } = envieList.actions
|
|||||||
export const fetchEnvieList = (): AppThunk => async (dispatch) => {
|
export const fetchEnvieList = (): AppThunk => async (dispatch) => {
|
||||||
dispatch(getRequesting())
|
dispatch(getRequesting())
|
||||||
|
|
||||||
const { error, data } = await getEnvieList()
|
const { error, data } = await envieListGet()
|
||||||
|
|
||||||
if (error) {
|
if (error) {
|
||||||
dispatch(getFailure(error.message))
|
dispatch(getFailure(error.message))
|
||||||
|
@ -2,7 +2,7 @@ import { PayloadAction, createSlice } from "@reduxjs/toolkit"
|
|||||||
import { toast } from "react-toastify"
|
import { toast } from "react-toastify"
|
||||||
|
|
||||||
import { StateRequest } from "./utils"
|
import { StateRequest } from "./utils"
|
||||||
import { Membre, getMembre } from "../services/membres"
|
import { Membre, membreGet } from "../services/membres"
|
||||||
import { AppThunk, AppState } from "."
|
import { AppThunk, AppState } from "."
|
||||||
|
|
||||||
type StateMembre = { entity?: Membre } & StateRequest
|
type StateMembre = { entity?: Membre } & StateRequest
|
||||||
@ -37,7 +37,7 @@ export const fetchMembreData =
|
|||||||
async (dispatch) => {
|
async (dispatch) => {
|
||||||
dispatch(getRequesting())
|
dispatch(getRequesting())
|
||||||
|
|
||||||
const { error, data } = await getMembre(id)
|
const { error, data } = await membreGet(id)
|
||||||
|
|
||||||
if (error) {
|
if (error) {
|
||||||
dispatch(getFailure(error.message))
|
dispatch(getFailure(error.message))
|
||||||
|
@ -2,7 +2,7 @@ import { PayloadAction, createSlice, createEntityAdapter } from "@reduxjs/toolki
|
|||||||
import { toast } from "react-toastify"
|
import { toast } from "react-toastify"
|
||||||
|
|
||||||
import { StateRequest } from "./utils"
|
import { StateRequest } from "./utils"
|
||||||
import { Membre, getMembreList } from "../services/membres"
|
import { Membre, membreListGet } from "../services/membres"
|
||||||
import { AppThunk, AppState } from "."
|
import { AppThunk, AppState } from "."
|
||||||
|
|
||||||
const membreAdapter = createEntityAdapter<Membre>()
|
const membreAdapter = createEntityAdapter<Membre>()
|
||||||
@ -35,7 +35,7 @@ export const { getRequesting, getSuccess, getFailure } = membreList.actions
|
|||||||
export const fetchMembreList = (): AppThunk => async (dispatch) => {
|
export const fetchMembreList = (): AppThunk => async (dispatch) => {
|
||||||
dispatch(getRequesting())
|
dispatch(getRequesting())
|
||||||
|
|
||||||
const { error, data } = await getMembreList()
|
const { error, data } = await membreListGet()
|
||||||
|
|
||||||
if (error) {
|
if (error) {
|
||||||
dispatch(getFailure(error.message))
|
dispatch(getFailure(error.message))
|
||||||
|
65
src/store/membreSet.ts
Normal file
65
src/store/membreSet.ts
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
import { PayloadAction, createSlice, createEntityAdapter } from "@reduxjs/toolkit"
|
||||||
|
import { toast } from "react-toastify"
|
||||||
|
|
||||||
|
import { StateRequest } from "./utils"
|
||||||
|
import { Membre, membreSet } from "../services/membres"
|
||||||
|
import { AppThunk } from "."
|
||||||
|
|
||||||
|
const membreAdapter = createEntityAdapter<Membre>({
|
||||||
|
selectId: (membre) => membre.id,
|
||||||
|
})
|
||||||
|
|
||||||
|
const membreSetSlice = createSlice({
|
||||||
|
name: "membreSet",
|
||||||
|
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 membreSetSlice.reducer
|
||||||
|
export const { getRequesting, getSuccess, getFailure } = membreSetSlice.actions
|
||||||
|
|
||||||
|
export const sendMembreSet =
|
||||||
|
(membre: Membre): AppThunk =>
|
||||||
|
async (dispatch) => {
|
||||||
|
dispatch(getRequesting())
|
||||||
|
|
||||||
|
const { error, data } = await membreSet(membre)
|
||||||
|
|
||||||
|
if (error) {
|
||||||
|
dispatch(getFailure(error.message))
|
||||||
|
toast.error(`Erreur lors de la modification d'un membre: ${error.message}`, {
|
||||||
|
position: "top-center",
|
||||||
|
autoClose: 6000,
|
||||||
|
hideProgressBar: true,
|
||||||
|
closeOnClick: true,
|
||||||
|
pauseOnHover: true,
|
||||||
|
draggable: true,
|
||||||
|
progress: undefined,
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
dispatch(getSuccess(data as Membre))
|
||||||
|
toast.success("Membre modifié !", {
|
||||||
|
position: "top-center",
|
||||||
|
autoClose: 3000,
|
||||||
|
hideProgressBar: true,
|
||||||
|
closeOnClick: true,
|
||||||
|
pauseOnHover: true,
|
||||||
|
draggable: true,
|
||||||
|
progress: undefined,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user