diff --git a/frontend/src/features/PriorNotification/components/ManualPriorNotificationForm/constants.ts b/frontend/src/features/PriorNotification/components/ManualPriorNotificationForm/constants.ts index 98b4a33491..e29d906e6a 100644 --- a/frontend/src/features/PriorNotification/components/ManualPriorNotificationForm/constants.ts +++ b/frontend/src/features/PriorNotification/components/ManualPriorNotificationForm/constants.ts @@ -6,8 +6,6 @@ import type { ManualPriorNotificationFormValues } from './types' import PurposeCode = PriorNotification.PurposeCode -export const BLUEFIN_TUNA_EXTENDED_SPECY_CODES = ['BF1', 'BF2', 'BF3'] - const FISHING_CATCH_VALIDATION_SCHEMA: ObjectSchema = object({ faoArea: string().when('$hasGlobalFaoArea', { is: false, diff --git a/frontend/src/features/PriorNotification/components/ManualPriorNotificationForm/fields/FormikFishingCatchesMultiSelect/FormikExtraField.tsx b/frontend/src/features/PriorNotification/components/ManualPriorNotificationForm/fields/FormikFishingCatchesMultiSelect/FormikExtraField.tsx index 585acaf675..8ff0aca710 100644 --- a/frontend/src/features/PriorNotification/components/ManualPriorNotificationForm/fields/FormikFishingCatchesMultiSelect/FormikExtraField.tsx +++ b/frontend/src/features/PriorNotification/components/ManualPriorNotificationForm/fields/FormikFishingCatchesMultiSelect/FormikExtraField.tsx @@ -2,7 +2,7 @@ import { FormikNumberInput } from '@mtes-mct/monitor-ui' import styled from 'styled-components' import { InputWithUnit, SubRow } from './styles' -import { BLUEFIN_TUNA_EXTENDED_SPECY_CODES } from '../../constants' +import { BLUEFIN_TUNA_EXTENDED_SPECY_CODES } from '../../../../constants' import type { PriorNotification } from '@features/PriorNotification/PriorNotification.types' diff --git a/frontend/src/features/PriorNotification/components/ManualPriorNotificationForm/fields/FormikFishingCatchesMultiSelect/index.tsx b/frontend/src/features/PriorNotification/components/ManualPriorNotificationForm/fields/FormikFishingCatchesMultiSelect/index.tsx index 18c2b13322..0c63ac0b02 100644 --- a/frontend/src/features/PriorNotification/components/ManualPriorNotificationForm/fields/FormikFishingCatchesMultiSelect/index.tsx +++ b/frontend/src/features/PriorNotification/components/ManualPriorNotificationForm/fields/FormikFishingCatchesMultiSelect/index.tsx @@ -1,5 +1,6 @@ import { useGetSpeciesQuery } from '@api/specy' import { FieldsetGroupSpinner } from '@features/Mission/components/MissionForm/shared/FieldsetGroup' +import { BLUEFIN_TUNA_EXTENDED_SPECY_CODES } from '@features/PriorNotification/constants' import { useGetFaoAreasAsOptions } from '@hooks/useGetFaoAreasAsOptions' import { useGetSpeciesAsOptions } from '@hooks/useGetSpeciesAsOptions' import { CustomSearch, FormikNumberInput, FormikSelect, Select, SingleTag } from '@mtes-mct/monitor-ui' @@ -12,7 +13,6 @@ import styled from 'styled-components' import { FormikExtraField } from './FormikExtraField' import { InputWithUnit, SubRow } from './styles' import { getFishingsCatchesValidationError } from './utils' -import { BLUEFIN_TUNA_EXTENDED_SPECY_CODES } from '../../constants' import { getFishingsCatchesInitialValues } from '../../utils' import type { Specy } from '../../../../../../domain/types/specy' @@ -52,11 +52,13 @@ export function FormikFishingCatchesMultiSelect({ isReadOnly }: FormikFishingCat ) const add = (nextSpecy: Specy | undefined) => { - const specyIsAlreadyInCatches = values.fishingCatches?.find( - fishingCatch => fishingCatch.specyCode === nextSpecy?.code - ) - if (specyIsAlreadyInCatches) { - return + if (values.hasGlobalFaoArea) { + const isSpecyCodeAlreadyInCatches = values.fishingCatches?.find( + fishingCatch => fishingCatch.specyCode === nextSpecy?.code + ) + if (isSpecyCodeAlreadyInCatches) { + return + } } const specyOption = speciesAsOptions?.find(({ value }) => value.code === nextSpecy?.code) diff --git a/frontend/src/features/PriorNotification/components/ManualPriorNotificationForm/utils.tsx b/frontend/src/features/PriorNotification/components/ManualPriorNotificationForm/utils.tsx index b8517d11d1..bccf8c8643 100644 --- a/frontend/src/features/PriorNotification/components/ManualPriorNotificationForm/utils.tsx +++ b/frontend/src/features/PriorNotification/components/ManualPriorNotificationForm/utils.tsx @@ -1,6 +1,7 @@ +import { BLUEFIN_TUNA_EXTENDED_SPECY_CODES } from '@features/PriorNotification/constants' import { pick } from 'lodash' -import { BLUEFIN_TUNA_EXTENDED_SPECY_CODES, INITIAL_FORM_VALUES } from './constants' +import { INITIAL_FORM_VALUES } from './constants' import { PriorNotification } from '../../PriorNotification.types' import type { ManualPriorNotificationFormValues } from './types' diff --git a/frontend/src/features/PriorNotification/components/PriorNotificationList/FilterBar.tsx b/frontend/src/features/PriorNotification/components/PriorNotificationList/FilterBar.tsx index ee74688494..3804eb36ef 100644 --- a/frontend/src/features/PriorNotification/components/PriorNotificationList/FilterBar.tsx +++ b/frontend/src/features/PriorNotification/components/PriorNotificationList/FilterBar.tsx @@ -1,5 +1,6 @@ import { COUNTRIES_AS_ALPHA3_OPTIONS } from '@constants/index' import { useGetFleetSegmentsAsOptions } from '@features/FleetSegment/hooks/useGetFleetSegmentsAsOptions' +import { BLUEFIN_TUNA_EXTENDED_SPECY_CODES, BLUEFIN_TUNA_SPECY_CODE } from '@features/PriorNotification/constants' import { useGetPriorNotificationTypesAsOptions } from '@features/PriorNotification/hooks/useGetPriorNotificationTypesAsOptions' import { useGetGearsAsTreeOptions } from '@hooks/useGetGearsAsTreeOptions' import { useGetPortsAsTreeOptions } from '@hooks/useGetPortsAsTreeOptions' @@ -20,6 +21,7 @@ import { useNewWindow } from '@mtes-mct/monitor-ui' import { assertNotNullish } from '@utils/assertNotNullish' +import { uniq } from 'lodash' import { useCallback } from 'react' import styled from 'styled-components' @@ -110,7 +112,11 @@ export function FilterBar() { } const updateSpecyCodes = (nextSpecyCodes: string[] | undefined) => { - dispatch(priorNotificationActions.setListFilterValues({ specyCodes: nextSpecyCodes })) + const normalizedNextSpecyCodes = nextSpecyCodes?.includes(BLUEFIN_TUNA_SPECY_CODE) + ? uniq([...nextSpecyCodes, ...BLUEFIN_TUNA_EXTENDED_SPECY_CODES]) + : nextSpecyCodes + + dispatch(priorNotificationActions.setListFilterValues({ specyCodes: normalizedNextSpecyCodes })) } const updateStatuses = (nextStatuses: FilterStatus[] | undefined) => { diff --git a/frontend/src/features/PriorNotification/components/PriorNotificationList/Row.tsx b/frontend/src/features/PriorNotification/components/PriorNotificationList/Row.tsx index 44738e0d83..eb5307e819 100644 --- a/frontend/src/features/PriorNotification/components/PriorNotificationList/Row.tsx +++ b/frontend/src/features/PriorNotification/components/PriorNotificationList/Row.tsx @@ -3,11 +3,10 @@ import { useMainAppDispatch } from '@hooks/useMainAppDispatch' import { customDayjs, Icon, TableWithSelectableRows, Tag, THEME } from '@mtes-mct/monitor-ui' import { flexRender, type Row as RowType } from '@tanstack/react-table' import { useIsSuperUser } from 'auth/hooks/useIsSuperUser' -import { orderBy } from 'lodash' import styled from 'styled-components' import { FixedTag, None } from './styles' -import { getColorsFromState, getExpandableRowCellCustomStyle } from './utils' +import { displayOnboardFishingSpecies, getColorsFromState, getExpandableRowCellCustomStyle } from './utils' import { PriorNotification } from '../../PriorNotification.types' import { openManualPriorNotificationForm } from '../../useCases/openManualPriorNotificationForm' import { openPriorNotificationCard } from '../../useCases/openPriorNotificationCard' @@ -20,7 +19,6 @@ export function Row({ row }: RowProps) { const isSuperUser = useIsSuperUser() const priorNotification = row.original - const firstFiveOnBoardCatchesByWeight = orderBy(priorNotification.onBoardCatches, ['weight'], ['desc']).slice(0, 5) const openCard = () => { if (priorNotification.isManuallyCreated) { @@ -161,14 +159,7 @@ export function Row({ row }: RowProps) { Principales espèces à bord : {priorNotification.onBoardCatches.length > 0 ? ( - - {firstFiveOnBoardCatchesByWeight.map(({ species, speciesName, weight }) => ( - {`${speciesName} (${species}) – ${weight} kg`} - ))} - + {displayOnboardFishingSpecies(priorNotification.onBoardCatches)} ) : ( Aucune capture à bord. )} @@ -211,13 +202,6 @@ export function Row({ row }: RowProps) { ) } -const StyledLi = styled.li` - overflow: hidden; - text-overflow: ellipsis; - width: 215px; - white-space: nowrap; -` - const ExpandableRowCell = styled(TableWithSelectableRows.Td)<{ $isInvalidated: boolean }>` diff --git a/frontend/src/features/PriorNotification/components/PriorNotificationList/__tests__/__snapshots__/utils.test.ts.snap b/frontend/src/features/PriorNotification/components/PriorNotificationList/__tests__/__snapshots__/utils.test.ts.snap new file mode 100644 index 0000000000..8a15b1c235 --- /dev/null +++ b/frontend/src/features/PriorNotification/components/PriorNotificationList/__tests__/__snapshots__/utils.test.ts.snap @@ -0,0 +1,21 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`features/PriorNotification/components/PriorNotificationList/utils displayOnboardFishingSpecies() should return the expected result 1`] = ` +[ + + Thon rouge de l'Atlantique (BFT) – 18 kg + , + + DEF Name (DEF) – 7 kg + , + + ABC Name (ABC) – 3 kg + , +] +`; diff --git a/frontend/src/features/PriorNotification/components/PriorNotificationList/__tests__/utils.test.ts b/frontend/src/features/PriorNotification/components/PriorNotificationList/__tests__/utils.test.ts new file mode 100644 index 0000000000..34a2e015d5 --- /dev/null +++ b/frontend/src/features/PriorNotification/components/PriorNotificationList/__tests__/utils.test.ts @@ -0,0 +1,24 @@ +import { describe, expect, it } from '@jest/globals' + +import { displayOnboardFishingSpecies } from '../utils' + +import type { LogbookMessage } from '@features/Logbook/LogbookMessage.types' + +describe('features/PriorNotification/components/PriorNotificationList/utils', () => { + it('displayOnboardFishingSpecies() should return the expected result', () => { + const onboardCatches = [ + { species: 'ABC', speciesName: `ABC Name`, weight: 0 }, + { species: 'BF1', speciesName: `Thon rouge de l'Atlantique (Calibre 1)`, weight: 1 }, + { species: 'DEF', speciesName: `DEF Name`, weight: 2 }, + { species: 'ABC', speciesName: `ABC Name`, weight: 3 }, + { species: 'BFT', speciesName: `Thon rouge de l'Atlantique`, weight: 4 }, + { species: 'DEF', speciesName: `DEF Name`, weight: 5 }, + { species: 'BF2', speciesName: `Thon rouge de l'Atlantique (Calibre 2)`, weight: 6 }, + { species: 'BF3', speciesName: `Thon rouge de l'Atlantique (Calibre 3)`, weight: 7 } + ] as LogbookMessage.Catch[] + + const result = displayOnboardFishingSpecies(onboardCatches) + + expect(result).toMatchSnapshot() + }) +}) diff --git a/frontend/src/features/PriorNotification/components/PriorNotificationList/utils.ts b/frontend/src/features/PriorNotification/components/PriorNotificationList/utils.tsx similarity index 82% rename from frontend/src/features/PriorNotification/components/PriorNotificationList/utils.ts rename to frontend/src/features/PriorNotification/components/PriorNotificationList/utils.tsx index 124f9b5b8f..d1aa1de9c5 100644 --- a/frontend/src/features/PriorNotification/components/PriorNotificationList/utils.ts +++ b/frontend/src/features/PriorNotification/components/PriorNotificationList/utils.tsx @@ -6,7 +6,14 @@ import { type AllSeafrontGroup } from '@constants/seafront' import { LogbookMessage } from '@features/Logbook/LogbookMessage.types' +import { + BLUEFIN_TUNA_EXTENDED_SPECY_CODES, + BLUEFIN_TUNA_NAME_FR, + BLUEFIN_TUNA_SPECY_CODE +} from '@features/PriorNotification/constants' import { THEME, customDayjs, getMaybeBooleanFromRichBoolean, type DateAsStringRange } from '@mtes-mct/monitor-ui' +import { update } from 'lodash' +import styled from 'styled-components' import { COMMUNITY_PRIOR_NOTIFICATION_TYPES, @@ -23,6 +30,51 @@ import { PriorNotification } from '../../PriorNotification.types' import type { FilterStatus, ListFilter } from './types' import type { CSSProperties } from 'react' +export function displayOnboardFishingSpecies(onBoardCatches: LogbookMessage.Catch[]) { + const heaviestOnBoardCatches = onBoardCatches + .reduce< + Array<{ + specyCode: string + specyName: string + weight: number + }> + >((aggregatedCatches, currentCatch) => { + const [normalizedSpecyCode, normalizedSpecyName] = BLUEFIN_TUNA_EXTENDED_SPECY_CODES.includes( + currentCatch.species + ) + ? [BLUEFIN_TUNA_SPECY_CODE, BLUEFIN_TUNA_NAME_FR] + : [currentCatch.species, currentCatch.speciesName] + const existingCatchSpecyIndex = aggregatedCatches.findIndex( + aggregatedCatch => aggregatedCatch.specyCode === normalizedSpecyCode + ) + if ( + existingCatchSpecyIndex > -1 && + currentCatch.weight !== undefined && + aggregatedCatches[existingCatchSpecyIndex]?.weight !== undefined + ) { + return update(aggregatedCatches, `[${existingCatchSpecyIndex}].weight`, weight => weight + currentCatch.weight) + } + + return [ + ...aggregatedCatches, + { + specyCode: normalizedSpecyCode, + specyName: normalizedSpecyName, + weight: currentCatch.weight + } + ] + }, []) + .sort((a, b) => b.weight - a.weight) + .slice(0, 5) + + return heaviestOnBoardCatches.map(({ specyCode, specyName, weight }) => ( + {`${specyName} (${specyCode}) – ${weight} kg`} + )) +} + function getApiFilterFromExpectedArrivalPeriod( period: ExpectedArrivalPeriod, customPeriod: DateAsStringRange | undefined @@ -254,3 +306,10 @@ export function getTitle(seafrontGroup: SeafrontGroup | AllSeafrontGroup | NoSea return `Préavis en ${SUB_MENU_LABEL[seafrontGroup]}` } } + +const StyledLi = styled.li` + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + width: 215px; +` diff --git a/frontend/src/features/PriorNotification/constants.ts b/frontend/src/features/PriorNotification/constants.ts index 3ae81027a8..e0487921f6 100644 --- a/frontend/src/features/PriorNotification/constants.ts +++ b/frontend/src/features/PriorNotification/constants.ts @@ -1,3 +1,7 @@ +export const BLUEFIN_TUNA_SPECY_CODE = 'BFT' +export const BLUEFIN_TUNA_EXTENDED_SPECY_CODES = ['BF1', 'BF2', 'BF3'] +export const BLUEFIN_TUNA_NAME_FR = `Thon rouge de l'Atlantique` + export enum OpenedPriorNotificationType { LogbookForm = 'LogbookForm', ManualForm = 'ManualForm'