mirror of
https://github.com/Paris-est-Ludique/intranet.git
synced 2025-06-09 09:04:20 +02:00
days wishes components
This commit is contained in:
parent
6d0134cb63
commit
3fd6741a78
@ -1,10 +1,31 @@
|
|||||||
import { FC, memo, useCallback, useState } from "react"
|
import { FC, memo, useCallback, useEffect, useRef, useState } from "react"
|
||||||
import classnames from "classnames"
|
import classnames from "classnames"
|
||||||
import { daysChoice, daysChoiceSelectionDefaultState } from "./days.utils"
|
import get from "lodash/get"
|
||||||
import styles from "./styles.module.scss"
|
import styles from "./styles.module.scss"
|
||||||
|
import {
|
||||||
|
daysChoice,
|
||||||
|
daysChoiceSelectionDefaultState,
|
||||||
|
selectionChoices,
|
||||||
|
useUserDayWishes,
|
||||||
|
} from "./days.utils"
|
||||||
|
|
||||||
const DayWishes: FC = (): JSX.Element | null => {
|
const DayWishes: FC = (): JSX.Element | null => {
|
||||||
const [selection, setSelection] = useState(daysChoiceSelectionDefaultState)
|
const [selection, setSelection] = useState(daysChoiceSelectionDefaultState)
|
||||||
|
const commentRef = useRef<HTMLTextAreaElement | null>(null)
|
||||||
|
const [userWishes, saveWishes] = useUserDayWishes()
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!userWishes) return
|
||||||
|
const newSelection = get(userWishes, "dayWishes", []).reduce(
|
||||||
|
(acc: selectionChoices, day: string) => ({
|
||||||
|
...acc,
|
||||||
|
[day]: true,
|
||||||
|
}),
|
||||||
|
daysChoice
|
||||||
|
)
|
||||||
|
setSelection(newSelection)
|
||||||
|
}, [setSelection, userWishes])
|
||||||
|
|
||||||
const onChoiceClick = useCallback(
|
const onChoiceClick = useCallback(
|
||||||
(id) => {
|
(id) => {
|
||||||
setSelection({
|
setSelection({
|
||||||
@ -14,24 +35,41 @@ const DayWishes: FC = (): JSX.Element | null => {
|
|||||||
},
|
},
|
||||||
[selection, setSelection]
|
[selection, setSelection]
|
||||||
)
|
)
|
||||||
|
const onChoiceSubmit = useCallback(() => {
|
||||||
|
const comment = get(commentRef, "current.value", "")
|
||||||
|
const days = daysChoice.map(({ id }) => id).filter((id) => selection[id])
|
||||||
|
saveWishes(days, comment)
|
||||||
|
}, [selection, commentRef, saveWishes])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ul className={styles.dayWishes}>
|
<div className={styles.dayWishes}>
|
||||||
{daysChoice.map(({ id, label }) => (
|
<div className={styles.dayWishesTitle}>Jours de présence</div>
|
||||||
<li key={id} className={styles.dayWishesItem}>
|
<ul className={styles.dayWishesList}>
|
||||||
<button
|
{daysChoice.map(({ id, label }) => (
|
||||||
type="button"
|
<li key={id} className={styles.dayWishesItem}>
|
||||||
onClick={() => onChoiceClick(id)}
|
<button
|
||||||
className={classnames(
|
type="button"
|
||||||
styles.dayWishesButton,
|
onClick={() => onChoiceClick(id)}
|
||||||
selection[id] && styles.active
|
className={classnames(
|
||||||
)}
|
styles.dayWishesButton,
|
||||||
>
|
selection[id] && styles.active
|
||||||
{label}
|
)}
|
||||||
</button>
|
>
|
||||||
</li>
|
{label}
|
||||||
))}
|
</button>
|
||||||
</ul>
|
</li>
|
||||||
|
))}
|
||||||
|
</ul>
|
||||||
|
<div className={styles.dayWishCommentWrapper}>
|
||||||
|
<label htmlFor="day-choice-comment">Commentaires</label>
|
||||||
|
<textarea id="day-choice-comment" ref={commentRef} />
|
||||||
|
</div>
|
||||||
|
<div className={styles.dayWishesButtonWrapper}>
|
||||||
|
<button type="submit" onClick={onChoiceSubmit}>
|
||||||
|
Enregistrer
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,3 +1,10 @@
|
|||||||
|
import { shallowEqual, useSelector } from "react-redux"
|
||||||
|
import { useCallback } from "react"
|
||||||
|
import { selectUserJwtToken } from "../../../store/auth"
|
||||||
|
import { AppState } from "../../../store"
|
||||||
|
import { fetchVolunteerDayWishesSet } from "../../../store/volunteerDayWishesSet"
|
||||||
|
import useAction from "../../../utils/useAction"
|
||||||
|
|
||||||
const daysUtils = ["Jeudi", "Vendredi", "Samedi", "Dimanche", "Lundi"]
|
const daysUtils = ["Jeudi", "Vendredi", "Samedi", "Dimanche", "Lundi"]
|
||||||
|
|
||||||
export const daysChoice = daysUtils.map((label) => ({
|
export const daysChoice = daysUtils.map((label) => ({
|
||||||
@ -5,7 +12,7 @@ export const daysChoice = daysUtils.map((label) => ({
|
|||||||
label,
|
label,
|
||||||
}))
|
}))
|
||||||
|
|
||||||
interface selectionChoices {
|
export interface selectionChoices {
|
||||||
[key: string]: boolean
|
[key: string]: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -13,3 +20,26 @@ export const daysChoiceSelectionDefaultState = daysChoice.reduce((state, { id })
|
|||||||
state[id] = false
|
state[id] = false
|
||||||
return state
|
return state
|
||||||
}, <selectionChoices>{})
|
}, <selectionChoices>{})
|
||||||
|
|
||||||
|
export const useUserDayWishes = (): [any, any] => {
|
||||||
|
const save = useAction(fetchVolunteerDayWishesSet)
|
||||||
|
const jwtToken = useSelector(selectUserJwtToken)
|
||||||
|
const userWishes = useSelector(
|
||||||
|
(state: AppState) => state.volunteerDayWishesSet?.entity,
|
||||||
|
shallowEqual
|
||||||
|
)
|
||||||
|
|
||||||
|
const saveWishes = useCallback(
|
||||||
|
(days, comment) => {
|
||||||
|
if (!userWishes) return
|
||||||
|
save(jwtToken, 0, {
|
||||||
|
id: userWishes.id,
|
||||||
|
dayWishes: days,
|
||||||
|
dayWishesComment: comment,
|
||||||
|
})
|
||||||
|
},
|
||||||
|
[userWishes, save, jwtToken]
|
||||||
|
)
|
||||||
|
|
||||||
|
return [userWishes, saveWishes]
|
||||||
|
}
|
||||||
|
@ -2,6 +2,16 @@
|
|||||||
@import "../../../theme/mixins";
|
@import "../../../theme/mixins";
|
||||||
|
|
||||||
.dayWishes {
|
.dayWishes {
|
||||||
|
width: 470px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dayWishesTitle {
|
||||||
|
padding: 4px;
|
||||||
|
font-weight: bold;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dayWishesList {
|
||||||
@include clear-ul-style;
|
@include clear-ul-style;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -12,7 +22,7 @@
|
|||||||
|
|
||||||
.dayWishesButton {
|
.dayWishesButton {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
padding: 4px;
|
padding: 5px 0 4px;
|
||||||
border: 0;
|
border: 0;
|
||||||
border-radius: 0;
|
border-radius: 0;
|
||||||
width: 90px;
|
width: 90px;
|
||||||
@ -26,3 +36,25 @@
|
|||||||
background-color: $color-black;
|
background-color: $color-black;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.dayWishCommentWrapper {
|
||||||
|
margin: 6px 0;
|
||||||
|
|
||||||
|
label {
|
||||||
|
display: block;
|
||||||
|
padding-left: 4px;
|
||||||
|
}
|
||||||
|
textarea {
|
||||||
|
width: 100%;
|
||||||
|
height: 50px;
|
||||||
|
padding: 5px;
|
||||||
|
border: 1px solid $color-grey-light;
|
||||||
|
background-color: $color-grey-lighter;
|
||||||
|
outline: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.dayWishesButtonWrapper {
|
||||||
|
margin-bottom: 10px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
@ -1,90 +1,25 @@
|
|||||||
import { FC, memo, useCallback, useEffect, useState } from "react"
|
import { FC, memo } from "react"
|
||||||
import { RouteComponentProps } from "react-router-dom"
|
import { RouteComponentProps } from "react-router-dom"
|
||||||
import { useSelector, shallowEqual, useDispatch } from "react-redux"
|
import { useSelector } from "react-redux"
|
||||||
|
|
||||||
import { AppState, AppThunk } from "../../store"
|
import { AppThunk } from "../../store"
|
||||||
import {
|
import { fetchVolunteerDayWishesSetIfNeed } from "../../store/volunteerDayWishesSet"
|
||||||
fetchVolunteerDayWishesSet,
|
|
||||||
fetchVolunteerDayWishesSetIfNeed,
|
|
||||||
} from "../../store/volunteerDayWishesSet"
|
|
||||||
import { VolunteerDayWishes } from "../../services/volunteers"
|
|
||||||
import { selectUserJwtToken } from "../../store/auth"
|
import { selectUserJwtToken } from "../../store/auth"
|
||||||
import DayWishes from "../../components/VolunteerBoard/DayWishes/DayWishes"
|
import DayWishes from "../../components/VolunteerBoard/DayWishes/DayWishes"
|
||||||
|
import styles from "./styles.module.scss"
|
||||||
|
|
||||||
export type Props = RouteComponentProps
|
export type Props = RouteComponentProps
|
||||||
|
|
||||||
let prevWishes: VolunteerDayWishes | undefined
|
|
||||||
|
|
||||||
const HomePage: FC<Props> = (): JSX.Element => {
|
const HomePage: FC<Props> = (): JSX.Element => {
|
||||||
const dispatch = useDispatch()
|
|
||||||
const jwtToken = useSelector(selectUserJwtToken)
|
const jwtToken = useSelector(selectUserJwtToken)
|
||||||
|
|
||||||
const wishesForm = useSelector((state: AppState) => {
|
|
||||||
const wishes = state.volunteerDayWishesSet?.entity
|
|
||||||
if (wishes) {
|
|
||||||
prevWishes = wishes
|
|
||||||
return wishes
|
|
||||||
}
|
|
||||||
return prevWishes
|
|
||||||
}, shallowEqual)
|
|
||||||
|
|
||||||
const [dayWishes, setDayWishes] = useState(wishesForm?.dayWishes.join(",") || "")
|
|
||||||
const [dayWishesComment, setDayWishesComment] = useState(wishesForm?.dayWishesComment || "")
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
setDayWishes(wishesForm?.dayWishes.join(",") || "")
|
|
||||||
setDayWishesComment(wishesForm?.dayWishesComment || "")
|
|
||||||
}, [wishesForm])
|
|
||||||
|
|
||||||
const onDayWishesChanged = (e: React.ChangeEvent<HTMLInputElement>) =>
|
|
||||||
setDayWishes(e.target.value)
|
|
||||||
const onDayWishesCommentChanged = (e: React.ChangeEvent<HTMLInputElement>) =>
|
|
||||||
setDayWishesComment(e.target.value)
|
|
||||||
|
|
||||||
const onSubmit = useCallback(
|
|
||||||
(event: React.SyntheticEvent): void => {
|
|
||||||
event.preventDefault()
|
|
||||||
if (!wishesForm) {
|
|
||||||
console.error("NO FORM WISHES RECEIVED")
|
|
||||||
return // Form should not even appear if this happens
|
|
||||||
}
|
|
||||||
dispatch(
|
|
||||||
fetchVolunteerDayWishesSet(jwtToken, 0, {
|
|
||||||
id: wishesForm.id,
|
|
||||||
dayWishes: (dayWishes || "").split(","),
|
|
||||||
dayWishesComment,
|
|
||||||
})
|
|
||||||
)
|
|
||||||
},
|
|
||||||
[dispatch, jwtToken, wishesForm, dayWishes, dayWishesComment]
|
|
||||||
)
|
|
||||||
|
|
||||||
if (jwtToken === undefined) return <p>Loading...</p>
|
if (jwtToken === undefined) return <p>Loading...</p>
|
||||||
|
|
||||||
if (jwtToken) {
|
if (jwtToken) {
|
||||||
return (
|
return (
|
||||||
<div>
|
<div className={styles.dayWishPage}>
|
||||||
<DayWishes />
|
<div className={styles.dayWisContent}>
|
||||||
<form>
|
<DayWishes />
|
||||||
<input
|
</div>
|
||||||
type="text"
|
|
||||||
id="dayWishes"
|
|
||||||
required
|
|
||||||
value={dayWishes}
|
|
||||||
onChange={onDayWishesChanged}
|
|
||||||
/>
|
|
||||||
<br />
|
|
||||||
<input
|
|
||||||
type="text"
|
|
||||||
id="dayWishesComment"
|
|
||||||
required
|
|
||||||
value={dayWishesComment}
|
|
||||||
onChange={onDayWishesCommentChanged}
|
|
||||||
/>
|
|
||||||
<button type="button" onClick={onSubmit}>
|
|
||||||
Envoyer
|
|
||||||
</button>
|
|
||||||
</form>
|
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -1 +1,9 @@
|
|||||||
@import "../../theme/mixins";
|
@import "../../theme/mixins";
|
||||||
|
|
||||||
|
.dayWishPage {
|
||||||
|
@include page-wrapper-center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dayWisContent {
|
||||||
|
@include page-content-wrapper(800px);
|
||||||
|
}
|
||||||
|
@ -3,7 +3,9 @@ $color-black: #000;
|
|||||||
$color-orange: #ea4d0a;
|
$color-orange: #ea4d0a;
|
||||||
$color-yellow: #fdd137;
|
$color-yellow: #fdd137;
|
||||||
$color-grey-dark: #555;
|
$color-grey-dark: #555;
|
||||||
|
$color-grey-medium: #999;
|
||||||
$color-grey-light: #ccc;
|
$color-grey-light: #ccc;
|
||||||
|
$color-grey-lighter: #eee;
|
||||||
|
|
||||||
$border-large: 4px solid $color-black;
|
$border-large: 4px solid $color-black;
|
||||||
$border-thin: 2px solid $color-black;
|
$border-thin: 2px solid $color-black;
|
||||||
|
11
src/utils/useAction.ts
Normal file
11
src/utils/useAction.ts
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
import { useDispatch } from "react-redux"
|
||||||
|
|
||||||
|
const useAction = (action: (...args: any[]) => any): any => {
|
||||||
|
const dispatch = useDispatch()
|
||||||
|
|
||||||
|
return (...args: any[]) => {
|
||||||
|
dispatch(action(...args))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default useAction
|
Loading…
x
Reference in New Issue
Block a user