Skip to content

Commit

Permalink
[MISSION] Garder le formulaire des infractions ouverts (#1493)
Browse files Browse the repository at this point in the history
## Related Pull Requests & Issues

- Resolve #1187 

----

- [ ] Tests E2E (Cypress)
  • Loading branch information
maximeperraultdev authored Jun 24, 2024
2 parents f41f0fb + d4270da commit 1fc16ec
Show file tree
Hide file tree
Showing 12 changed files with 122 additions and 94 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -622,7 +622,7 @@ context('Side Window > Mission Form > Mission actions', () => {
})
})

it('Should keep pending action when switching tabs', () => {
it('Should keep pending action and pending infraction form when switching tabs', () => {
createPendingMission().then(({ body }) => {
const mission = body

Expand All @@ -646,7 +646,6 @@ context('Side Window > Mission Form > Mission actions', () => {

cy.getDataCy('mission-0').first().click({ force: true })
cy.getDataCy('mission-1').first().click({ force: true })
cy.clickButton('Editer')
cy.get('input[name="envActions[0].infractions[0].mmsi"]').should('have.value', '123456789')
cy.get('input[name="envActions[0].infractions[0].vesselName"]').should('have.value', 'BALTIK')
cy.get('input[name="envActions[0].infractions[0].imo"]').should('have.value', 'IMO123')
Expand Down
44 changes: 24 additions & 20 deletions frontend/src/domain/use_cases/missions/switchTab.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,29 +5,33 @@ import { sideWindowActions } from '../../../features/SideWindow/slice'
import { getIdTyped } from '../../../utils/getIdTyped'
import { getMissionPageRoute } from '../../../utils/routes'

export const switchTab = (path: string) => async (dispatch, getState) => {
const { missions } = getState().missionForms
import type { HomeAppThunk } from '@store/index'

const routeParams = getMissionPageRoute(path)
const id = getIdTyped(routeParams?.params.id)
export const switchTab =
(path: string): HomeAppThunk =>
async (dispatch, getState) => {
const { missions } = getState().missionForms

// if we want to switch to mission list
if (!id) {
await dispatch(sideWindowActions.setCurrentPath(path))
await dispatch(missionActions.resetSelectedMissionIdOnMap())
await dispatch(missionFormsActions.resetActiveMissionId())
const routeParams = getMissionPageRoute(path)
const id = getIdTyped(routeParams?.params.id)

return
}
// if we want to switch to mission list
if (!id) {
dispatch(sideWindowActions.setCurrentPath(path))
dispatch(missionActions.resetSelectedMissionIdOnMap())
dispatch(missionFormsActions.resetActiveMissionId())

return
}

await dispatch(missionFormsActions.setActiveMissionId(id))
await dispatch(missionActions.setSelectedMissionIdOnMap(id))
dispatch(missionFormsActions.setActiveMissionId(id))
dispatch(missionActions.setSelectedMissionIdOnMap(id))

// since we are switching to another mission, we need to update the attached reportings store
// because it's the form who listen to this store
await dispatch(
attachReportingToMissionSliceActions.setAttachedReportings(missions[id]?.missionForm?.attachedReportings || [])
)
dispatch(sideWindowActions.setCurrentPath(path))

await dispatch(sideWindowActions.setCurrentPath(path))
}
// since we are switching to another mission, we need to update the attached reportings store
// because it's the form who listen to this store
dispatch(
attachReportingToMissionSliceActions.setAttachedReportings(missions[id]?.missionForm?.attachedReportings || [])

Check warning on line 35 in frontend/src/domain/use_cases/missions/switchTab.ts

View workflow job for this annotation

GitHub Actions / Run frontend unit tests

Prefer using nullish coalescing operator (`??`) instead of a logical or (`||`), as it is a safer operator
)
}
Original file line number Diff line number Diff line change
@@ -1,42 +1,64 @@
import { useAppDispatch } from '@hooks/useAppDispatch'
import { useAppSelector } from '@hooks/useAppSelector'
import { Accent, Button } from '@mtes-mct/monitor-ui'
import { useState } from 'react'
import styled from 'styled-components'

import { InfractionCard } from './InfractionCard'
import { InfractionForm } from './InfractionForm/InfractionForm'
import { infractionFactory } from '../../../Missions.helpers'
import { missionFormsActions } from '../../slice'

import type { Infraction } from '../../../../../domain/entities/missions'

export function InfractionsForm({ canAddInfraction, envActionIndex, form, push, remove }) {
const dispatch = useAppDispatch()

const infractions: Array<Infraction> = form?.values.envActions[envActionIndex]?.infractions ?? []
const [currentInfractionIndex, setCurrentInfractionIndex] = useState<number | undefined>(undefined)

const activeMissionId = useAppSelector(state => state.missionForms.activeMissionId)

const selectedMission = useAppSelector(state =>
activeMissionId ? state.missionForms.missions[activeMissionId] : undefined
)

const activeInfractionId = selectedMission?.activeAction?.activeInfractionId

const infractionIndex = infractions.findIndex(infraction => infraction.id === activeInfractionId)

const [currentInfractionIndex, setCurrentInfractionIndex] = useState<number | undefined>(infractionIndex)

const handleAddInfraction = () => {
const numberOfInfractions = infractions?.length || 0
push(infractionFactory())
const newInfraction = infractionFactory()
push(newInfraction)
setCurrentInfractionIndex(numberOfInfractions)
dispatch(missionFormsActions.setActiveInfractionId(newInfraction.id))
}

const handleValidate = () => {
setCurrentInfractionIndex(undefined)
dispatch(missionFormsActions.setActiveInfractionId(undefined))
}

const handleEditInfraction = index => () => {
const handleEditInfraction = (index, id: string) => () => {
setCurrentInfractionIndex(index)
dispatch(missionFormsActions.setActiveInfractionId(id))
}

const handleRemoveInfraction = index => () => {
setCurrentInfractionIndex(undefined)
dispatch(missionFormsActions.setActiveInfractionId(undefined))
remove(index)
}

const handleDuplicateInfraction = index => () => {
const handleDuplicateInfraction = (index, id: string) => () => {
const numberOfInfractions = infractions.length || 0
const selectedInfraction = infractions[index]

push(infractionFactory(selectedInfraction))
setCurrentInfractionIndex(numberOfInfractions)
dispatch(missionFormsActions.setActiveInfractionId(id))
}

return (
Expand All @@ -50,24 +72,24 @@ export function InfractionsForm({ canAddInfraction, envActionIndex, form, push,

{form?.values.envActions?.length > 0 && infractions.length > 0 ? (
<InfractionsWrapper>
{infractions.map((infraction, index) =>
{infractions.map(({ id }, index) =>
currentInfractionIndex !== undefined && index === currentInfractionIndex ? (
<InfractionForm
key={infraction.id}
key={id}
currentInfractionIndex={currentInfractionIndex}
envActionIndex={envActionIndex}
removeInfraction={handleRemoveInfraction(index)}
validateInfraction={handleValidate}
/>
) : (
<InfractionCard
key={infraction.id}
key={id}
canAddInfraction={canAddInfraction}
currentInfractionIndex={index}
duplicateInfraction={handleDuplicateInfraction(index)}
duplicateInfraction={handleDuplicateInfraction(index, id)}
envActionIndex={envActionIndex}
removeInfraction={handleRemoveInfraction(index)}
setCurrentInfractionIndex={handleEditInfraction(index)}
setCurrentInfractionIndex={handleEditInfraction(index, id)}
/>
)
)}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,23 +1,23 @@
import { actionFactory } from '@features/missions/Missions.helpers'
import { useGetControlPlans } from '@hooks/useGetControlPlans'
import {
customDayjs,
FormikNumberInput,
FormikTextarea,
MultiRadio,
getOptionsFromLabelledEnum,
type OptionValueType,
Accent,
Button,
DatePicker,
FieldError,
Accent,
FormikNumberInput,
FormikTextInput,
FormikTextarea,
Icon,
MultiRadio,
Size,
THEME,
Toggle,
customDayjs,
getOptionsFromLabelledEnum,
pluralize,
Button,
FormikTextInput,
useNewWindow
useNewWindow,
type OptionValueType
} from '@mtes-mct/monitor-ui'
import { FieldArray, useFormikContext, type FormikErrors } from 'formik'
import _ from 'lodash'
Expand All @@ -29,10 +29,10 @@ import { MultiPointPicker } from './MultiPointPicker'
import { OtherControlTypesForm } from './OtherControlTypesForm'
import { CONTROL_PLAN_INIT, UNIQ_CONTROL_PLAN_INDEX } from '../../../../../domain/entities/controlPlan'
import {
type Mission,
type EnvActionControl,
ActionTypeEnum,
CompletionStatus
CompletionStatus,
type EnvActionControl,
type Mission
} from '../../../../../domain/entities/missions'
import { ReportingTargetTypeEnum, TargetTypeEnum, TargetTypeLabels } from '../../../../../domain/entities/targetType'
import { VehicleTypeEnum } from '../../../../../domain/entities/vehicleType'
Expand All @@ -44,25 +44,23 @@ import { useMissionAndActionsCompletion } from '../../hooks/useMissionAndActions
import { Separator } from '../../style'
import { MissingFieldsText } from '../MissingFieldsText'
import {
ActionFormBody,
ActionThemes,
ActionTitle,
ActionFormBody,
Header,
HeaderButtons,
StyledAuthorContainer,
StyledDeleteIconButton,
TitleWithIcon,
StyledAuthorContainer
TitleWithIcon
} from '../style'
import { ActionTheme } from '../Themes/ActionTheme'

export function ControlForm({
currentActionId,
removeControlAction,
setCurrentActionId
removeControlAction
}: {
currentActionId: string
removeControlAction: () => void
setCurrentActionId: (actionId: string | undefined) => void
}) {
const { newWindowContainerRef } = useNewWindow()
const {
Expand Down Expand Up @@ -170,7 +168,6 @@ export function ControlForm({
}

const handleRemoveAction = () => {
setCurrentActionId(undefined)
removeControlAction()
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { Header, HeaderButtons, StyledDeleteIconButton, TitleWithIcon } from './
import { type EnvAction, type EnvActionNote, type Mission } from '../../../../domain/entities/missions'
import { FormTitle, Separator } from '../style'

export function NoteForm({ currentActionId, remove, setCurrentActionId }) {
export function NoteForm({ currentActionId, remove }) {
const [actionsFields] = useField<EnvAction[]>('envActions')
const {
setFieldValue,
Expand All @@ -17,7 +17,6 @@ export function NoteForm({ currentActionId, remove, setCurrentActionId }) {
const currentAction = envActions[envActionIndex]

const handleRemoveAction = () => {
setCurrentActionId(undefined)
remove(currentActionId)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,10 @@ const EMPTY_VALUE = '--'

export function ReportingForm({
reportingActionIndex,
setCurrentActionId: setCurrentActionIndex
setCurrentActionId
}: {
reportingActionIndex: number
setCurrentActionId: (string) => void
setCurrentActionId: (actionId: string | undefined) => void
}) {
const dispatch = useAppDispatch()
const { subThemes, themes } = useGetControlPlans()
Expand Down Expand Up @@ -77,8 +77,7 @@ export function ReportingForm({
})
setFieldValue('envActions', envActionsToUpdate)
setFieldValue('detachedReportingIds', [...(values.detachedReportingIds ?? []), reporting.id])

setCurrentActionIndex(undefined)
setCurrentActionId(undefined)
}

return (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ import {
} from '../style'
import { SurveillanceThemes } from '../Themes/SurveillanceThemes'

export function SurveillanceForm({ currentActionId, remove, setCurrentActionId }) {
export function SurveillanceForm({ currentActionId, remove }) {
const { newWindowContainerRef } = useNewWindow()

const {
Expand Down Expand Up @@ -146,7 +146,6 @@ export function SurveillanceForm({ currentActionId, remove, setCurrentActionId }
)

const handleRemoveAction = () => {
setCurrentActionId(undefined)
remove(envActionIndex)
}

Expand Down
20 changes: 5 additions & 15 deletions frontend/src/features/missions/MissionForm/ActionForm/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,9 @@ type ActionFormProps = {
export function ActionForm({ currentActionId, setCurrentActionId }: ActionFormProps) {
const [attachedReportingsField] = useField<Reporting[]>('attachedReportings')
const reportingActionIndex = (attachedReportingsField.value ?? []).findIndex(
reporting => String(reporting.id) === currentActionId
reporting => reporting.id === currentActionId
)

const [reportingField] = useField<Reporting>(`attachedReportings.${reportingActionIndex}`)

const [envActionsField, , envActionsHelper] = useField<EnvAction[]>('envActions')
Expand All @@ -32,7 +33,7 @@ export function ActionForm({ currentActionId, setCurrentActionId }: ActionFormPr
envActionsHelper.setValue(actionsToUpdate)

setCurrentActionId(undefined)
}, [envActionIndex, envActionsField, envActionsHelper, setCurrentActionId])
}, [envActionIndex, envActionsField.value, envActionsHelper, setCurrentActionId])

if (currentActionId === undefined) {
return (
Expand Down Expand Up @@ -62,30 +63,19 @@ export function ActionForm({ currentActionId, setCurrentActionId }: ActionFormPr
key={actionIdField.value}
currentActionId={currentActionId}
removeControlAction={removeAction}
setCurrentActionId={setCurrentActionId}
/>
</FormWrapper>
)
case ActionTypeEnum.SURVEILLANCE:
return (
<FormWrapper>
<SurveillanceForm
key={actionIdField.value}
currentActionId={currentActionId}
remove={removeAction}
setCurrentActionId={setCurrentActionId}
/>
<SurveillanceForm key={actionIdField.value} currentActionId={currentActionId} remove={removeAction} />
</FormWrapper>
)
case ActionTypeEnum.NOTE:
return (
<FormWrapper>
<NoteForm
key={actionIdField.value}
currentActionId={currentActionId}
remove={removeAction}
setCurrentActionId={setCurrentActionId}
/>
<NoteForm key={actionIdField.value} currentActionId={currentActionId} remove={removeAction} />
</FormWrapper>
)

Expand Down
Loading

0 comments on commit 1fc16ec

Please sign in to comment.