Skip to content

Commit

Permalink
Add manual PNO message
Browse files Browse the repository at this point in the history
  • Loading branch information
louptheron committed Jun 12, 2024
1 parent 5e1429d commit 46107ff
Show file tree
Hide file tree
Showing 9 changed files with 146 additions and 69 deletions.
2 changes: 2 additions & 0 deletions frontend/src/features/Logbook/LogbookMessage.types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,8 @@ export namespace LogbookMessage {
export type Gear = {
dimensions: string
gear: string
// TODO Replace null by undefined after deleting Gear in logbook.types.ts
gearName: string | null
mesh: number
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { Ellipsised } from '@components/Ellipsised'
import { useMainAppDispatch } from '@hooks/useMainAppDispatch'
import { useMainAppSelector } from '@hooks/useMainAppSelector'
import { Icon, THEME } from '@mtes-mct/monitor-ui'
import { useMemo } from 'react'
import styled from 'styled-components'

import { getComponentFromMessageType } from './constants'
import { useMainAppDispatch } from '../../../../../../hooks/useMainAppDispatch'
import { useMainAppSelector } from '../../../../../../hooks/useMainAppSelector'
import { getDateTime } from '../../../../../../utils'
import XMLSVG from '../../../../../icons/Picto_XML.svg?react'
import ShowActivitySVG from '../../../../../icons/Position_message_JPE_Pin_gris_clair.svg?react'
Expand All @@ -19,10 +19,16 @@ import type { LogbookMessage as LogbookMessageType } from '../../../../Logbook.t

type LogbookMessageComponentProps = Readonly<{
isFirst: boolean
isLessThanTwelveMetersVessel?: boolean
logbookMessage: LogbookMessageType | LogbookMessageNamespace.LogbookMessage
withMapControls?: boolean
}>
export function LogbookMessage({ isFirst, logbookMessage, withMapControls = false }: LogbookMessageComponentProps) {
export function LogbookMessage({
isFirst,
isLessThanTwelveMetersVessel = false,
logbookMessage,
withMapControls = false
}: LogbookMessageComponentProps) {
const dispatch = useMainAppDispatch()
const fishingActivitiesShowedOnMap = useMainAppSelector(state => state.fishingActivities.fishingActivitiesShowedOnMap)

Expand All @@ -37,11 +43,18 @@ export function LogbookMessage({ isFirst, logbookMessage, withMapControls = fals
</>
)
}
case LogbookMessageTypeEnum.PNO.code.toString(): {
if (isLessThanTwelveMetersVessel) {
return 'Préavis (notification de retour au port) – navire sans JPE'
}

return LogbookMessageTypeEnum[logbookMessage.messageType].fullName
}
default: {
return LogbookMessageTypeEnum[logbookMessage.messageType].fullName
}
}
}, [logbookMessage])
}, [logbookMessage, isLessThanTwelveMetersVessel])

const openXML = (xml: string) => {
const blob = new Blob([xml], { type: 'text/xml' })
Expand All @@ -50,12 +63,17 @@ export function LogbookMessage({ isFirst, logbookMessage, withMapControls = fals
URL.revokeObjectURL(url)
}

const logbookMessageComponent = useMemo(() => getComponentFromMessageType(logbookMessage), [logbookMessage])
const logbookMessageComponent = useMemo(
() => getComponentFromMessageType(logbookMessage, isLessThanTwelveMetersVessel),
[logbookMessage, isLessThanTwelveMetersVessel]
)

return (
<Wrapper id={logbookMessage.operationNumber} isFirst={isFirst}>
<Header>
<LogbookMessageTypeText>{getLogbookMessageType(logbookMessage)}</LogbookMessageTypeText>
{!isLessThanTwelveMetersVessel && (
<LogbookMessageTypeText>{getLogbookMessageType(logbookMessage)}</LogbookMessageTypeText>
)}
<LogbookMessageHeaderText
data-cy="vessel-fishing-message"
isShortcut={
Expand Down Expand Up @@ -85,14 +103,12 @@ export function LogbookMessage({ isFirst, logbookMessage, withMapControls = fals
</OperationTag>
)}

{logbookMessage.rawMessage ? (
{!isLessThanTwelveMetersVessel && logbookMessage.rawMessage && (
<Xml
onClick={() => openXML(logbookMessage.rawMessage)}
style={{ cursor: 'pointer' }}
title="Ouvrir le message XML brut"
/>
) : (
<Xml />
)}

{withMapControls &&
Expand Down Expand Up @@ -120,38 +136,42 @@ export function LogbookMessage({ isFirst, logbookMessage, withMapControls = fals
)}
<LogbookMessageMetadata>
<EmissionDateTime>
<Key>Date d’émission</Key>
<Key>{isLessThanTwelveMetersVessel ? 'Date de saisie dans MF par le CNSP' : 'Date d’émission'}</Key>
{getDateTime(logbookMessage.reportDateTime, true)}
</EmissionDateTime>
<ReceptionDateTime>
<Key>Date de réception</Key>
<Key>{isLessThanTwelveMetersVessel ? 'Date de réception par le CNSP' : 'Date de réception'}</Key>
{getDateTime(logbookMessage.integrationDateTime, true)}
</ReceptionDateTime>
<VoyageNumber>
<Key>N° de marée</Key>
{logbookMessage.tripNumber ? (
<Ellipsised maxWidth={80}>{logbookMessage.tripNumber}</Ellipsised>
) : (
<Gray>-</Gray>
)}
</VoyageNumber>
<Acknowledge>
<Key>Acq.</Key>
{!logbookMessage.acknowledgment || (logbookMessage.acknowledgment.isSuccess === null && <Gray>-</Gray>)}
{logbookMessage.acknowledgment?.isSuccess === true && (
<Icon.Confirm
color={THEME.color.mediumSeaGreen}
data-cy="LogbookMessage-successful-acknowledgement-icon"
/>
)}
{logbookMessage.acknowledgment?.isSuccess === false && (
<Icon.Reject
color={THEME.color.maximumRed}
data-cy="LogbookMessage-failed-acknowledgement-icon"
title={logbookMessage.acknowledgment?.rejectionCause ?? ''}
/>
)}
</Acknowledge>
{!isLessThanTwelveMetersVessel && (
<VoyageNumber>
<Key>N° de marée</Key>
{logbookMessage.tripNumber ? (
<Ellipsised maxWidth={80}>{logbookMessage.tripNumber}</Ellipsised>
) : (
<Gray>-</Gray>
)}
</VoyageNumber>
)}
{!isLessThanTwelveMetersVessel && (
<Acknowledge>
<Key>Acq.</Key>
{!logbookMessage.acknowledgment || (logbookMessage.acknowledgment.isSuccess === null && <Gray>-</Gray>)}
{logbookMessage.acknowledgment?.isSuccess === true && (
<Icon.Confirm
color={THEME.color.mediumSeaGreen}
data-cy="LogbookMessage-successful-acknowledgement-icon"
/>
)}
{logbookMessage.acknowledgment?.isSuccess === false && (
<Icon.Reject
color={THEME.color.maximumRed}
data-cy="LogbookMessage-failed-acknowledgement-icon"
title={logbookMessage.acknowledgment?.rejectionCause ?? ''}
/>
)}
</Acknowledge>
)}
</LogbookMessageMetadata>
{logbookMessageComponent}
</Body>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,19 +1,24 @@
import { PriorNotification } from '@features/PriorNotification/PriorNotification.types'
import { FlatKeyValue } from '@features/VesselSidebar/common/FlatKeyValue'
import { uniq } from 'lodash'
import { useMemo } from 'react'
import styled from 'styled-components'

import { CatchDetails } from './common/CatchDetails'
import { SpecyCatch } from './common/SpecyCatch'
import { getCodeWithNameOrDash, getDatetimeOrDash } from './utils'
import { buildCatchArray, getTotalPNOWeight } from '../../../../utils'
import { WeightType } from '../constants'
import { NoValue, Table, TableBody, TableKey, TableRow, TableValue, Zone, SpeciesList } from '../styles'
import { NoValue, SpeciesList, Table, TableBody, TableKey, TableRow, TableValue, Zone } from '../styles'

import type { PNOMessageValue } from '../../../../Logbook.types'
import type { Gear, PNOMessageValue } from '../../../../Logbook.types'

type PNOMessageProps = Readonly<{
isLessThanTwelveMetersVessel: boolean
message: PNOMessageValue
tripGears: Gear[] | undefined
}>
export function PNOMessage({ message }: PNOMessageProps) {
export function PNOMessage({ isLessThanTwelveMetersVessel, message, tripGears }: PNOMessageProps) {
const catchesWithProperties = useMemo(() => {
if (!message?.catchOnboard) {
return []
Expand Down Expand Up @@ -45,10 +50,12 @@ export function PNOMessage({ message }: PNOMessageProps) {
<TableKey>Date prévue de débarque</TableKey>
<TableValue>{getDatetimeOrDash(message.predictedLandingDatetimeUtc)}</TableValue>
</TableRow>
<TableRow>
<TableKey>Date de début de la marée</TableKey>
<TableValue>{getDatetimeOrDash(message.tripStartDate)}</TableValue>
</TableRow>
{!isLessThanTwelveMetersVessel && (
<TableRow>
<TableKey>Date de début de la marée</TableKey>
<TableValue>{getDatetimeOrDash(message.tripStartDate)}</TableValue>
</TableRow>
)}
<TableRow>
<TableKey>Port d’arrivée</TableKey>
<TableValue>{getCodeWithNameOrDash(message.port, message.portName)}</TableValue>
Expand All @@ -72,11 +79,26 @@ export function PNOMessage({ message }: PNOMessageProps) {
</TableBody>
</Table>
</Zone>
{isLessThanTwelveMetersVessel && (
<StyledFlatKeyValue
column={[
{
key: 'Engins utilisés',
value: tripGears?.map(gear => gear.gear).join(', ')
},
{
key: 'Zones de pêche',
value: uniq(message.catchOnboard.map(aCatch => aCatch.faoZone)).join(', ')
}
]}
/>
)}
<SpeciesList $hasCatches={!!catchesWithProperties.length}>
{catchesWithProperties.map((speciesCatch, index) => (
<SpecyCatch
// eslint-disable-next-line react/no-array-index-key
key={index}
isOpenable={!isLessThanTwelveMetersVessel}
specyCatch={speciesCatch}
weightType={WeightType.LIVE}
>
Expand All @@ -92,3 +114,7 @@ export function PNOMessage({ message }: PNOMessageProps) {
</>
)
}

const StyledFlatKeyValue = styled(FlatKeyValue)`
margin: 10px 0px 10px 0px;
`
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,18 @@ import type { ReactNode, HTMLProps } from 'react'

type SpecyCatchProps = Readonly<{
children: ReactNode
isOpenable?: boolean
isProtectedSpecy?: boolean
specyCatch: CatchWithProperties | ProtectedCatchWithProperties
weightType: WeightType
}>
export function SpecyCatch({ children, isProtectedSpecy = false, specyCatch, weightType }: SpecyCatchProps) {
export function SpecyCatch({
children,
isOpenable = true,
isProtectedSpecy = false,
specyCatch,
weightType
}: SpecyCatchProps) {
const [isOpen, setIsOpen] = useState(false)

const specyFullName = useMemo(() => {
Expand All @@ -27,13 +34,13 @@ export function SpecyCatch({ children, isProtectedSpecy = false, specyCatch, wei

return (
<Species>
<Title $isOpen={isOpen} onClick={() => setIsOpen(!isOpen)}>
<Title $isOpen={isOpen} $isOpenable={isOpenable} onClick={() => isOpenable && setIsOpen(!isOpen)}>
<SpecyName title={specyFullName}>{specyFullName}</SpecyName>
<SpecyWeight title={`${specyCatch.weight} kg (${weightType})`}>
<SpecyWeightLabel>Poids total ({weightType})</SpecyWeightLabel>
<SpecyWeightValue>{specyCatch.weight || <NoValue>-</NoValue>} kg</SpecyWeightValue>
</SpecyWeight>
<ChevronIcon $isOpen={isOpen} />
{isOpenable && <ChevronIcon $isOpen={isOpen} />}
</Title>
<Content $isOpen={isOpen} $isProtectedSpecy={isProtectedSpecy} $length={specyCatch.properties.length || 1}>
{specyCatch.properties.length > 1 && (
Expand Down Expand Up @@ -62,9 +69,10 @@ const MultipleProperties = styled.div`

const Title = styled.div<{
$isOpen: boolean
$isOpenable: boolean
}>`
border-bottom: ${p => (p.$isOpen ? `1px solid ${p.theme.color.lightGray}` : 'unset')};
cursor: pointer;
cursor: ${p => (p.$isOpenable ? 'pointer' : 'unset')};
display: flex;
flex-wrap: wrap;
overflow: hidden;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,39 +15,45 @@ import { LogbookMessageType } from '../../../../constants'
import type { LogbookMessage } from '../../../../Logbook.types'
import type { LogbookMessage as LogbookMessageNamespace } from '../../../../LogbookMessage.types'

export function getComponentFromMessageType({
message,
messageType
}: LogbookMessage | LogbookMessageNamespace.LogbookMessage) {
switch (messageType) {
export function getComponentFromMessageType(
logbookMessage: LogbookMessage | LogbookMessageNamespace.LogbookMessage,
isLessThanTwelveMetersVessel: boolean
) {
switch (logbookMessage.messageType) {
case LogbookMessageType.DEP.code:
return <DEPMessage message={message} />
return <DEPMessage message={logbookMessage.message} />
case LogbookMessageType.FAR.code:
return <FARMessage message={message} />
return <FARMessage message={logbookMessage.message} />
case LogbookMessageType.PNO.code:
return <PNOMessage message={message} />
return (
<PNOMessage
isLessThanTwelveMetersVessel={isLessThanTwelveMetersVessel}
message={logbookMessage.message}
tripGears={logbookMessage.tripGears}
/>
)
case LogbookMessageType.LAN.code:
return <LANMessage message={message} />
return <LANMessage message={logbookMessage.message} />
case LogbookMessageType.RTP.code:
return <RTPMessage message={message} />
return <RTPMessage message={logbookMessage.message} />
case LogbookMessageType.EOF.code:
return <EOFMessage message={message} />
return <EOFMessage message={logbookMessage.message} />
case LogbookMessageType.COE.code:
return <COEMessage message={message} />
return <COEMessage message={logbookMessage.message} />
case LogbookMessageType.CPS.code:
return <CPSMessage message={message} />
return <CPSMessage message={logbookMessage.message} />
case LogbookMessageType.NOT_COE.code:
return <COEMessage message={message} />
return <COEMessage message={logbookMessage.message} />
case LogbookMessageType.COX.code:
return <COXMessage message={message} />
return <COXMessage message={logbookMessage.message} />
case LogbookMessageType.NOT_COX.code:
return <COXMessage message={message} />
return <COXMessage message={logbookMessage.message} />
case LogbookMessageType.JFO.code:
return <NotImplementedMessage />
case LogbookMessageType.CRO.code:
return <CROMessage message={message} />
return <CROMessage message={logbookMessage.message} />
case LogbookMessageType.DIS.code:
return <DISMessage message={message} />
return <DISMessage message={logbookMessage.message} />
case LogbookMessageType.RLC.code:
return <NotImplementedMessage />
case LogbookMessageType.TRA.code:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,11 @@ export function PriorNotificationCard() {
<Header onClose={close} priorNotificationDetail={priorNotificationDetail} />

<Body>
<LogbookMessage isFirst logbookMessage={priorNotificationDetail.logbookMessage} />
<LogbookMessage
isFirst
isLessThanTwelveMetersVessel={priorNotificationDetail.isLessThanTwelveMetersVessel}
logbookMessage={priorNotificationDetail.logbookMessage}
/>
</Body>

<Footer>
Expand Down
Loading

0 comments on commit 46107ff

Please sign in to comment.