From 5fa8df276db08a09486a028a19ec23895dee99cc Mon Sep 17 00:00:00 2001 From: Maxime Chaillet Date: Fri, 10 Jan 2025 17:50:07 +0100 Subject: [PATCH 1/3] permanently show last analysed time point popup --- .../AAStormDatePopup/index.tsx | 83 ++++++++++++++----- .../AnticipatoryActionStormLayer/index.tsx | 2 +- .../AnticipatoryActionStormLayer/types.ts | 7 +- 3 files changed, 68 insertions(+), 24 deletions(-) diff --git a/frontend/src/components/MapView/Layers/AnticipatoryActionStormLayer/AAStormDatePopup/index.tsx b/frontend/src/components/MapView/Layers/AnticipatoryActionStormLayer/AAStormDatePopup/index.tsx index bccb47e05..84cb8d862 100644 --- a/frontend/src/components/MapView/Layers/AnticipatoryActionStormLayer/AAStormDatePopup/index.tsx +++ b/frontend/src/components/MapView/Layers/AnticipatoryActionStormLayer/AAStormDatePopup/index.tsx @@ -3,9 +3,17 @@ import _React, { useCallback, useState } from 'react'; import { createStyles, makeStyles, Typography } from '@material-ui/core'; import { useMapCallback } from 'utils/map-utils'; import { formatInUTC, getDateInUTC } from '../utils'; -import { TimeSeriesFeature } from '../types'; +import { + FeaturePropertyDataType, + TimeSeries, + TimeSeriesFeature, +} from '../types'; -function AAStormDatePopup() { +interface AAStormDatePopupProps { + timeSeries: TimeSeries; +} + +function AAStormDatePopup({ timeSeries }: AAStormDatePopupProps) { const classes = useStyles(); const [selectedFeature, setSelectedFeature] = useState(null); @@ -50,31 +58,62 @@ function AAStormDatePopup() { return formatInUTC(dateInUTC, 'dd - Kaaa'); } - if (!selectedFeature) { - return null; + const lastAnalysedTimePoint: TimeSeriesFeature | undefined = + // eslint-disable-next-line fp/no-mutating-methods + timeSeries?.features + .slice() + .reverse() + .find( + feature => + feature.properties.data_type === FeaturePropertyDataType.analysis, + ); + + function renderPopup(feature?: TimeSeriesFeature | null) { + if (!feature) { + return null; + } + + const lng = feature.geometry.coordinates[0]; + const lat = feature.geometry.coordinates[1]; + const { time } = feature.properties; + + return ( + null} + closeOnClick={false} + className={classes.popup} + > + + {getDayAndTime(time)} + + + ); } - const lng = selectedFeature.geometry.coordinates[0]; - const lat = selectedFeature.geometry.coordinates[1]; + function renderHoveredPopup() { + const isLastAnalysedFeatureHovered = + selectedFeature?.id === lastAnalysedTimePoint?.id; + + if (!isLastAnalysedFeatureHovered && selectedFeature) { + return renderPopup(selectedFeature); + } - const { time } = selectedFeature.properties; + return null; + } return ( - null} - closeOnClick={false} - className={classes.popup} - > - - {getDayAndTime(time)} - - + <> + {/* Permanently render the popup for the last analysed point */} + {renderPopup(lastAnalysedTimePoint)} + + {renderHoveredPopup()} + ); } diff --git a/frontend/src/components/MapView/Layers/AnticipatoryActionStormLayer/index.tsx b/frontend/src/components/MapView/Layers/AnticipatoryActionStormLayer/index.tsx index 3d7f177b6..190c1b53d 100644 --- a/frontend/src/components/MapView/Layers/AnticipatoryActionStormLayer/index.tsx +++ b/frontend/src/components/MapView/Layers/AnticipatoryActionStormLayer/index.tsx @@ -445,7 +445,7 @@ const AnticipatoryActionStormLayer = React.memo( )} - + {selectedFeature && stormData.landfall?.time && ( Date: Mon, 13 Jan 2025 15:54:59 +0100 Subject: [PATCH 2/3] refacto types --- .../AAStormDatePopup/index.tsx | 2 +- .../PopupContent/index.test.tsx | 3 +- .../PopupContent/index.tsx | 3 +- .../AAStormLandfallPopup/index.tsx | 2 +- .../AnticipatoryActionStormLayer/index.tsx | 2 +- .../ActivationTriggerView/index.tsx | 17 +-- .../ActivationTriggerView/types.ts | 13 ++ .../AnticipatoryActionStormPanel/utils.tsx | 6 +- .../useAnticipatoryAction.ts | 4 +- .../AAStormStateSlice/index.ts | 18 +-- .../AAStormStateSlice/parsedStromDataTypes.ts | 72 ++++++++++ .../AAStormStateSlice/rawStormDataTypes.ts | 67 +++++++++ .../AAStormStateSlice/types.ts | 131 ++---------------- .../AAStormStateSlice/utils.ts | 9 +- 14 files changed, 191 insertions(+), 158 deletions(-) create mode 100644 frontend/src/components/MapView/LeftPanel/AnticipatoryActionPanel/AnticipatoryActionStormPanel/ActivationTriggerView/types.ts create mode 100644 frontend/src/context/anticipatoryAction/AAStormStateSlice/parsedStromDataTypes.ts create mode 100644 frontend/src/context/anticipatoryAction/AAStormStateSlice/rawStormDataTypes.ts diff --git a/frontend/src/components/MapView/Layers/AnticipatoryActionStormLayer/AAStormDatePopup/index.tsx b/frontend/src/components/MapView/Layers/AnticipatoryActionStormLayer/AAStormDatePopup/index.tsx index 84cb8d862..3f369549d 100644 --- a/frontend/src/components/MapView/Layers/AnticipatoryActionStormLayer/AAStormDatePopup/index.tsx +++ b/frontend/src/components/MapView/Layers/AnticipatoryActionStormLayer/AAStormDatePopup/index.tsx @@ -10,7 +10,7 @@ import { } from '../types'; interface AAStormDatePopupProps { - timeSeries: TimeSeries; + timeSeries?: TimeSeries; } function AAStormDatePopup({ timeSeries }: AAStormDatePopupProps) { diff --git a/frontend/src/components/MapView/Layers/AnticipatoryActionStormLayer/AAStormLandfallPopup/PopupContent/index.test.tsx b/frontend/src/components/MapView/Layers/AnticipatoryActionStormLayer/AAStormLandfallPopup/PopupContent/index.test.tsx index 2c653ab5f..9728f4ba4 100644 --- a/frontend/src/components/MapView/Layers/AnticipatoryActionStormLayer/AAStormLandfallPopup/PopupContent/index.test.tsx +++ b/frontend/src/components/MapView/Layers/AnticipatoryActionStormLayer/AAStormLandfallPopup/PopupContent/index.test.tsx @@ -1,5 +1,6 @@ import { render } from '@testing-library/react'; -import { AACategory } from 'context/anticipatoryAction/AAStormStateSlice/types'; + +import { AACategory } from 'context/anticipatoryAction/AAStormStateSlice/parsedStromDataTypes'; import PopupContent from '.'; describe('AAStormLandfallPopup component', () => { diff --git a/frontend/src/components/MapView/Layers/AnticipatoryActionStormLayer/AAStormLandfallPopup/PopupContent/index.tsx b/frontend/src/components/MapView/Layers/AnticipatoryActionStormLayer/AAStormLandfallPopup/PopupContent/index.tsx index 38249fdcd..7e5cfbd87 100644 --- a/frontend/src/components/MapView/Layers/AnticipatoryActionStormLayer/AAStormLandfallPopup/PopupContent/index.tsx +++ b/frontend/src/components/MapView/Layers/AnticipatoryActionStormLayer/AAStormLandfallPopup/PopupContent/index.tsx @@ -1,5 +1,6 @@ import { createStyles, makeStyles, Typography } from '@material-ui/core'; -import { LandfallInfo } from 'context/anticipatoryAction/AAStormStateSlice/types'; + +import { LandfallInfo } from 'context/anticipatoryAction/AAStormStateSlice/parsedStromDataTypes'; import { formatLandfallDate, formatLandfallEstimatedLeadtime, diff --git a/frontend/src/components/MapView/Layers/AnticipatoryActionStormLayer/AAStormLandfallPopup/index.tsx b/frontend/src/components/MapView/Layers/AnticipatoryActionStormLayer/AAStormLandfallPopup/index.tsx index ffa9fe064..548305b48 100644 --- a/frontend/src/components/MapView/Layers/AnticipatoryActionStormLayer/AAStormLandfallPopup/index.tsx +++ b/frontend/src/components/MapView/Layers/AnticipatoryActionStormLayer/AAStormLandfallPopup/index.tsx @@ -1,7 +1,7 @@ import { createStyles, makeStyles } from '@material-ui/core'; import { Point } from 'geojson'; import { Popup } from 'react-map-gl/maplibre'; -import { LandfallInfo } from 'context/anticipatoryAction/AAStormStateSlice/types'; +import { LandfallInfo } from 'context/anticipatoryAction/AAStormStateSlice/parsedStromDataTypes'; import PopupContent from './PopupContent'; function AAStormLandfallPopup({ diff --git a/frontend/src/components/MapView/Layers/AnticipatoryActionStormLayer/index.tsx b/frontend/src/components/MapView/Layers/AnticipatoryActionStormLayer/index.tsx index 190c1b53d..6885cccff 100644 --- a/frontend/src/components/MapView/Layers/AnticipatoryActionStormLayer/index.tsx +++ b/frontend/src/components/MapView/Layers/AnticipatoryActionStormLayer/index.tsx @@ -19,10 +19,10 @@ import { AALoadingSelector, loadStormReport, } from 'context/anticipatoryAction/AAStormStateSlice'; -import { AACategory } from 'context/anticipatoryAction/AAStormStateSlice/types'; import { updateDateRange } from 'context/mapStateSlice'; import { useWindStatesByTime } from 'components/MapView/DateSelector/TimelineItems/hooks'; import { getAAColor } from 'components/MapView/LeftPanel/AnticipatoryActionPanel/AnticipatoryActionStormPanel/utils'; +import { AACategory } from 'context/anticipatoryAction/AAStormStateSlice/parsedStromDataTypes'; import AAStormDatePopup from './AAStormDatePopup'; import AAStormLandfallPopup from './AAStormLandfallPopup'; import moderateStorm from '../../../../../public/images/anticipatory-action-storm/moderate-tropical-storm.png'; diff --git a/frontend/src/components/MapView/LeftPanel/AnticipatoryActionPanel/AnticipatoryActionStormPanel/ActivationTriggerView/index.tsx b/frontend/src/components/MapView/LeftPanel/AnticipatoryActionPanel/AnticipatoryActionStormPanel/ActivationTriggerView/index.tsx index 51dba0555..b97d8c6eb 100644 --- a/frontend/src/components/MapView/LeftPanel/AnticipatoryActionPanel/AnticipatoryActionStormPanel/ActivationTriggerView/index.tsx +++ b/frontend/src/components/MapView/LeftPanel/AnticipatoryActionPanel/AnticipatoryActionStormPanel/ActivationTriggerView/index.tsx @@ -2,13 +2,10 @@ import { Typography, createStyles, makeStyles } from '@material-ui/core'; import { useSelector } from 'react-redux'; import { AADataSelector } from 'context/anticipatoryAction/AAStormStateSlice'; import { useSafeTranslation } from 'i18n'; -import { - AADisplayCategory, - AACategory, - AAPanelCategories, -} from 'context/anticipatoryAction/AAStormStateSlice/types'; +import { AACategory } from 'context/anticipatoryAction/AAStormStateSlice/parsedStromDataTypes'; import { getAAColor } from '../utils'; import { useAACommonStyles } from '../../utils'; +import { AADisplayCategory, AAPanelCategories } from './types'; interface AreaTagProps { name: string; @@ -96,17 +93,17 @@ interface ActivationTriggerProps { function ActivationTrigger({ dialogs }: ActivationTriggerProps) { const { t } = useSafeTranslation(); const classes = useActivationTriggerStyles(); - const rawAAData = useSelector(AADataSelector); + const parsedStromData = useSelector(AADataSelector); const commonClasses = useAACommonStyles(); - const filteredActiveDistricts = rawAAData.activeDistricts - ? Object.entries(rawAAData.activeDistricts).filter(([category]) => + const filteredActiveDistricts = parsedStromData.activeDistricts + ? Object.entries(parsedStromData.activeDistricts).filter(([category]) => AAPanelCategories.includes(category as AACategory), ) : []; - const filteredNADistricts = rawAAData.naDistricts - ? Object.entries(rawAAData.naDistricts).filter(([category]) => + const filteredNADistricts = parsedStromData.naDistricts + ? Object.entries(parsedStromData.naDistricts).filter(([category]) => AAPanelCategories.includes(category as AACategory), ) : []; diff --git a/frontend/src/components/MapView/LeftPanel/AnticipatoryActionPanel/AnticipatoryActionStormPanel/ActivationTriggerView/types.ts b/frontend/src/components/MapView/LeftPanel/AnticipatoryActionPanel/AnticipatoryActionStormPanel/ActivationTriggerView/types.ts new file mode 100644 index 000000000..d6f8c8f0a --- /dev/null +++ b/frontend/src/components/MapView/LeftPanel/AnticipatoryActionPanel/AnticipatoryActionStormPanel/ActivationTriggerView/types.ts @@ -0,0 +1,13 @@ +import { AACategory } from 'context/anticipatoryAction/AAStormStateSlice/parsedStromDataTypes'; + +export const AAPanelCategories: AACategory[] = [ + AACategory.Severe, + AACategory.Moderate, +]; + +export const AADisplayCategory: { + [key in AACategory]?: string; +} = { + [AACategory.Severe]: ' >118 KM/H', + [AACategory.Moderate]: ' >89 KM/H', +}; diff --git a/frontend/src/components/MapView/LeftPanel/AnticipatoryActionPanel/AnticipatoryActionStormPanel/utils.tsx b/frontend/src/components/MapView/LeftPanel/AnticipatoryActionPanel/AnticipatoryActionStormPanel/utils.tsx index 16b9c6fb9..0161025f3 100644 --- a/frontend/src/components/MapView/LeftPanel/AnticipatoryActionPanel/AnticipatoryActionStormPanel/utils.tsx +++ b/frontend/src/components/MapView/LeftPanel/AnticipatoryActionPanel/AnticipatoryActionStormPanel/utils.tsx @@ -1,8 +1,6 @@ /* eslint-disable react-refresh/only-export-components */ -import { - AAPhaseType, - AACategory, -} from 'context/anticipatoryAction/AAStormStateSlice/types'; +import { AACategory } from 'context/anticipatoryAction/AAStormStateSlice/parsedStromDataTypes'; +import { AAPhaseType } from 'context/anticipatoryAction/AAStormStateSlice/types'; const AACategoryPhaseMap: { [key in AACategory]?: any } = { [AACategory.Severe]: { diff --git a/frontend/src/components/MapView/LeftPanel/AnticipatoryActionPanel/useAnticipatoryAction.ts b/frontend/src/components/MapView/LeftPanel/AnticipatoryActionPanel/useAnticipatoryAction.ts index b4ab9c0eb..9db791181 100644 --- a/frontend/src/components/MapView/LeftPanel/AnticipatoryActionPanel/useAnticipatoryAction.ts +++ b/frontend/src/components/MapView/LeftPanel/AnticipatoryActionPanel/useAnticipatoryAction.ts @@ -20,14 +20,14 @@ import { updateLayersCapabilities, } from 'context/serverStateSlice'; import { AnticipatoryActionData } from 'context/anticipatoryAction/AADroughtStateSlice/types'; -import { AAStormData } from 'context/anticipatoryAction/AAStormStateSlice/types'; import { getFormattedDate } from 'utils/date-utils'; import { DateFormat } from 'utils/name-utils'; +import { ParsedStormData } from 'context/anticipatoryAction/AAStormStateSlice/parsedStromDataTypes'; import { toggleRemoveLayer } from '../layersPanel/MenuItem/MenuSwitch/SwitchItem/utils'; type AADataByAction = T extends AnticipatoryAction.storm - ? AAStormData + ? ParsedStormData : Record<'Window 1' | 'Window 2', AnticipatoryActionData>; type AAAvailableDatesByAction = diff --git a/frontend/src/context/anticipatoryAction/AAStormStateSlice/index.ts b/frontend/src/context/anticipatoryAction/AAStormStateSlice/index.ts index 584bc70ed..5fa35d363 100644 --- a/frontend/src/context/anticipatoryAction/AAStormStateSlice/index.ts +++ b/frontend/src/context/anticipatoryAction/AAStormStateSlice/index.ts @@ -1,14 +1,10 @@ import { createAsyncThunk, createSlice, PayloadAction } from '@reduxjs/toolkit'; import { DateItem } from 'config/types'; import type { CreateAsyncThunkTypes, RootState } from '../../store'; -import { - AACategory, - AAStormData, - AAStormWindStateReports, - AnticipatoryActionState, - StormData, -} from './types'; +import { AAStormWindStateReports, AnticipatoryActionState } from './types'; import { parseAndTransformAA } from './utils'; +import { AACategory, ParsedStormData } from './parsedStromDataTypes'; +import { StormDataResponseBody } from './rawStormDataTypes'; const initialState: AnticipatoryActionState = { data: {}, @@ -38,7 +34,7 @@ export const loadAllAAStormData = createAsyncThunk< export const loadLatestStormReport = createAsyncThunk< { - data: AAStormData; + data: ParsedStormData; }, undefined, CreateAsyncThunkTypes @@ -50,7 +46,7 @@ export const loadLatestStormReport = createAsyncThunk< 'https://data.earthobservation.vam.wfp.org/public-share/aa/ts/outputs/latest.json', ); const stormData = await response.json(); - const data = parseAndTransformAA(stormData as StormData); + const data = parseAndTransformAA(stormData as StormDataResponseBody); return data; } catch (error) { return rejectWithValue(error); @@ -60,7 +56,7 @@ export const loadLatestStormReport = createAsyncThunk< export const loadStormReport = createAsyncThunk< { - data: AAStormData; + data: ParsedStormData; }, { stormName: string; date: string }, CreateAsyncThunkTypes @@ -77,7 +73,7 @@ export const loadStormReport = createAsyncThunk< `https://data.earthobservation.vam.wfp.org/public-share/aa/ts/outputs/${stormName}/${date}.json?v2`, ); const stormData = await response.json(); - const data = parseAndTransformAA(stormData as StormData); + const data = parseAndTransformAA(stormData as StormDataResponseBody); return data; } catch (error) { return rejectWithValue(error); diff --git a/frontend/src/context/anticipatoryAction/AAStormStateSlice/parsedStromDataTypes.ts b/frontend/src/context/anticipatoryAction/AAStormStateSlice/parsedStromDataTypes.ts new file mode 100644 index 000000000..193aa2042 --- /dev/null +++ b/frontend/src/context/anticipatoryAction/AAStormStateSlice/parsedStromDataTypes.ts @@ -0,0 +1,72 @@ +import { TimeSeries } from './rawStormDataTypes'; + +export enum AACategory { + Severe = 'Severe', + Moderate = 'Moderate', + Risk = 'Risk', +} + +export enum AACategoryKey { + Severe = 'exposed_area_64kt', + Moderate = 'exposed_area_48kt', + Proba = 'proba_48kt_20_5d', +} + +export enum AACategoryLandfall { + Severe = 'severe tropical storm', + Moderate = 'moderate tropical storm', +} + +export interface AAData { + districtNames: string[]; + polygon: any; +} + +export type DistrictDataType = { + [key in AACategory]?: AAData; +}; + +export interface LandfallInfo { + district: string; + time: string[]; + severity: AACategory[]; +} + +interface FeatureProperties { + time: string; + [key: string]: any; +} + +interface ForecastDetails { + basin: string; + cyclone_name: string; + event_id: string; + reference_time: string; + season: number; +} + +export const AACategoryDataToLandfallMap: { + [key in AACategoryLandfall]: AACategory; +} = { + [AACategoryLandfall.Severe]: AACategory.Severe, + [AACategoryLandfall.Moderate]: AACategory.Moderate, +}; + +export const AACategoryKeyToCategoryMap: { + [key in AACategoryKey]: AACategory; +} = { + [AACategoryKey.Severe]: AACategory.Severe, + [AACategoryKey.Moderate]: AACategory.Moderate, + [AACategoryKey.Proba]: AACategory.Risk, +}; + +/* parsed storm data type */ +export type ParsedStormData = { + activeDistricts?: DistrictDataType; + naDistricts?: DistrictDataType; + landfall?: LandfallInfo; + timeSeries?: TimeSeries; + landfallDetected?: boolean; + forecastDetails?: ForecastDetails; + uncertaintyCone?: FeatureProperties; +}; diff --git a/frontend/src/context/anticipatoryAction/AAStormStateSlice/rawStormDataTypes.ts b/frontend/src/context/anticipatoryAction/AAStormStateSlice/rawStormDataTypes.ts new file mode 100644 index 000000000..1381dc02f --- /dev/null +++ b/frontend/src/context/anticipatoryAction/AAStormStateSlice/rawStormDataTypes.ts @@ -0,0 +1,67 @@ +import { FeatureCollection, Point, Feature } from 'geojson'; + +export enum FeaturePropertyDataType { + analysis = 'analysis', + forecast = 'forecast', +} + +interface FeatureProperties { + time: string; + [key: string]: any; +} + +/* timeserie types */ + +interface TimeSerieFeatureProperty { + data_type: FeaturePropertyDataType; + time: string; + development: string; + // maximum_wind_speed: number; + // maximum_wind_gust: number; + // wind_buffer_48: any; + // wind_buffer_64: any; +} + +export interface TimeSeries + extends FeatureCollection {} +export interface AAStormTimeSeriesFeature + extends Feature {} + +/* forcast-details types */ +export interface ForecastDetails { + basin: string; + cyclone_name: string; + event_id: string; + reference_time: string; + season: number; +} + +/* landfall-info types */ +export enum AACategoryLandfall { + Severe = 'severe tropical storm', + Moderate = 'moderate tropical storm', +} + +/* ready_set_results types */ +interface ExposedAreaStorm { + affected_districts: string[]; + polygon: any; +} + +/* storm data reponse body type */ +export interface StormDataResponseBody { + time_series: TimeSeries; + landfall_detected: boolean; + forecast_details: ForecastDetails; + uncertainty_cone: FeatureProperties; + landfall_info: { + landfall_time: string[]; + landfall_impact_district: string; + landfall_impact_intensity: AACategoryLandfall[]; + }; + ready_set_results?: { + exposed_area_48kt: ExposedAreaStorm; + exposed_area_64kt: ExposedAreaStorm; + proba_48kt_20_5d: ExposedAreaStorm; + }; +} diff --git a/frontend/src/context/anticipatoryAction/AAStormStateSlice/types.ts b/frontend/src/context/anticipatoryAction/AAStormStateSlice/types.ts index bd2e90baa..1d64133e9 100644 --- a/frontend/src/context/anticipatoryAction/AAStormStateSlice/types.ts +++ b/frontend/src/context/anticipatoryAction/AAStormStateSlice/types.ts @@ -1,68 +1,6 @@ -// na/ny are not actually found in CSV, but defined not to cause confusion when calling the functions +// // na/ny are not actually found in CSV, but defined not to cause confusion when calling the functions import { DateItem } from 'config/types'; - -export enum AACategory { - Severe = 'Severe', - Moderate = 'Moderate', - Risk = 'Risk', -} - -export enum AACategoryKey { - Severe = 'exposed_area_64kt', - Moderate = 'exposed_area_48kt', - Proba = 'proba_48kt_20_5d', -} - -export enum AACategoryLandfall { - Severe = 'severe tropical storm', - Moderate = 'moderate tropical storm', -} - -export const AAPanelCategories: AACategory[] = [ - AACategory.Severe, - AACategory.Moderate, -]; - -export const AADisplayCategory: { - [key in AACategory]?: string; -} = { - [AACategory.Severe]: ' >118 KM/H', - [AACategory.Moderate]: ' >89 KM/H', -}; - -export const AACategoryDataToLandfallMap: { - [key in AACategoryLandfall]: AACategory; -} = { - [AACategoryLandfall.Severe]: AACategory.Severe, - [AACategoryLandfall.Moderate]: AACategory.Moderate, -}; - -export const AACategoryKeyToCategoryMap: { - [key in AACategoryKey]: AACategory; -} = { - [AACategoryKey.Severe]: AACategory.Severe, - [AACategoryKey.Moderate]: AACategory.Moderate, - [AACategoryKey.Proba]: AACategory.Risk, -}; - -export interface AAData { - districtNames: string[]; - polygon: any; -} - -export type DistrictDataType = { - [key in AACategory]?: AAData; -}; - -export type AAStormData = { - activeDistricts?: DistrictDataType; - naDistricts?: DistrictDataType; - landfall?: LandfallInfo; - timeSeries?: any; - landfallDetected?: boolean; - forecastDetails?: ForecastDetails; - uncertaintyCone?: FeatureProperties; -}; +import { AACategory, ParsedStormData } from './parsedStromDataTypes'; export enum WindState { monitoring = 'monitoring', @@ -79,71 +17,20 @@ export type AAStormWindStateReports = Record< >; export type ResultType = { - data: AAStormData; + data: ParsedStormData; }; -interface ExposedAreaStorm { - affected_districts: string[]; - polygon: any; -} - -interface FeatureProperties { - time: string; - [key: string]: any; -} - -interface Feature { - properties: FeatureProperties; - [key: string]: any; -} - -interface TimeSeries { - features: Feature[]; - [key: string]: any; -} - -interface ForecastDetails { - basin: string; - cyclone_name: string; - event_id: string; - reference_time: string; - season: number; -} - -export interface LandfallInfo { - district: string; - time: string[]; - severity: AACategory[]; -} - -export interface StormData { - time_series: TimeSeries; - landfall_detected: boolean; - forecast_details: ForecastDetails; - uncertainty_cone: FeatureProperties; - landfall_info: { - landfall_time: string[]; - landfall_impact_district: string; - landfall_impact_intensity: AACategoryLandfall[]; - }; - ready_set_results?: { - exposed_area_48kt: ExposedAreaStorm; - exposed_area_64kt: ExposedAreaStorm; - proba_48kt_20_5d: ExposedAreaStorm; - }; -} - export const AAPhase = ['Active', 'na'] as const; export type AAPhaseType = (typeof AAPhase)[number]; -export const phaseValues = Object.values(AAPhase); +// export const phaseValues = Object.values(AAPhase); -export enum AAView { - Activation_trigger = 'Actication Trigger', - Readiness_trigger = 'Readiness Trigger', -} +// export enum AAView { +// Activation_trigger = 'Actication Trigger', +// Readiness_trigger = 'Readiness Trigger', +// } export type AnticipatoryActionState = { - data: AAStormData; + data: ParsedStormData; windStateReports: AAStormWindStateReports; // availableDates used to update layer available dates after csv processed availableDates?: DateItem[] | undefined; diff --git a/frontend/src/context/anticipatoryAction/AAStormStateSlice/utils.ts b/frontend/src/context/anticipatoryAction/AAStormStateSlice/utils.ts index bc9568f65..67480b590 100644 --- a/frontend/src/context/anticipatoryAction/AAStormStateSlice/utils.ts +++ b/frontend/src/context/anticipatoryAction/AAStormStateSlice/utils.ts @@ -5,9 +5,9 @@ import { AACategoryKeyToCategoryMap, AACategoryLandfall, DistrictDataType, - ResultType, - StormData, -} from './types'; +} from './parsedStromDataTypes'; +import { StormDataResponseBody } from './rawStormDataTypes'; +import { ResultType } from './types'; const districtNameMapping: { [key: string]: string } = { Maganja_Da_Costa: 'Maganja Da Costa', @@ -28,9 +28,10 @@ const watchedDistricts: { [key in AACategory]: string[] } = { }; // DRAFT: This is a provisional implementation based on a test dataset with a temporary structure that is subject to change. -export function parseAndTransformAA(data: StormData): ResultType { +export function parseAndTransformAA(data: StormDataResponseBody): ResultType { const exposedAreas = data.ready_set_results; const landfallInfo = data.landfall_info; + const [activeDistricts, naDistricts] = exposedAreas ? (Object.values(AACategoryKey) as AACategoryKey[]).reduce( ([activeResult, naResult], categoryKey) => { From f938589de70c223c76456ce21ba46d5070ffa59a Mon Sep 17 00:00:00 2001 From: Maxime Chaillet Date: Mon, 13 Jan 2025 16:07:45 +0100 Subject: [PATCH 3/3] remove unused types, more refacto --- .../AAStormStateSlice/parsedStromDataTypes.ts | 14 +++++--------- .../anticipatoryAction/AAStormStateSlice/types.ts | 10 ---------- .../anticipatoryAction/AAStormStateSlice/utils.ts | 2 +- 3 files changed, 6 insertions(+), 20 deletions(-) diff --git a/frontend/src/context/anticipatoryAction/AAStormStateSlice/parsedStromDataTypes.ts b/frontend/src/context/anticipatoryAction/AAStormStateSlice/parsedStromDataTypes.ts index 193aa2042..c56db752e 100644 --- a/frontend/src/context/anticipatoryAction/AAStormStateSlice/parsedStromDataTypes.ts +++ b/frontend/src/context/anticipatoryAction/AAStormStateSlice/parsedStromDataTypes.ts @@ -1,4 +1,4 @@ -import { TimeSeries } from './rawStormDataTypes'; +import { ForecastDetails, TimeSeries } from './rawStormDataTypes'; export enum AACategory { Severe = 'Severe', @@ -37,14 +37,6 @@ interface FeatureProperties { [key: string]: any; } -interface ForecastDetails { - basin: string; - cyclone_name: string; - event_id: string; - reference_time: string; - season: number; -} - export const AACategoryDataToLandfallMap: { [key in AACategoryLandfall]: AACategory; } = { @@ -70,3 +62,7 @@ export type ParsedStormData = { forecastDetails?: ForecastDetails; uncertaintyCone?: FeatureProperties; }; + +export type ResultType = { + data: ParsedStormData; +}; diff --git a/frontend/src/context/anticipatoryAction/AAStormStateSlice/types.ts b/frontend/src/context/anticipatoryAction/AAStormStateSlice/types.ts index 1d64133e9..518352fc9 100644 --- a/frontend/src/context/anticipatoryAction/AAStormStateSlice/types.ts +++ b/frontend/src/context/anticipatoryAction/AAStormStateSlice/types.ts @@ -16,18 +16,8 @@ export type AAStormWindStateReports = Record< Record >; -export type ResultType = { - data: ParsedStormData; -}; - export const AAPhase = ['Active', 'na'] as const; export type AAPhaseType = (typeof AAPhase)[number]; -// export const phaseValues = Object.values(AAPhase); - -// export enum AAView { -// Activation_trigger = 'Actication Trigger', -// Readiness_trigger = 'Readiness Trigger', -// } export type AnticipatoryActionState = { data: ParsedStormData; diff --git a/frontend/src/context/anticipatoryAction/AAStormStateSlice/utils.ts b/frontend/src/context/anticipatoryAction/AAStormStateSlice/utils.ts index 67480b590..dd2416615 100644 --- a/frontend/src/context/anticipatoryAction/AAStormStateSlice/utils.ts +++ b/frontend/src/context/anticipatoryAction/AAStormStateSlice/utils.ts @@ -5,9 +5,9 @@ import { AACategoryKeyToCategoryMap, AACategoryLandfall, DistrictDataType, + ResultType, } from './parsedStromDataTypes'; import { StormDataResponseBody } from './rawStormDataTypes'; -import { ResultType } from './types'; const districtNameMapping: { [key: string]: string } = { Maganja_Da_Costa: 'Maganja Da Costa',