From b812177a23999a0c98a1f311fdcc64521dec8b44 Mon Sep 17 00:00:00 2001 From: Christian Date: Fri, 10 Jan 2025 15:43:04 +0100 Subject: [PATCH] fix(pam): uncouple timeline and action - Create a specific pam timeline hook to return only timeline needs - refactor pam components to use the new hook --- .../element/mission-action-item-pam.tsx | 4 +- .../element/mission-action-pam-body.tsx | 15 +- .../components/element/mission-action-pam.tsx | 9 +- .../element/mission-timeline-header-pam.tsx | 15 +- .../element/mission-timeline-item-pam.tsx | 16 +- .../pam/hooks/use-pam-action-registry.tsx | 21 +-- .../pam/hooks/use-pam-timeline-registry.tsx | 148 ++++++++++++++++++ 7 files changed, 197 insertions(+), 31 deletions(-) create mode 100644 frontend/src/v2/features/pam/hooks/use-pam-timeline-registry.tsx diff --git a/frontend/src/v2/features/pam/components/element/mission-action-item-pam.tsx b/frontend/src/v2/features/pam/components/element/mission-action-item-pam.tsx index 8ff5c91d1..7c2d6c82f 100644 --- a/frontend/src/v2/features/pam/components/element/mission-action-item-pam.tsx +++ b/frontend/src/v2/features/pam/components/element/mission-action-item-pam.tsx @@ -15,8 +15,8 @@ interface MissionActionItemPamProps { const MissionActionItemPam: FC = ({ action, missionId, isMissionFinished }) => { const { handleExecuteOnDelay } = useDelay() + const { component } = usePamActionRegistry(action.actionType) const debounceTime = useStore(store, state => state.delayQuery.debounceTime) - const { actionComponent } = usePamActionRegistry(action.actionType) const mutation = useUpdateMissionActionMutation(missionId, action?.id) @@ -29,7 +29,7 @@ const MissionActionItemPam: FC = ({ action, missionId return (
- {actionComponent && createElement(actionComponent, { action, onChange, isMissionFinished })} + {component && createElement(component, { action, onChange, isMissionFinished })}
) } diff --git a/frontend/src/v2/features/pam/components/element/mission-action-pam-body.tsx b/frontend/src/v2/features/pam/components/element/mission-action-pam-body.tsx index 0dc7f8517..f7fa6035d 100644 --- a/frontend/src/v2/features/pam/components/element/mission-action-pam-body.tsx +++ b/frontend/src/v2/features/pam/components/element/mission-action-pam-body.tsx @@ -1,21 +1,22 @@ import { FC } from 'react' -import useGetActionQuery from '../../../common/services/use-mission-action' +import { MissionAction } from '../../../common/types/mission-action' import MissionActionWrapper from '../../../mission-action/components/layout/mission-action-wrapper' import MissionActionItemPam from './mission-action-item-pam' interface MissionActionProps { - actionId?: string missionId: number + isLoading?: boolean + error?: Error | null + action?: MissionAction } -const MissionActionPamBody: FC = ({ missionId, actionId }) => { - const query = useGetActionQuery(missionId, actionId) +const MissionActionPamBody: FC = ({ missionId, error, action, isLoading }) => { return ( ) diff --git a/frontend/src/v2/features/pam/components/element/mission-action-pam.tsx b/frontend/src/v2/features/pam/components/element/mission-action-pam.tsx index 95598100b..4d5629ea5 100644 --- a/frontend/src/v2/features/pam/components/element/mission-action-pam.tsx +++ b/frontend/src/v2/features/pam/components/element/mission-action-pam.tsx @@ -21,7 +21,14 @@ const MissionActionPam: FC = ({ missionId, actionId, status ) } - sectionBody={} + sectionBody={ + + } /> ) } diff --git a/frontend/src/v2/features/pam/components/element/mission-timeline-header-pam.tsx b/frontend/src/v2/features/pam/components/element/mission-timeline-header-pam.tsx index 21d5b342c..603a53e13 100644 --- a/frontend/src/v2/features/pam/components/element/mission-timeline-header-pam.tsx +++ b/frontend/src/v2/features/pam/components/element/mission-timeline-header-pam.tsx @@ -1,13 +1,24 @@ import { FC } from 'react' -import { ModuleType } from '../../../common/types/module-type' +import { useNavigate } from 'react-router-dom' import MissionTimelineHeaderWrapper from '../../../mission-timeline/components/layout/mission-timeline-Header-wrapper' +import { usePamTimelineRegistry } from '../../hooks/use-pam-timeline-registry' interface MissionTimelineHeaderPamProps { missionId: number } const MissionTimelineHeaderPam: FC = ({ missionId }) => { - return + const navigate = useNavigate() + const { timelineDropdownItems } = usePamTimelineRegistry() + const handleOnSubmit = (id?: string) => navigate(`/v2/pam/missions/${missionId}/${id}`) + + return ( + + ) } export default MissionTimelineHeaderPam diff --git a/frontend/src/v2/features/pam/components/element/mission-timeline-item-pam.tsx b/frontend/src/v2/features/pam/components/element/mission-timeline-item-pam.tsx index f9059b02c..06711a6e2 100644 --- a/frontend/src/v2/features/pam/components/element/mission-timeline-item-pam.tsx +++ b/frontend/src/v2/features/pam/components/element/mission-timeline-item-pam.tsx @@ -2,8 +2,9 @@ import { createElement, FC, useEffect, useState } from 'react' import { useParams } from 'react-router-dom' import { ModuleType } from '../../../common/types/module-type' import MissionTimelineItemWrapper from '../../../mission-timeline/components/layout/mission-timeline-item-wrapper' +import { useTimeline } from '../../../mission-timeline/hooks/use-timeline' import { MissionTimelineAction } from '../../../mission-timeline/types/mission-timeline-output' -import { usePamActionRegistry } from '../../hooks/use-pam-action-registry' +import { usePamTimelineRegistry } from '../../hooks/use-pam-timeline-registry' interface MissionTimelineItemPamProps { missionId?: number @@ -13,21 +14,28 @@ interface MissionTimelineItemPamProps { const MissionTimelineItemPam: FC = ({ action, prevAction, missionId }) => { const { actionId } = useParams() + const { isIncomplete } = useTimeline() + const { getTimeline } = usePamTimelineRegistry() const [isSelected, setIsSelected] = useState(false) - const { style, icon, title, timeline, hasStatusTag, isIncomplete } = usePamActionRegistry(action.type) useEffect(() => { setIsSelected(action.id === actionId) }, [action, actionId]) return ( ) } diff --git a/frontend/src/v2/features/pam/hooks/use-pam-action-registry.tsx b/frontend/src/v2/features/pam/hooks/use-pam-action-registry.tsx index 62d416fb8..0ed9daaca 100644 --- a/frontend/src/v2/features/pam/hooks/use-pam-action-registry.tsx +++ b/frontend/src/v2/features/pam/hooks/use-pam-action-registry.tsx @@ -1,30 +1,21 @@ -import { ActionTypeEnum } from '@common/types/env-mission-types' import { ActionRegistryHook, ActionRegistryItem, useActionRegistry } from '../../common/hooks/use-action-registry' +import { ActionType } from '../../common/types/action-type' import MissionActionItemStatus from '../../mission-action/components/elements/mission-action-item-status' -import MissionTimelineItemStatusCard from '../../mission-timeline/components/elements/mission-timeline-item-status-card' type PamActionRegistry = { - [key in ActionTypeEnum]?: ActionRegistryItem + [key in ActionType]?: ActionRegistryItem } + const PAM_ACTION_REGISTRY: PamActionRegistry = { - [ActionTypeEnum.STATUS]: { - hasStatusTag: true, - style: { - minHeight: 0 - }, + [ActionType.STATUS]: { title: 'Statut du navire', - timeline: { - noPadding: true, - dropdownText: 'Ajouter des contrôles', - component: MissionTimelineItemStatusCard - }, - actionComponent: MissionActionItemStatus + component: MissionActionItemStatus } } type PamActionRegistryHook = {} & PamActionRegistry & ActionRegistryHook -export function usePamActionRegistry(actionType: ActionTypeEnum): PamActionRegistryHook { +export function usePamActionRegistry(actionType: ActionType): PamActionRegistryHook { const common = useActionRegistry(actionType) const pam = PAM_ACTION_REGISTRY[actionType] return { ...pam, ...common } diff --git a/frontend/src/v2/features/pam/hooks/use-pam-timeline-registry.tsx b/frontend/src/v2/features/pam/hooks/use-pam-timeline-registry.tsx new file mode 100644 index 000000000..b2d7a0142 --- /dev/null +++ b/frontend/src/v2/features/pam/hooks/use-pam-timeline-registry.tsx @@ -0,0 +1,148 @@ +import { Icon, THEME } from '@mtes-mct/monitor-ui' +import { ActionGroupType, ActionType } from '../../common/types/action-type' +import MissionTimelineItemControlCard from '../../mission-timeline/components/elements/mission-timeline-item-control-card' +import MissionTimelineItemGenericCard from '../../mission-timeline/components/elements/mission-timeline-item-generic-card' +import MissionTimelineItemRescueCard from '../../mission-timeline/components/elements/mission-timeline-item-rescue-card' +import MissionTimelineItemStatusCard from '../../mission-timeline/components/elements/mission-timeline-item-status-card' +import MissionTimelineItemSurveillanceCard from '../../mission-timeline/components/elements/mission-timeline-item-surveillance-card' +import { Timeline, TimelineDropdownItem, TimelineRegistry } from '../../mission-timeline/hooks/use-timeline' + +const TIME_LINE_DROPDOWN_PAM_ITEMS: TimelineDropdownItem[] = [ + { type: ActionType.CONTROL, icon: Icon.ControlUnit, dropdownText: 'Ajouter des contrôles' }, + { type: ActionType.NOTE, icon: Icon.Note, dropdownText: 'Ajouter une note libre' }, + { type: ActionType.RESCUE, icon: Icon.Rescue, dropdownText: 'Ajouter une assistance / sauvetage' }, + { + icon: Icon.More, + type: ActionGroupType.OTHER_GROUP, + dropdownText: 'Ajouter une autre activité de mission', + subItems: [ + { type: ActionType.NAUTICAL_EVENT, dropdownText: 'Sécu de manifestation nautique' }, + { type: ActionType.BAAEM_PERMANENCE, dropdownText: 'Permanence BAAEM' }, + { type: ActionType.VIGIMER, dropdownText: 'Permanence Vigimer' }, + { type: ActionType.ANTI_POLLUTION, dropdownText: 'Opération de lutte anti-pollution' }, + { type: ActionType.ILLEGAL_IMMIGRATION, dropdownText: `Lutte contre l'immigration illégale` }, + { type: ActionType.PUBLIC_ORDER, dropdownText: `Maintien de l'ordre public` }, + { type: ActionType.REPRESENTATION, dropdownText: 'Représentation' } + ] + } +] + +const TIMELINE_PAM_REGISTRY: TimelineRegistry = { + [ActionType.STATUS]: { + noPadding: true, + style: { minHeight: 0 }, + title: 'Statut du navire', + component: MissionTimelineItemStatusCard + }, + [ActionType.CONTROL]: { + style: { backgroundColor: THEME.color.white, borderColor: THEME.color.lightGray }, + title: 'Contrôles', + icon: Icon.ControlUnit, + component: MissionTimelineItemControlCard + }, + [ActionType.SURVEILLANCE]: { + style: { backgroundColor: '#e5e5eb', borderColor: THEME.color.lightGray }, + icon: Icon.Observation, + title: 'Surveillance Environnement', + component: MissionTimelineItemSurveillanceCard + }, + [ActionType.NOTE]: { + style: { backgroundColor: THEME.color.blueYonder25, borderColor: THEME.color.lightGray }, + title: 'Note libre', + icon: Icon.Note, + component: MissionTimelineItemGenericCard + }, + [ActionType.VIGIMER]: { + style: { + backgroundColor: THEME.color.blueGray25, + borderColor: THEME.color.lightGray + }, + icon: Icon.More, + title: 'Permanence Vigimer', + component: MissionTimelineItemGenericCard + }, + [ActionType.NAUTICAL_EVENT]: { + style: { + backgroundColor: THEME.color.blueGray25, + borderColor: THEME.color.lightGray + }, + icon: Icon.More, + title: 'Manifestation nautique', + component: MissionTimelineItemGenericCard + }, + [ActionType.RESCUE]: { + style: { + backgroundColor: THEME.color.goldenPoppy25, + borderColor: THEME.color.blueYonder25 + }, + title: 'Assistance et sauvetage', + icon: Icon.Rescue, + component: MissionTimelineItemRescueCard + }, + [ActionType.REPRESENTATION]: { + style: { + backgroundColor: THEME.color.blueGray25, + borderColor: THEME.color.lightGray + }, + icon: Icon.More, + title: 'Représentation', + component: MissionTimelineItemGenericCard + }, + [ActionType.PUBLIC_ORDER]: { + style: { + backgroundColor: THEME.color.blueGray25, + borderColor: THEME.color.lightGray + }, + icon: Icon.More, + title: `Maintien de l'ordre public`, + component: MissionTimelineItemGenericCard + }, + [ActionType.ANTI_POLLUTION]: { + style: { + backgroundColor: THEME.color.blueGray25, + borderColor: THEME.color.lightGray + }, + icon: Icon.More, + title: 'Opération de lutte anti-pollution', + component: MissionTimelineItemGenericCard + }, + [ActionType.BAAEM_PERMANENCE]: { + style: { + backgroundColor: THEME.color.blueGray25, + borderColor: THEME.color.lightGray + }, + icon: Icon.More, + title: 'Permanence BAAEM', + component: MissionTimelineItemGenericCard + }, + [ActionType.ILLEGAL_IMMIGRATION]: { + style: { + backgroundColor: THEME.color.blueGray25, + borderColor: THEME.color.lightGray + }, + icon: Icon.More, + title: `Lutte contre l'immigration illégale`, + component: MissionTimelineItemGenericCard + }, + [ActionType.OTHER]: { + style: {}, + icon: Icon.More, + component: MissionTimelineItemGenericCard + }, + [ActionType.CONTACT]: { + style: { backgroundColor: THEME.color.blueYonder25, borderColor: THEME.color.lightGray }, + icon: Icon.Observation, + title: 'Contact', + component: MissionTimelineItemGenericCard + } +} + +interface PamTimelineRegistrHook { + timelineDropdownItems: TimelineDropdownItem[] + getTimeline: (actionType: ActionType) => Timeline +} + +export function usePamTimelineRegistry(): PamTimelineRegistrHook { + const getTimeline = (actionType: ActionType) => TIMELINE_PAM_REGISTRY[actionType] ?? ({} as Timeline) + return { timelineDropdownItems: TIME_LINE_DROPDOWN_PAM_ITEMS, getTimeline } +}