mirror of
https://github.com/Paris-est-Ludique/intranet.git
synced 2025-06-09 00:54:21 +02:00
add component to display day wishes
This commit is contained in:
parent
bf649aa040
commit
2bfd8d2a7b
@ -1,76 +1,30 @@
|
|||||||
import { FC, memo, useCallback, useEffect, useRef, useState } from "react"
|
import { FC, memo } from "react"
|
||||||
import classnames from "classnames"
|
|
||||||
import get from "lodash/get"
|
import get from "lodash/get"
|
||||||
import set from "lodash/set"
|
|
||||||
import styles from "./styles.module.scss"
|
import styles from "./styles.module.scss"
|
||||||
import {
|
import { getDayLabel, useUserDayWishes } from "../days.utils"
|
||||||
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 [userWishes] = useUserDayWishes()
|
||||||
const commentRef = useRef<HTMLTextAreaElement | null>(null)
|
const dayWishesString = get(userWishes, "dayWishes", []).map(getDayLabel).join(", ")
|
||||||
const [userWishes, saveWishes] = useUserDayWishes()
|
const comment = get(userWishes, "dayWishesComment", "")
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (!userWishes) return
|
|
||||||
console.log("userWishes", userWishes)
|
|
||||||
const newSelection = get(userWishes, "dayWishes", []).reduce(
|
|
||||||
(acc: selectionChoices, day: string) => ({
|
|
||||||
...acc,
|
|
||||||
[day]: true,
|
|
||||||
}),
|
|
||||||
daysChoice
|
|
||||||
)
|
|
||||||
setSelection(newSelection)
|
|
||||||
set(commentRef, "current.value", get(userWishes, "dayWishesComment", ""))
|
|
||||||
}, [setSelection, commentRef, userWishes])
|
|
||||||
|
|
||||||
const onChoiceClick = useCallback(
|
|
||||||
(id) => {
|
|
||||||
setSelection({
|
|
||||||
...selection,
|
|
||||||
[id]: !selection[id],
|
|
||||||
})
|
|
||||||
},
|
|
||||||
[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 (
|
||||||
<div className={styles.dayWishes}>
|
<div className={styles.dayWishes}>
|
||||||
<div className={styles.dayWishesTitle}>Jours de présence</div>
|
<div className={styles.daysLine}>
|
||||||
<ul className={styles.dayWishesList}>
|
<span className={styles.dayLineTitle}>Mes jours de présence :</span>
|
||||||
{daysChoice.map(({ id, label }) => (
|
{dayWishesString && <span>{dayWishesString}</span>}
|
||||||
<li key={id} className={styles.dayWishesItem}>
|
{!dayWishesString && <span>Non renseignés</span>}
|
||||||
<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>
|
||||||
<div className={styles.dayWishesButtonWrapper}>
|
{comment && (
|
||||||
<button type="submit" onClick={onChoiceSubmit}>
|
<div className={styles.commentLine}>
|
||||||
Enregistrer
|
<span className={styles.commentLineTitle}>Mon commentaire :</span>
|
||||||
</button>
|
<span className={styles.commentLineText}>
|
||||||
|
{get(userWishes, "dayWishesComment", "")}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
<div className={styles.editButton}>
|
||||||
|
<button type="button">Modifier</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
@ -2,59 +2,39 @@
|
|||||||
@import "../../../theme/mixins";
|
@import "../../../theme/mixins";
|
||||||
|
|
||||||
.dayWishes {
|
.dayWishes {
|
||||||
width: 470px;
|
@include inner-content-wrapper();
|
||||||
|
|
||||||
|
position: relative;
|
||||||
}
|
}
|
||||||
|
|
||||||
.dayWishesTitle {
|
.daysLine,
|
||||||
padding: 4px;
|
.commentLine {
|
||||||
font-weight: bold;
|
span {
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.dayWishesList {
|
|
||||||
@include clear-ul-style;
|
|
||||||
}
|
|
||||||
|
|
||||||
.dayWishesItem {
|
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
margin: 2px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.dayWishesButton {
|
|
||||||
margin: 0;
|
|
||||||
padding: 5px 0 4px;
|
|
||||||
border: 0;
|
|
||||||
border-radius: 0;
|
|
||||||
width: 90px;
|
|
||||||
text-align: center;
|
|
||||||
color: $color-grey-dark;
|
|
||||||
background-color: $color-grey-light;
|
|
||||||
cursor: pointer;
|
|
||||||
|
|
||||||
&.active {
|
|
||||||
color: $color-yellow;
|
|
||||||
background-color: $color-black;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.dayWishCommentWrapper {
|
.dayLineTitle {
|
||||||
margin: 6px 0;
|
padding-right: 5px;
|
||||||
|
font-weight: bold;
|
||||||
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 {
|
.dayLineEmpty {
|
||||||
margin-bottom: 10px;
|
color: $color-red;
|
||||||
text-align: center;
|
font-style: italic;
|
||||||
|
}
|
||||||
|
|
||||||
|
.commentLineTitle {
|
||||||
|
padding-right: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.commentLineText {
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
|
||||||
|
.editButton {
|
||||||
|
@include vertical-center();
|
||||||
|
|
||||||
|
position: absolute;
|
||||||
|
right: 20px;
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,78 @@
|
|||||||
|
import { FC, memo, useCallback, useEffect, useRef, useState } from "react"
|
||||||
|
import classnames from "classnames"
|
||||||
|
import get from "lodash/get"
|
||||||
|
import set from "lodash/set"
|
||||||
|
import styles from "./styles.module.scss"
|
||||||
|
import {
|
||||||
|
daysChoice,
|
||||||
|
daysChoiceSelectionDefaultState,
|
||||||
|
selectionChoices,
|
||||||
|
useUserDayWishes,
|
||||||
|
} from "../days.utils"
|
||||||
|
|
||||||
|
const DayWishesForm: 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)
|
||||||
|
set(commentRef, "current.value", get(userWishes, "dayWishesComment", ""))
|
||||||
|
}, [setSelection, commentRef, userWishes])
|
||||||
|
|
||||||
|
const onChoiceClick = useCallback(
|
||||||
|
(id) => {
|
||||||
|
setSelection({
|
||||||
|
...selection,
|
||||||
|
[id]: !selection[id],
|
||||||
|
})
|
||||||
|
},
|
||||||
|
[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 (
|
||||||
|
<div className={styles.dayWishesForm}>
|
||||||
|
<div className={styles.dayWishesTitle}>Mes 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">Un commentaire, une précision ?</label>
|
||||||
|
<textarea id="day-choice-comment" ref={commentRef} />
|
||||||
|
</div>
|
||||||
|
<div className={styles.dayWishesButtonWrapper}>
|
||||||
|
<button type="submit" onClick={onChoiceSubmit}>
|
||||||
|
Enregistrer
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default memo(DayWishesForm)
|
60
src/components/VolunteerBoard/DayWishesForm/styles.module.scss
Executable file
60
src/components/VolunteerBoard/DayWishesForm/styles.module.scss
Executable file
@ -0,0 +1,60 @@
|
|||||||
|
@import "../../../theme/variables";
|
||||||
|
@import "../../../theme/mixins";
|
||||||
|
|
||||||
|
.dayWishesForm {
|
||||||
|
width: 470px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dayWishesTitle {
|
||||||
|
padding: 4px;
|
||||||
|
font-weight: bold;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dayWishesList {
|
||||||
|
@include clear-ul-style;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dayWishesItem {
|
||||||
|
display: inline-block;
|
||||||
|
margin: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dayWishesButton {
|
||||||
|
margin: 0;
|
||||||
|
padding: 5px 0 4px;
|
||||||
|
border: 0;
|
||||||
|
border-radius: 0;
|
||||||
|
width: 90px;
|
||||||
|
text-align: center;
|
||||||
|
color: $color-grey-dark;
|
||||||
|
background-color: $color-grey-light;
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
|
&.active {
|
||||||
|
color: $color-yellow;
|
||||||
|
background-color: $color-black;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.dayWishCommentWrapper {
|
||||||
|
margin: 6px 0;
|
||||||
|
|
||||||
|
label {
|
||||||
|
display: block;
|
||||||
|
padding: 6px 0 2px 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,9 +1,9 @@
|
|||||||
import { shallowEqual, useSelector } from "react-redux"
|
import { shallowEqual, useSelector } from "react-redux"
|
||||||
import { useCallback } from "react"
|
import { useCallback } from "react"
|
||||||
import { selectUserJwtToken } from "../../../store/auth"
|
import { selectUserJwtToken } from "../../store/auth"
|
||||||
import { AppState } from "../../../store"
|
import { AppState } from "../../store"
|
||||||
import { fetchVolunteerDayWishesSet } from "../../../store/volunteerDayWishesSet"
|
import { fetchVolunteerDayWishesSet } from "../../store/volunteerDayWishesSet"
|
||||||
import useAction from "../../../utils/useAction"
|
import useAction from "../../utils/useAction"
|
||||||
|
|
||||||
const daysUtils = ["Jeudi", "Vendredi", "Samedi", "Dimanche", "Lundi"]
|
const daysUtils = ["Jeudi", "Vendredi", "Samedi", "Dimanche", "Lundi"]
|
||||||
|
|
||||||
@ -43,3 +43,8 @@ export const useUserDayWishes = (): [any, any] => {
|
|||||||
|
|
||||||
return [userWishes, saveWishes]
|
return [userWishes, saveWishes]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const getDayLabel = (id: string): string => {
|
||||||
|
const matchingDay = daysChoice.find((day) => day.id === id)
|
||||||
|
return matchingDay ? matchingDay.label : ""
|
||||||
|
}
|
36
src/pages/Board/Board.tsx
Normal file
36
src/pages/Board/Board.tsx
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
import { FC, memo } from "react"
|
||||||
|
import { RouteComponentProps } from "react-router-dom"
|
||||||
|
import { useSelector } from "react-redux"
|
||||||
|
|
||||||
|
import { AppThunk } from "../../store"
|
||||||
|
import { fetchVolunteerDayWishesSetIfNeed } from "../../store/volunteerDayWishesSet"
|
||||||
|
import { selectUserJwtToken } from "../../store/auth"
|
||||||
|
import DayWishesForm from "../../components/VolunteerBoard/DayWishesForm/DayWishesForm"
|
||||||
|
import DDayInformations from "../../components/VolunteerBoard/DDayInformations/DDaysInformations"
|
||||||
|
import styles from "./styles.module.scss"
|
||||||
|
import DayWishes from "../../components/VolunteerBoard/DayWishes/DayWishes"
|
||||||
|
|
||||||
|
export type Props = RouteComponentProps
|
||||||
|
|
||||||
|
const BoardPage: FC<Props> = (): JSX.Element => {
|
||||||
|
const jwtToken = useSelector(selectUserJwtToken)
|
||||||
|
|
||||||
|
if (jwtToken === undefined) return <p>Loading...</p>
|
||||||
|
if (jwtToken) {
|
||||||
|
return (
|
||||||
|
<div className={styles.dayWishPage}>
|
||||||
|
<div className={styles.dayWisContent}>
|
||||||
|
<DayWishes />
|
||||||
|
<DayWishesForm />
|
||||||
|
<DDayInformations />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
return <div>Besoin d'être identifié</div>
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fetch server-side data here
|
||||||
|
export const loadData = (): AppThunk[] => [fetchVolunteerDayWishesSetIfNeed()]
|
||||||
|
|
||||||
|
export default memo(BoardPage)
|
16
src/pages/Board/index.tsx
Executable file
16
src/pages/Board/index.tsx
Executable file
@ -0,0 +1,16 @@
|
|||||||
|
import loadable from "@loadable/component"
|
||||||
|
|
||||||
|
import { Loading, ErrorBoundary } from "../../components"
|
||||||
|
import { Props, loadData } from "./Board"
|
||||||
|
|
||||||
|
const BoardPage = loadable(() => import("./Board"), {
|
||||||
|
fallback: <Loading />,
|
||||||
|
})
|
||||||
|
|
||||||
|
export default (props: Props): JSX.Element => (
|
||||||
|
<ErrorBoundary>
|
||||||
|
<BoardPage {...props} />
|
||||||
|
</ErrorBoundary>
|
||||||
|
)
|
||||||
|
|
||||||
|
export { loadData }
|
9
src/pages/Board/styles.module.scss
Executable file
9
src/pages/Board/styles.module.scss
Executable file
@ -0,0 +1,9 @@
|
|||||||
|
@import "../../theme/mixins";
|
||||||
|
|
||||||
|
.dayWishPage {
|
||||||
|
@include page-wrapper-center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dayWisContent {
|
||||||
|
@include page-content-wrapper(800px);
|
||||||
|
}
|
@ -5,7 +5,7 @@ import { useSelector } from "react-redux"
|
|||||||
import { AppThunk } from "../../store"
|
import { AppThunk } from "../../store"
|
||||||
import { fetchVolunteerDayWishesSetIfNeed } from "../../store/volunteerDayWishesSet"
|
import { fetchVolunteerDayWishesSetIfNeed } from "../../store/volunteerDayWishesSet"
|
||||||
import { selectUserJwtToken } from "../../store/auth"
|
import { selectUserJwtToken } from "../../store/auth"
|
||||||
import DayWishes from "../../components/VolunteerBoard/DayWishes/DayWishes"
|
import DayWishes from "../../components/VolunteerBoard/DayWishesForm/DayWishesForm"
|
||||||
import DDayInformations from "../../components/VolunteerBoard/DDayInformations/DDaysInformations"
|
import DDayInformations from "../../components/VolunteerBoard/DDayInformations/DDaysInformations"
|
||||||
import styles from "./styles.module.scss"
|
import styles from "./styles.module.scss"
|
||||||
|
|
||||||
|
@ -4,6 +4,7 @@ import App from "../app"
|
|||||||
import AsyncHome, { loadData as loadHomeData } from "../pages/Home"
|
import AsyncHome, { loadData as loadHomeData } from "../pages/Home"
|
||||||
import AsyncPreRegisterPage, { loadData as loadPreRegisterPage } from "../pages/PreRegister"
|
import AsyncPreRegisterPage, { loadData as loadPreRegisterPage } from "../pages/PreRegister"
|
||||||
import AsyncTeams, { loadData as loadTeamsData } from "../pages/Teams"
|
import AsyncTeams, { loadData as loadTeamsData } from "../pages/Teams"
|
||||||
|
import AsyncBoard, { loadData as loadBoardData } from "../pages/Board"
|
||||||
import AsyncDayWishes, { loadData as loadDayWishesData } from "../pages/DayWishes"
|
import AsyncDayWishes, { loadData as loadDayWishesData } from "../pages/DayWishes"
|
||||||
import AsyncTeamWishes, { loadData as loadTeamWishesData } from "../pages/TeamWishes"
|
import AsyncTeamWishes, { loadData as loadTeamWishesData } from "../pages/TeamWishes"
|
||||||
import AsyncWish, { loadData as loadWishData } from "../pages/Wish"
|
import AsyncWish, { loadData as loadWishData } from "../pages/Wish"
|
||||||
@ -60,6 +61,11 @@ export default [
|
|||||||
component: AsyncWish,
|
component: AsyncWish,
|
||||||
loadData: loadWishData,
|
loadData: loadWishData,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: "/board",
|
||||||
|
component: AsyncBoard,
|
||||||
|
loadData: loadBoardData,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
component: NotFound,
|
component: NotFound,
|
||||||
},
|
},
|
||||||
|
@ -29,8 +29,19 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@mixin inner-content-wrapper() {
|
||||||
|
padding: 10px;
|
||||||
|
border-radius: 5px;
|
||||||
|
background-color: $color-grey-lighter;
|
||||||
|
}
|
||||||
|
|
||||||
@mixin clear-ul-style {
|
@mixin clear-ul-style {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
list-style: none;
|
list-style: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@mixin vertical-center {
|
||||||
|
top: 50%;
|
||||||
|
transform: translateY(-50%);
|
||||||
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
$color-white: #fff;
|
$color-white: #fff;
|
||||||
$color-black: #000;
|
$color-black: #000;
|
||||||
|
$color-red: #f00;
|
||||||
$color-orange: #ea4d0a;
|
$color-orange: #ea4d0a;
|
||||||
$color-yellow: #fdd137;
|
$color-yellow: #fdd137;
|
||||||
$color-grey-dark: #555;
|
$color-grey-dark: #555;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user