From 88d6c44eecf82762d70ce36bcbab1b5853cd1815 Mon Sep 17 00:00:00 2001 From: Arnaud AMBROSELLI Date: Mon, 19 Feb 2024 14:35:03 +0100 Subject: [PATCH 1/2] =?UTF-8?q?feat:=20pouvoir=20filtrer=20par=20actions?= =?UTF-8?q?=20cr=C3=A9=C3=A9es=20le?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- dashboard/src/components/ActionModal.js | 19 ++- .../src/components/ActionsSortableList.js | 15 ++- dashboard/src/components/ConsultationModal.js | 4 +- .../ActionsOrConsultationsReport.js | 127 ++++++++++++++---- dashboard/src/scenes/report/view.js | 74 +++++++--- 5 files changed, 178 insertions(+), 61 deletions(-) diff --git a/dashboard/src/components/ActionModal.js b/dashboard/src/components/ActionModal.js index 30b728d2f..82a329d50 100644 --- a/dashboard/src/components/ActionModal.js +++ b/dashboard/src/components/ActionModal.js @@ -4,7 +4,7 @@ import { useRecoilValue, useSetRecoilState } from 'recoil'; import { useHistory, useLocation } from 'react-router-dom'; import { actionsState, allowedActionFieldsInHistory, CANCEL, DONE, prepareActionForEncryption, TODO } from '../recoil/actions'; import { currentTeamState, organisationState, teamsState, userState } from '../recoil/auth'; -import { dayjsInstance, now, outOfBoundariesDate } from '../services/date'; +import { dayjsInstance, formatDateWithNameOfDay, now, outOfBoundariesDate } from '../services/date'; import API from '../services/api'; import SelectPerson from './SelectPerson'; import SelectStatus from './SelectStatus'; @@ -274,15 +274,12 @@ function ActionContent({ onClose, action, personId = null, personIds = null, isM const body = { ...data }; body.teams = Array.isArray(data.teams) ? data.teams : [data.team]; if (!data.teams?.length) return toast.error('Une action doit être associée à au moins une équipe.'); - const statusChanged = data.status && action.status !== data.status; - if (statusChanged) { - if ([DONE, CANCEL].includes(data.status)) { - // When status changed to finished (done, cancel) completedAt we set it to now if not set. - body.completedAt = data.completedAt || now(); - } else { - // When status just changed to "todo" we set completedAt to null (since it's not done yet). - body.completedAt = null; - } + if ([DONE, CANCEL].includes(data.status)) { + // When status changed to finished (done, cancel) completedAt we set it to now if not set. + body.completedAt = data.completedAt || now(); + } else { + // When status just changed to "todo" we set completedAt to null (since it's not done yet). + body.completedAt = null; } if (data.completedAt && outOfBoundariesDate(data.completedAt)) return toast.error('La date de complétion est hors limites (entre 1900 et 2100)'); if (data.dueAt && outOfBoundariesDate(data.dueAt)) return toast.error("La date d'échéance est hors limites (entre 1900 et 2100)"); @@ -350,7 +347,7 @@ function ActionContent({ onClose, action, personId = null, personIds = null, isM ` (créée par ${name})`} + wrapper={(name) => ` (créée par ${name} le ${formatDateWithNameOfDay(action.createdAt)})`} /> )} diff --git a/dashboard/src/components/ActionsSortableList.js b/dashboard/src/components/ActionsSortableList.js index 7e380a8c2..e0db4d041 100644 --- a/dashboard/src/components/ActionsSortableList.js +++ b/dashboard/src/components/ActionsSortableList.js @@ -20,7 +20,7 @@ import useSearchParamState from '../services/useSearchParamState'; import DescriptionIcon from './DescriptionIcon'; import { AgendaMutedIcon } from '../assets/icons/AgendaMutedIcon'; -const ActionsSortableList = ({ data, limit }) => { +const ActionsSortableList = ({ data, limit, showCreatedAt }) => { useTitle('Agenda'); const history = useHistory(); const user = useRecoilValue(userState); @@ -154,7 +154,18 @@ const ActionsSortableList = ({ data, limit }) => { ); }, }, - ]} + { + title: 'Créée le', + dataKey: 'createdAt', + onSortOrder: setSortOrder, + onSortBy: setSortBy, + sortBy, + sortOrder, + render: (action) => { + return ; + }, + }, + ].filter((e) => showCreatedAt || e.dataKey !== 'createdAt')} /> {limit > 0 && setPage(page, true)} />} diff --git a/dashboard/src/components/ConsultationModal.js b/dashboard/src/components/ConsultationModal.js index 859ca68a0..e2b0ca9c0 100644 --- a/dashboard/src/components/ConsultationModal.js +++ b/dashboard/src/components/ConsultationModal.js @@ -13,7 +13,7 @@ import { prepareConsultationForEncryption, } from '../recoil/consultations'; import API from '../services/api'; -import { dayjsInstance } from '../services/date'; +import { dayjsInstance, formatDateWithNameOfDay } from '../services/date'; import useCreateReportAtDateIfNotExist from '../services/useCreateReportAtDateIfNotExist'; import CustomFieldInput from './CustomFieldInput'; import { modalConfirmState } from './ModalConfirm'; @@ -240,7 +240,7 @@ function ConsultationContent({ personId, consultation, date, onClose }) { ` (créée par ${name})`} + wrapper={(name) => ` (créée par ${name} le ${formatDateWithNameOfDay(consultation.createdAt)})`} /> )} diff --git a/dashboard/src/scenes/report/components/ActionsOrConsultationsReport.js b/dashboard/src/scenes/report/components/ActionsOrConsultationsReport.js index 420c96c03..ae5fd5257 100644 --- a/dashboard/src/scenes/report/components/ActionsOrConsultationsReport.js +++ b/dashboard/src/scenes/report/components/ActionsOrConsultationsReport.js @@ -1,5 +1,5 @@ import { useState } from 'react'; -import { mappedIdsToLabels } from '../../../recoil/actions'; +import { CANCEL, DONE, TODO, mappedIdsToLabels } from '../../../recoil/actions'; import { useHistory } from 'react-router-dom'; import SelectCustom from '../../../components/SelectCustom'; import { ModalHeader, ModalBody, ModalContainer, ModalFooter } from '../../../components/tailwind/Modal'; @@ -11,13 +11,33 @@ import { useRecoilValue } from 'recoil'; import { userState } from '../../../recoil/auth'; import { dayjsInstance } from '../../../services/date'; -export const ActionsOrConsultationsReport = ({ actions, consultations, period }) => { +export const ActionsOrConsultationsReport = ({ + actionsDueOrCompletedAt, + actionsCreatedAt, + consultationsDueOrCompletedAt, + consultationsCreatedAt, + period, +}) => { const [activeTab, setActiveTab] = useLocalStorage('reports-actions-consultation-toggle', 'Actions'); const [fullScreen, setFullScreen] = useState(false); - const [filterStatus, setFilterStatus] = useState([]); - const filteredActions = actions.filter((item) => !filterStatus.length || filterStatus.includes(item.status)); - const filteredConsultations = consultations.filter((item) => !filterStatus.length || filterStatus.includes(item.status)); - const data = activeTab.includes('Actions') ? actions : consultations; + const [filters, setFilters] = useLocalStorage('reports-actions-consultation-filter', []); // TODO, DONE CANCEL createdOnPeriod + + const filterStatus = filters.filter((f) => f !== 'createdOnPeriod'); + + const showCreatedAt = filters.includes('createdOnPeriod'); + + const actions = showCreatedAt ? actionsCreatedAt : actionsDueOrCompletedAt; + const consultations = showCreatedAt ? consultationsCreatedAt : consultationsDueOrCompletedAt; + + const filteredActionsDueOrCompletedAt = actionsDueOrCompletedAt.filter((item) => !filterStatus.length || filterStatus.includes(item.status)); + const filteredActionsCreatedAt = actionsCreatedAt.filter((item) => !filterStatus.length || filterStatus.includes(item.status)); + const filteredActions = showCreatedAt ? filteredActionsCreatedAt : filteredActionsDueOrCompletedAt; + const filteredConsultationsDueOrCompletedAt = consultationsDueOrCompletedAt.filter( + (item) => !filterStatus.length || filterStatus.includes(item.status) + ); + const filteredConsultationsCreatedAt = consultationsCreatedAt.filter((item) => !filterStatus.length || filterStatus.includes(item.status)); + const filteredConsultations = showCreatedAt ? filteredConsultationsCreatedAt : filteredConsultationsDueOrCompletedAt; + const unFilteredData = activeTab.includes('Actions') ? actions : consultations; const filteredData = activeTab.includes('Actions') ? filteredActions : filteredConsultations; const history = useHistory(); const user = useRecoilValue(userState); @@ -28,6 +48,8 @@ export const ActionsOrConsultationsReport = ({ actions, consultations, period }) ? [`Actions (${filteredActions.length})`, `Consultations (${filteredConsultations.length})`] : [`Actions (${filteredActions.length})`]; + const periodIsOneDay = dayjsInstance(period.startDate).isSame(period.endDate, 'day'); + return ( <>
@@ -61,27 +83,33 @@ export const ActionsOrConsultationsReport = ({ actions, consultations, period }) 'tw-h-6 tw-w-6 tw-rounded-full tw-transition hover:tw-scale-125 disabled:tw-cursor-not-allowed disabled:tw-opacity-30', activeTab.includes('Actions') ? 'tw-text-main' : 'tw-text-blue-900', ].join(' ')} - disabled={!data.length} + disabled={!unFilteredData.length} onClick={() => setFullScreen(true)}>
- +
+ {/* PRINTONLY */} + + + {/* END PRINTONLY */} setFullScreen(false)}> setFullScreen(false)}>
- +
- +