Skip to content

Commit

Permalink
Frontend - harmonise mutation through hooks
Browse files Browse the repository at this point in the history
  • Loading branch information
lwih committed Mar 1, 2024
1 parent d9329c5 commit 5d90856
Show file tree
Hide file tree
Showing 15 changed files with 1,138 additions and 1,146 deletions.
436 changes: 218 additions & 218 deletions frontend/src/pam/mission/actions/action-control-nav.test.tsx

Large diffs are not rendered by default.

6 changes: 3 additions & 3 deletions frontend/src/pam/mission/actions/action-control-nav.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@ import ControlGensDeMerForm from '../controls/control-gens-de-mer-form'
import ControlSecurityForm from '../controls/control-security-form'
import { controlMethodToHumanString, VESSEL_SIZE_OPTIONS, vesselTypeToHumanString } from '../controls/utils'
import useActionById from "./use-action-by-id.tsx";
import useAddOrUpdateControl from "../controls/use-add-update-control.tsx";
import useDeleteControl from "../controls/use-delete-control.tsx";
import useAddOrUpdateControl from "./use-add-update-action-control.tsx";
import useDeleteActionControl from "./use-delete-action-control.tsx";

export interface ActionControlNavProps {
action: Action
Expand All @@ -48,7 +48,7 @@ const ActionControlNav: React.FC<ActionControlNavProps> = ({action}) => {

const [mutateControl] = useAddOrUpdateControl()

const [deleteControl] = useDeleteControl()
const [deleteControl] = useDeleteActionControl()

const {data: navAction, loading, error} = useActionById(actionId, missionId, action.source, action.type)

Expand Down
41 changes: 41 additions & 0 deletions frontend/src/pam/mission/actions/use-add-update-action-control.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import { gql, MutationTuple, useMutation } from '@apollo/client'
import { GET_MISSION_TIMELINE } from "../timeline/use-mission-timeline.tsx";
import { GET_ACTION_BY_ID } from "./use-action-by-id.tsx";
import { ActionControl } from "../../../types/action-types.ts";
import { useParams } from "react-router-dom";

export const MUTATION_ADD_OR_UPDATE_ACTION_CONTROL = gql`
mutation AddOrUpdateControl($controlAction: ActionControlInput!) {
addOrUpdateControl(controlAction: $controlAction) {
id
startDateTimeUtc
endDateTimeUtc
latitude
longitude
controlMethod
observations
vesselIdentifier
vesselType
vesselSize
identityControlledPerson
}
}
`


const useAddOrUpdateControl = (): MutationTuple<ActionControl, Record<string, any>> => {
const {missionId} = useParams()
const mutation = useMutation(
MUTATION_ADD_OR_UPDATE_ACTION_CONTROL,
{
refetchQueries: [
{query: GET_MISSION_TIMELINE, variables: {missionId}},
GET_ACTION_BY_ID
]
}
)

return mutation
}

export default useAddOrUpdateControl
24 changes: 24 additions & 0 deletions frontend/src/pam/mission/actions/use-delete-action-control.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { gql, MutationTuple, useMutation } from '@apollo/client'
import { GET_MISSION_TIMELINE } from "../timeline/use-mission-timeline.tsx";
import { GET_ACTION_BY_ID } from "./use-action-by-id.tsx";
import { useParams } from "react-router-dom";

export const DELETE_ACTION_CONTROL = gql`
mutation DeleteControl($id: String!) {
deleteControl(id: $id)
}
`

const useDeleteActionControl = (): MutationTuple<boolean, Record<string, any>> => {
const {missionId} = useParams()
const mutation = useMutation(DELETE_ACTION_CONTROL, {
refetchQueries: [
{query: GET_MISSION_TIMELINE, variables: {missionId}},
GET_ACTION_BY_ID
]
})

return mutation
}

export default useDeleteActionControl
266 changes: 128 additions & 138 deletions frontend/src/pam/mission/controls/control-administrative-form.tsx
Original file line number Diff line number Diff line change
@@ -1,170 +1,160 @@
import { Panel, Stack, Toggle } from 'rsuite'
import { ControlAdministrative, ControlType } from '../../../types/control-types'
import { Label, MultiRadio, OptionValue, Textarea, THEME } from '@mtes-mct/monitor-ui'
import { useMutation } from '@apollo/client'
import { DELETE_CONTROL_ADMINISTRATIVE, MUTATION_ADD_OR_UPDATE_CONTROL_ADMINISTRATIVE } from '../queries'
import omit from 'lodash/omit'
import { controlResultOptions } from './control-result'
import { useParams } from 'react-router-dom'
import ControlTitleCheckbox from './control-title-checkbox'
import ControlInfraction from '../infractions/infraction-for-control'
import { FC, useEffect, useState } from 'react'
import { GET_MISSION_TIMELINE } from "../timeline/use-mission-timeline.tsx";
import { GET_ACTION_BY_ID } from "../actions/use-action-by-id.tsx";
import useDeleteControl from "./use-delete-control.tsx";
import useAddOrUpdateControl from "./use-add-update-control.tsx";

interface ControlAdministrativeFormProps {
data?: ControlAdministrative
shouldCompleteControl?: boolean
unitShouldConfirm?: boolean
data?: ControlAdministrative
shouldCompleteControl?: boolean
unitShouldConfirm?: boolean
}

const ControlAdministrativeForm: FC<ControlAdministrativeFormProps> = ({
data,
shouldCompleteControl,
unitShouldConfirm,
data,
shouldCompleteControl,
unitShouldConfirm,
}) => {
const {missionId, actionId} = useParams()
const {missionId, actionId} = useParams()

const [observationsValue, setObservationsValue] = useState<string | undefined>(data?.observations)
const [observationsValue, setObservationsValue] = useState<string | undefined>(data?.observations)

const handleObservationsChange = (nextValue?: string) => {
setObservationsValue(nextValue)
}

useEffect(() => {
setObservationsValue(data?.observations)
}, [data])
const handleObservationsChange = (nextValue?: string) => {
setObservationsValue(nextValue)
}

const handleObservationsBlur = async () => {
await onChange('observations', observationsValue)
}
useEffect(() => {
setObservationsValue(data?.observations)
}, [data])

const [mutate] = useMutation(
MUTATION_ADD_OR_UPDATE_CONTROL_ADMINISTRATIVE,
{
refetchQueries: [GET_MISSION_TIMELINE, GET_ACTION_BY_ID]
const handleObservationsBlur = async () => {
await onChange('observations', observationsValue)
}
)

const [deleteControl] = useMutation(DELETE_CONTROL_ADMINISTRATIVE, {
refetchQueries: [GET_MISSION_TIMELINE, GET_ACTION_BY_ID]
})
const [mutateControl] = useAddOrUpdateControl({controlType: ControlType.ADMINISTRATIVE})
const [deleteControl] = useDeleteControl({controlType: ControlType.ADMINISTRATIVE})

const toggleControl = async (isChecked: boolean) =>
isChecked
? onChange()
: await deleteControl({
variables: {
actionId
}
})

const toggleControl = async (isChecked: boolean) =>
isChecked
? onChange()
: await deleteControl({
variables: {
actionId
const onChange = async (field?: string, value?: any) => {
let updatedData = {
...omit(data, '__typename', 'infractions'),
id: data?.id,
missionId: missionId,
actionControlId: actionId,
amountOfControls: 1,
unitShouldConfirm: unitShouldConfirm
}
})

const onChange = async (field?: string, value?: any) => {
let updatedData = {
...omit(data, '__typename', 'infractions'),
id: data?.id,
missionId: missionId,
actionControlId: actionId,
amountOfControls: 1,
unitShouldConfirm: unitShouldConfirm
}
if (!!field && value !== undefined) {
updatedData = {
...updatedData,
[field]: value
}
}

if (!!field && value !== undefined) {
updatedData = {
...updatedData,
[field]: value
}
await mutateControl({variables: {control: updatedData}})
}

await mutate({variables: {control: updatedData}})
}

return (
<Panel
header={
<ControlTitleCheckbox
controlType={ControlType.ADMINISTRATIVE}
checked={!!data || shouldCompleteControl}
shouldCompleteControl={!!shouldCompleteControl && !!!data}
onChange={(isChecked: boolean) => toggleControl(isChecked)}
/>
}
// collapsible
// defaultExpanded={controlIsEnabled(data)}
style={{backgroundColor: THEME.color.white, borderRadius: 0}}
>
<Stack direction="column" alignItems="flex-start" spacing="1rem" style={{width: '100%'}}>
{unitShouldConfirm && (
<Stack.Item style={{width: '100%'}}>
<Stack direction="row" alignItems="baseline" spacing={'0.5rem'}>
<Stack.Item>
{/* TODO add Toggle component to monitor-ui */}
<Toggle
checked={!!data?.unitHasConfirmed}
size="sm"
onChange={(checked: boolean) => onChange('unitHasConfirmed', checked)}
return (
<Panel
header={
<ControlTitleCheckbox
controlType={ControlType.ADMINISTRATIVE}
checked={!!data || shouldCompleteControl}
shouldCompleteControl={!!shouldCompleteControl && !!!data}
onChange={(isChecked: boolean) => toggleControl(isChecked)}
/>
</Stack.Item>
<Stack.Item alignSelf="flex-end">
<Label style={{marginBottom: 0}}>
<b>Contrôle confirmé par l’unité</b>
</Label>
</Stack.Item>
}
// collapsible
// defaultExpanded={controlIsEnabled(data)}
style={{backgroundColor: THEME.color.white, borderRadius: 0}}
>
<Stack direction="column" alignItems="flex-start" spacing="1rem" style={{width: '100%'}}>
{unitShouldConfirm && (
<Stack.Item style={{width: '100%'}}>
<Stack direction="row" alignItems="baseline" spacing={'0.5rem'}>
<Stack.Item>
{/* TODO add Toggle component to monitor-ui */}
<Toggle
checked={!!data?.unitHasConfirmed}
size="sm"
onChange={(checked: boolean) => onChange('unitHasConfirmed', checked)}
/>
</Stack.Item>
<Stack.Item alignSelf="flex-end">
<Label style={{marginBottom: 0}}>
<b>Contrôle confirmé par l’unité</b>
</Label>
</Stack.Item>
</Stack>
</Stack.Item>
)}
<Stack.Item style={{width: '100%'}}>
<MultiRadio
value={data?.compliantOperatingPermit}
error=""
isInline
label="Permis de mise en exploitation (autorisation à pêcher) conforme"
name="compliantOperatingPermit"
onChange={(nextValue: OptionValue) => onChange('compliantOperatingPermit', nextValue)}
options={controlResultOptions()}
/>
</Stack.Item>
<Stack.Item style={{width: '100%'}}>
<MultiRadio
value={data?.upToDateNavigationPermit}
error=""
isInline
label="Permis de navigation à jour"
name="upToDateNavigationPermit"
onChange={(nextValue: OptionValue) => onChange('upToDateNavigationPermit', nextValue)}
options={controlResultOptions()}
/>
</Stack.Item>
<Stack.Item style={{width: '100%'}}>
<MultiRadio
value={data?.compliantSecurityDocuments}
error=""
isInline
label="Titres de sécurité conformes"
name="compliantSecurityDocuments"
onChange={(nextValue: OptionValue) => onChange('compliantSecurityDocuments', nextValue)}
options={controlResultOptions()}
/>
</Stack.Item>
<Stack.Item style={{width: '100%'}}>
<Textarea
name="observations"
label="Observations (hors infraction) sur les pièces administratives"
value={observationsValue}
onChange={handleObservationsChange}
onBlur={handleObservationsBlur}
/>
</Stack.Item>
<Stack.Item style={{width: '100%'}}>
<ControlInfraction
controlId={data?.id}
infractions={data?.infractions}
controlType={ControlType.ADMINISTRATIVE}
/>
</Stack.Item>
</Stack>
</Stack.Item>
)}
<Stack.Item style={{width: '100%'}}>
<MultiRadio
value={data?.compliantOperatingPermit}
error=""
isInline
label="Permis de mise en exploitation (autorisation à pêcher) conforme"
name="compliantOperatingPermit"
onChange={(nextValue: OptionValue) => onChange('compliantOperatingPermit', nextValue)}
options={controlResultOptions()}
/>
</Stack.Item>
<Stack.Item style={{width: '100%'}}>
<MultiRadio
value={data?.upToDateNavigationPermit}
error=""
isInline
label="Permis de navigation à jour"
name="upToDateNavigationPermit"
onChange={(nextValue: OptionValue) => onChange('upToDateNavigationPermit', nextValue)}
options={controlResultOptions()}
/>
</Stack.Item>
<Stack.Item style={{width: '100%'}}>
<MultiRadio
value={data?.compliantSecurityDocuments}
error=""
isInline
label="Titres de sécurité conformes"
name="compliantSecurityDocuments"
onChange={(nextValue: OptionValue) => onChange('compliantSecurityDocuments', nextValue)}
options={controlResultOptions()}
/>
</Stack.Item>
<Stack.Item style={{width: '100%'}}>
<Textarea
name="observations"
label="Observations (hors infraction) sur les pièces administratives"
value={observationsValue}
onChange={handleObservationsChange}
onBlur={handleObservationsBlur}
/>
</Stack.Item>
<Stack.Item style={{width: '100%'}}>
<ControlInfraction
controlId={data?.id}
infractions={data?.infractions}
controlType={ControlType.ADMINISTRATIVE}
/>
</Stack.Item>
</Stack>
</Panel>
)
</Panel>
)
}

export default ControlAdministrativeForm
Loading

0 comments on commit 5d90856

Please sign in to comment.