mirror of
https://github.com/Paris-est-Ludique/intranet.git
synced 2025-06-08 08:34: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 { daysChoice, daysChoiceSelectionDefaultState } from "./days.utils"
|
||||
import get from "lodash/get"
|
||||
import styles from "./styles.module.scss"
|
||||
import {
|
||||
daysChoice,
|
||||
daysChoiceSelectionDefaultState,
|
||||
selectionChoices,
|
||||
useUserDayWishes,
|
||||
} from "./days.utils"
|
||||
|
||||
const DayWishes: FC = (): JSX.Element | null => {
|
||||
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(
|
||||
(id) => {
|
||||
setSelection({
|
||||
@ -14,24 +35,41 @@ const DayWishes: FC = (): JSX.Element | null => {
|
||||
},
|
||||
[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 (
|
||||
<ul className={styles.dayWishes}>
|
||||
{daysChoice.map(({ id, label }) => (
|
||||
<li key={id} className={styles.dayWishesItem}>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => onChoiceClick(id)}
|
||||
className={classnames(
|
||||
styles.dayWishesButton,
|
||||
selection[id] && styles.active
|
||||
)}
|
||||
>
|
||||
{label}
|
||||
</button>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
<div className={styles.dayWishes}>
|
||||
<div className={styles.dayWishesTitle}>Jours de présence</div>
|
||||
<ul className={styles.dayWishesList}>
|
||||
{daysChoice.map(({ id, label }) => (
|
||||
<li key={id} className={styles.dayWishesItem}>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => onChoiceClick(id)}
|
||||
className={classnames(
|
||||
styles.dayWishesButton,
|
||||
selection[id] && styles.active
|
||||
)}
|
||||
>
|
||||
{label}
|
||||
</button>
|
||||
</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"]
|
||||
|
||||
export const daysChoice = daysUtils.map((label) => ({
|
||||
@ -5,7 +12,7 @@ export const daysChoice = daysUtils.map((label) => ({
|
||||
label,
|
||||
}))
|
||||
|
||||
interface selectionChoices {
|
||||
export interface selectionChoices {
|
||||
[key: string]: boolean
|
||||
}
|
||||
|
||||
@ -13,3 +20,26 @@ export const daysChoiceSelectionDefaultState = daysChoice.reduce((state, { id })
|
||||
state[id] = false
|
||||
return state
|
||||
}, <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";
|
||||
|
||||
.dayWishes {
|
||||
width: 470px;
|
||||
}
|
||||
|
||||
.dayWishesTitle {
|
||||
padding: 4px;
|
||||
font-weight: bold;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.dayWishesList {
|
||||
@include clear-ul-style;
|
||||
}
|
||||
|
||||
@ -12,7 +22,7 @@
|
||||
|
||||
.dayWishesButton {
|
||||
margin: 0;
|
||||
padding: 4px;
|
||||
padding: 5px 0 4px;
|
||||
border: 0;
|
||||
border-radius: 0;
|
||||
width: 90px;
|
||||
@ -26,3 +36,25 @@
|
||||
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 { useSelector, shallowEqual, useDispatch } from "react-redux"
|
||||
import { useSelector } from "react-redux"
|
||||
|
||||
import { AppState, AppThunk } from "../../store"
|
||||
import {
|
||||
fetchVolunteerDayWishesSet,
|
||||
fetchVolunteerDayWishesSetIfNeed,
|
||||
} from "../../store/volunteerDayWishesSet"
|
||||
import { VolunteerDayWishes } from "../../services/volunteers"
|
||||
import { AppThunk } from "../../store"
|
||||
import { fetchVolunteerDayWishesSetIfNeed } from "../../store/volunteerDayWishesSet"
|
||||
import { selectUserJwtToken } from "../../store/auth"
|
||||
import DayWishes from "../../components/VolunteerBoard/DayWishes/DayWishes"
|
||||
import styles from "./styles.module.scss"
|
||||
|
||||
export type Props = RouteComponentProps
|
||||
|
||||
let prevWishes: VolunteerDayWishes | undefined
|
||||
|
||||
const HomePage: FC<Props> = (): JSX.Element => {
|
||||
const dispatch = useDispatch()
|
||||
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) {
|
||||
return (
|
||||
<div>
|
||||
<DayWishes />
|
||||
<form>
|
||||
<input
|
||||
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 className={styles.dayWishPage}>
|
||||
<div className={styles.dayWisContent}>
|
||||
<DayWishes />
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
@ -1 +1,9 @@
|
||||
@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-yellow: #fdd137;
|
||||
$color-grey-dark: #555;
|
||||
$color-grey-medium: #999;
|
||||
$color-grey-light: #ccc;
|
||||
$color-grey-lighter: #eee;
|
||||
|
||||
$border-large: 4px 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