diff --git a/front/public/locales/en/stdcm.json b/front/public/locales/en/stdcm.json index 6f32cc4df34..0a0397f9bca 100644 --- a/front/public/locales/en/stdcm.json +++ b/front/public/locales/en/stdcm.json @@ -10,10 +10,20 @@ "pathfindingFailed": "No path have been found for these waypoints.", "pleaseWait": "Please wait…", "simulation":{ + "available": "Simulation available", "averageRequestTime": "For your request, the time required is generally 90 seconds.", "calculatingSimulation": "Calculation in progress...", "getSimulation": "Get the simulation", "pendingSimulation": "Simulation in progress", + "results":{ + "displayAll": "Display all operational points", + "displayMain": "Display main operational points", + "downloadSimulationSheet": "Download simulation report sheet", + "gesicoRequest":"and attach this document to your GESICO DSDM request.", + "selectThisSimulation": "Select this simulation", + "simulationNumber": "Simulation n°1", + "simulationSelected": "You have selected this simulation" + }, "stopCalculation" : "Stop calculation" }, "spaceSpeedGraphic": "Space-Velocity graph", diff --git a/front/public/locales/fr/stdcm.json b/front/public/locales/fr/stdcm.json index 5356fefdffd..ca32d0295ac 100644 --- a/front/public/locales/fr/stdcm.json +++ b/front/public/locales/fr/stdcm.json @@ -10,10 +10,20 @@ "pathfindingFailed": "Aucun chemin n'a été trouvé pour ces points de jalonnement.", "pleaseWait": "Veuillez patientez…", "simulation":{ + "available": "Simulation disponible", "averageRequestTime": "Pour votre demande, le temps nécessaire est généralement de 90 secondes.", "calculatingSimulation": "Calcul en cours...", "getSimulation": "Obtenir la simulation", "pendingSimulation": "simulation en cours", + "results":{ + "displayAll": "Afficher tous les jalons", + "displayMain": "Afficher les jalons principaux", + "downloadSimulationSheet": "Télécharger la fiche de simulation", + "gesicoRequest":"et joignez ce document à votre demande GESICO DSDM", + "selectThisSimulation": "Retenir cette simulation", + "simulationNumber": "Simulation n°1", + "simulationSelected": "Vous avez retenu cette simulation" + }, "stopCalculation" : "Arrêter le calcul" }, "spaceSpeedGraphic": "Graphique Espace-Vitesse", diff --git a/front/src/applications/stdcm/components/SimulationReportSheetV2.tsx b/front/src/applications/stdcm/components/SimulationReportSheetV2.tsx index f3124e71218..81dea51180d 100644 --- a/front/src/applications/stdcm/components/SimulationReportSheetV2.tsx +++ b/front/src/applications/stdcm/components/SimulationReportSheetV2.tsx @@ -10,21 +10,18 @@ import { formatDateToString, formatDayV2 } from 'utils/date'; import styles from './SimulationReportStyleSheet'; import type { SimulationReportSheetProps } from '../types'; -import { extractSpeedLimit, getStopDurationTime, getOperationalPointsWithTimes } from '../utils'; +import { extractSpeedLimit, getStopDurationTime } from '../utils'; const SimulationReportSheetV2 = ({ stdcmData, - pathProperties, - rollingStockData, - speedLimitByTag, simulationReportSheetNumber, mapCanvas, - creationDate, + operationalPointsList, }: SimulationReportSheetProps) => { const { t } = useTranslation('stdcm-simulation-report-sheet'); let renderedIndex = 0; - const date = creationDate && t('formattedDate', formatDateToString(creationDate)); + const { rollingStock, speedLimitByTag, departure_time: departureTime, creationDate } = stdcmData; // TODO: Add RC information when it becomes avalaible, until that, we use fake ones const fakeInformation = { @@ -36,18 +33,6 @@ const SimulationReportSheetV2 = ({ path_number2: 'n°YYYYYY', }; - const simulationReport: SimulationReportSheetProps = { - stdcmData, - pathProperties, - rollingStockData, - speedLimitByTag, - simulationReportSheetNumber, - mapCanvas, - creationDate, - }; - - const opList = getOperationalPointsWithTimes(simulationReport); - return ( @@ -68,7 +53,9 @@ const SimulationReportSheetV2 = ({ n° {simulationReportSheetNumber} - {date} + + {t('formattedDate', formatDateToString(creationDate))} + @@ -85,7 +72,7 @@ const SimulationReportSheetV2 = ({ {t('applicationDate')} - {formatDayV2(stdcmData.departure_time)} + {formatDayV2(departureTime)} {t('referencePath')} {fakeInformation.path_number1} @@ -104,22 +91,22 @@ const SimulationReportSheetV2 = ({ - {t('maxSpeed')} - {`${Math.floor(rollingStockData.max_speed * 3.6)} km/h`} + {`${Math.floor(rollingStock.max_speed * 3.6)} km/h`} {t('maxWeight')} - {`${Math.floor(rollingStockData.mass / 1000)} t`} + {`${Math.floor(rollingStock.mass / 1000)} t`} {t('referenceEngine')} - {rollingStockData.metadata?.reference || '-'} + {rollingStock.metadata?.reference || '-'} {t('maxLength')} {`${rollingStockData.length} m`} + >{`${rollingStock.length} m`} @@ -155,9 +142,9 @@ const SimulationReportSheetV2 = ({ {t('motif')} - {opList.map((step, index) => { + {operationalPointsList.map((step, index) => { const isFirstStep = index === 0; - const isLastStep = index === opList.length - 1; + const isLastStep = index === operationalPointsList.length - 1; const shouldRenderRow = isFirstStep || step.duration > 0 || isLastStep; if (shouldRenderRow) { renderedIndex += 1; @@ -183,7 +170,7 @@ const SimulationReportSheetV2 = ({ - {isFirstStep ? step.departureTime : ''} + {isFirstStep ? step.stopEndTime : ''} @@ -259,10 +246,10 @@ const SimulationReportSheetV2 = ({ {t('crossedATE')} - {opList.map((step, index) => { + {operationalPointsList.map((step, index) => { const isFirstStep = index === 0; - const isLastStep = index === opList.length - 1; - const prevStep = opList[index - 1]; + const isLastStep = index === operationalPointsList.length - 1; + const prevStep = operationalPointsList[index - 1]; return ( - {!isFirstStep ? '=' : `${Math.floor(rollingStockData.mass / 1000)} t`} + {!isFirstStep ? '=' : `${Math.floor(rollingStock.mass / 1000)} t`} - {!isFirstStep ? '=' : rollingStockData.metadata?.reference} + {!isFirstStep ? '=' : rollingStock.metadata?.reference} @@ -349,9 +336,11 @@ const SimulationReportSheetV2 = ({ - - - + {mapCanvas && ( + + + + )} {t('withoutWarranty')} diff --git a/front/src/applications/stdcm/hooks/useStdcm.ts b/front/src/applications/stdcm/hooks/useStdcm.ts index e7ee0c74121..538f8511c23 100644 --- a/front/src/applications/stdcm/hooks/useStdcm.ts +++ b/front/src/applications/stdcm/hooks/useStdcm.ts @@ -16,6 +16,7 @@ import type { TrainScheduleResult, } from 'common/api/osrdEditoastApi'; import { useOsrdConfActions, useOsrdConfSelectors } from 'common/osrdContext'; +import { useStoreDataForSpeedLimitByTagSelector } from 'common/SpeedLimitByTagSelector/useStoreDataForSpeedLimitByTagSelector'; import createTrain from 'modules/simulationResult/components/SpaceTimeChart/createTrain'; import { CHART_AXES } from 'modules/simulationResult/consts'; import { setFailure } from 'reducers/main'; @@ -76,6 +77,8 @@ const useStdcm = () => { const { timetableID } = osrdconf; + const { speedLimitByTag } = useStoreDataForSpeedLimitByTagSelector(); + const resetResults = () => { dispatch(updateSelectedTrainId(undefined)); dispatch(updateConsolidatedSimulation([])); @@ -160,6 +163,8 @@ const useStdcm = () => { setStdcmV2Response({ ...response, rollingStock: stdcmRollingStock, + creationDate: new Date(), + speedLimitByTag, } as StdcmV2SuccessResponse); const stdcmTrain: TrainScheduleResult = { @@ -213,6 +218,8 @@ const useStdcm = () => { dispatch(updateSimulation(emptySimulation)); }; + const isPending = currentStdcmRequestStatus === STDCM_REQUEST_STATUS.pending; + return { stdcmResults, stdcmV2Results, @@ -221,6 +228,7 @@ const useStdcm = () => { cancelStdcmRequest, pathProperties, setPathProperties, + isPending, }; }; diff --git a/front/src/applications/stdcm/types.ts b/front/src/applications/stdcm/types.ts index 690d8771700..e9bb5f7d37e 100644 --- a/front/src/applications/stdcm/types.ts +++ b/front/src/applications/stdcm/types.ts @@ -1,5 +1,4 @@ import type { - ManageTrainSchedulePathProperties, PathPropertiesFormatted, TrainSpaceTimeData, } from 'applications/operationalStudies/types'; @@ -22,16 +21,30 @@ export type StdcmV2SuccessResponse = Omit< > & { simulation: Extract; rollingStock: LightRollingStock; + creationDate: Date; + speedLimitByTag?: string; }; export type SimulationReportSheetProps = { stdcmData: StdcmV2SuccessResponse; - pathProperties?: ManageTrainSchedulePathProperties; - rollingStockData: RollingStockWithLiveries; - speedLimitByTag?: string; simulationReportSheetNumber: string; mapCanvas?: string; - creationDate?: Date; + operationalPointsList: StdcmResultsOperationalPointsList; +}; + +export type StdcmResultsOperationalPointsList = StdcmResultsOperationalPoint[]; + +type StdcmResultsOperationalPoint = { + opId: string; + positionOnPath: number; + time: string | null; + name?: string; + ch?: string; + stop?: string | null; + duration: number; + departureTime: string; + stopEndTime: string; + trackName?: string; }; export type StdcmV2Results = { diff --git a/front/src/applications/stdcm/utils.ts b/front/src/applications/stdcm/utils.ts index 6ba4ac320b3..aea538f50d4 100644 --- a/front/src/applications/stdcm/utils.ts +++ b/front/src/applications/stdcm/utils.ts @@ -1,4 +1,7 @@ -import type { SimulationReportSheetProps } from './types'; +import type { SimulationResponse } from 'common/api/generatedEditoastApi'; +import type { SuggestedOP } from 'modules/trainschedule/components/ManageTrainSchedule/types'; + +import type { StdcmResultsOperationalPointsList } from './types'; function generateRandomString(length: number): string { return Array.from({ length }, () => Math.floor(Math.random() * 10)).join(''); @@ -112,28 +115,16 @@ const getStopDurationBetweenToPositions = ( return null; }; -export function getOperationalPointsWithTimes(simulationReport: SimulationReportSheetProps): { - opId: string; - positionOnPath: number; - time: string | null; - name: string | undefined; - ch: string | undefined; - stop: string | null | undefined; - duration: number; - departureTime: string; - stopEndTime: string; - trackName: string | undefined; -}[] { - const operationalPoints = simulationReport.pathProperties?.suggestedOperationalPoints || []; - const { simulation } = simulationReport.stdcmData; - +export function getOperationalPointsWithTimes( + operationalPoints: SuggestedOP[], + simulation: Extract, + departureTime: string +): StdcmResultsOperationalPointsList { const { positions, times } = simulation.final_output; - const departureTime = new Date(simulationReport.stdcmData.departure_time) - .toLocaleTimeString() - .substring(0, 5); + const pathDepartureTime = new Date(departureTime).toLocaleTimeString().substring(0, 5); // Parse departure time into hours and minutes - const [departureHour, departureMinute] = departureTime.split(':').map(Number); + const [departureHour, departureMinute] = pathDepartureTime.split(':').map(Number); // Map operational points with their positions, times, and stop durations const opResults = operationalPoints.map((op) => { diff --git a/front/src/applications/stdcm/views/StdcmConfig.tsx b/front/src/applications/stdcm/views/StdcmConfig.tsx index 646936af409..6dc8d366738 100644 --- a/front/src/applications/stdcm/views/StdcmConfig.tsx +++ b/front/src/applications/stdcm/views/StdcmConfig.tsx @@ -99,11 +99,7 @@ const StdcmConfig = ({ ); }, [infra, osrdconf, originV2, destinationV2]); - const [creationDate, setCreationDate] = useState(); - const handleClick = () => { - const currentDateTime = new Date(); - setCreationDate(currentDateTime); launchStdcmRequest(); }; @@ -212,9 +208,6 @@ const StdcmConfig = ({ mapCanvas={mapCanvas} stdcmV2Results={stdcmV2Results} pathProperties={pathProperties} - rollingStockData={rollingStock} - speedLimitByTag={speedLimitByTag} - creationDate={creationDate} /> )} diff --git a/front/src/applications/stdcm/views/StdcmResultsV2.tsx b/front/src/applications/stdcm/views/StdcmResultsV2.tsx index 752a88699e7..401d178d405 100644 --- a/front/src/applications/stdcm/views/StdcmResultsV2.tsx +++ b/front/src/applications/stdcm/views/StdcmResultsV2.tsx @@ -1,10 +1,9 @@ -import React, { useState } from 'react'; +import React, { useMemo, useState } from 'react'; import { PDFDownloadLink } from '@react-pdf/renderer'; import { useTranslation } from 'react-i18next'; import type { ManageTrainSchedulePathProperties } from 'applications/operationalStudies/types'; -import type { RollingStockWithLiveries } from 'common/api/osrdEditoastApi'; import { LoaderFill } from 'common/Loaders'; import SpaceTimeChartV2 from 'modules/simulationResult/components/SpaceTimeChart/SpaceTimeChartV2'; import SpeedSpaceChartV2 from 'modules/simulationResult/components/SpeedSpaceChart/SpeedSpaceChartV2'; @@ -13,29 +12,19 @@ import type { TimeScaleDomain } from 'modules/simulationResult/types'; import SimulationReportSheetV2 from '../components/SimulationReportSheetV2'; import { STDCM_TRAIN_ID } from '../consts'; import type { StdcmV2Results } from '../types'; -import { generateCodeNumber } from '../utils'; +import { generateCodeNumber, getOperationalPointsWithTimes } from '../utils'; type StcdmResultsProps = { mapCanvas?: string; stdcmV2Results: StdcmV2Results; pathProperties?: ManageTrainSchedulePathProperties; - rollingStockData: RollingStockWithLiveries; - speedLimitByTag?: string; - creationDate?: Date; }; const codeNumber = generateCodeNumber(); // TODO TS2 : Adapt StdcmResult to trainSchedule v2 (SpaceTimeChart and SpeedSpaceChart) -const StcdmResultsV2 = ({ - mapCanvas, - stdcmV2Results, - pathProperties, - rollingStockData, - speedLimitByTag, - creationDate, -}: StcdmResultsProps) => { +const StcdmResultsV2 = ({ mapCanvas, stdcmV2Results, pathProperties }: StcdmResultsProps) => { const { t } = useTranslation(['stdcm']); const [spaceTimeChartHeight, setSpaceTimeChartHeight] = useState(450); const [speedSpaceChartHeight, setSpeedSpaceChartHeight] = useState(250); @@ -55,6 +44,16 @@ const StcdmResultsV2 = ({ setSpaceTimeData, } = stdcmV2Results; + const operationalPointsList = useMemo( + () => + getOperationalPointsWithTimes( + pathProperties?.suggestedOperationalPoints || [], + stdcmV2Results.stdcmResponse.simulation, + stdcmV2Results.stdcmResponse.departure_time + ), + [pathProperties, stdcmV2Results] + ); + return (
@@ -104,12 +103,9 @@ const StcdmResultsV2 = ({ document={ } fileName={`STDCM-${codeNumber}.pdf`} diff --git a/front/src/applications/stdcmV2/components/StdcmConfig.tsx b/front/src/applications/stdcmV2/components/StdcmConfig.tsx index bca2ad1cbdc..5bd24241bb8 100644 --- a/front/src/applications/stdcmV2/components/StdcmConfig.tsx +++ b/front/src/applications/stdcmV2/components/StdcmConfig.tsx @@ -6,8 +6,6 @@ import cx from 'classnames'; import { useTranslation } from 'react-i18next'; import type { ManageTrainSchedulePathProperties } from 'applications/operationalStudies/types'; -import { STDCM_REQUEST_STATUS } from 'applications/stdcm/consts'; -import useStdcm from 'applications/stdcm/hooks/useStdcm'; import { useOsrdConfActions } from 'common/osrdContext'; import { usePathfindingV2 } from 'modules/pathfinding/hook/usePathfinding'; import { Map } from 'modules/trainschedule/components/ManageTrainSchedule'; @@ -24,7 +22,9 @@ import type { StdcmSimulationResult } from '../types'; type StdcmConfigProps = { currentSimulationInputs: StdcmSimulationResult['input'] | undefined; pathProperties?: ManageTrainSchedulePathProperties; - setPathProperties: (pathProperties?: ManageTrainSchedulePathProperties) => void; + isPending: boolean; + launchStdcmRequest: () => Promise; + cancelStdcmRequest: () => void; setCurrentSimulationInputs: React.Dispatch< React.SetStateAction >; @@ -33,20 +33,26 @@ type StdcmConfigProps = { const StdcmConfig = ({ currentSimulationInputs, pathProperties, - setPathProperties, + isPending, + launchStdcmRequest, + cancelStdcmRequest, setCurrentSimulationInputs, }: StdcmConfigProps) => { const { t } = useTranslation('stdcm'); const loaderRef = useRef(null); - const { launchStdcmRequest, cancelStdcmRequest, currentStdcmRequestStatus } = useStdcm(); - const isPending = currentStdcmRequestStatus === STDCM_REQUEST_STATUS.pending; - const dispatch = useAppDispatch(); const { updateGridMarginAfter, updateGridMarginBefore, updateStdcmStandardAllowance } = useOsrdConfActions() as StdcmConfSliceActions; - const { pathfindingState } = usePathfindingV2(setPathProperties, pathProperties); + const { pathfindingState } = usePathfindingV2(undefined, pathProperties); + + const clickOnSimulation = () => { + if (pathfindingState.done) { + launchStdcmRequest(); + setCurrentSimulationInputs(undefined); + } + }; useEffect(() => { if (isPending) { @@ -92,15 +98,7 @@ const StdcmConfig = ({ })} > {currentSimulationInputs && ( -
+
{t('simulation.results.gesicoRequest')}
+ + )} + +
+ +
+ +
+ ); +}; + +export default StcdmResults; diff --git a/front/src/applications/stdcmV2/components/StdcmResults/StdcmResultsTable.tsx b/front/src/applications/stdcmV2/components/StdcmResults/StdcmResultsTable.tsx new file mode 100644 index 00000000000..7058a56affa --- /dev/null +++ b/front/src/applications/stdcmV2/components/StdcmResults/StdcmResultsTable.tsx @@ -0,0 +1,149 @@ +import React, { useEffect, useState } from 'react'; + +import { Button } from '@osrd-project/ui-core'; +import { useTranslation } from 'react-i18next'; + +import type { + StdcmResultsOperationalPointsList, + StdcmV2SuccessResponse, +} from 'applications/stdcm/types'; +import { getStopDurationTime } from 'applications/stdcm/utils'; + +type SimulationTableProps = { + stdcmData: StdcmV2SuccessResponse; + setIsSimulationSelected: (simulationSelected: boolean) => void; + isSimulationSelected: boolean; + operationalPointsList: StdcmResultsOperationalPointsList; +}; + +const StcdmResultsTable = ({ + stdcmData, + setIsSimulationSelected, + isSimulationSelected, + operationalPointsList, +}: SimulationTableProps) => { + const { t } = useTranslation(['stdcm-simulation-report-sheet', 'stdcm']); + + const [showAllOP, setShowAllOP] = useState(false); + + const selectSimulation = () => { + setIsSimulationSelected(true); + }; + + useEffect(() => { + setIsSimulationSelected(false); + }, [stdcmData]); + + const handleShowAllClick = () => { + setShowAllOP((prevState) => !prevState); + }; + + return ( +
+ + + + + + + + + + + + {operationalPointsList.map((step, index) => { + const isFirstStep = index === 0; + const isLastStep = index === operationalPointsList.length - 1; + const prevStep = operationalPointsList[index - 1]; + const shouldRenderRow = isFirstStep || step.duration > 0 || isLastStep; + if (showAllOP || shouldRenderRow) { + return ( + + + + + + + + + + + ); + } + return null; + })} + +
+ {t('operationalPoint')}{t('code')}{t('endStop')}{t('passageStop')}{t('startStop')}{t('weight')}{t('refEngine')}
+ {index + 1} + + {!isFirstStep && + !isLastStep && + step.name === prevStep.name && + step.duration === 0 + ? '=' + : step.name || 'Unknown'} + {step.ch}{isLastStep || step.duration > 0 ? step.time : ''} +
= 60 ? 55 : 65}px`, + }} + > + { + // eslint-disable-next-line no-nested-ternary + !isFirstStep && !isLastStep + ? step.duration !== 0 + ? getStopDurationTime(step.duration) + : step.time + : '' + } +
+
+ {isFirstStep || step.duration > 0 ? step.stopEndTime : ''} + + {!isFirstStep && !isLastStep + ? '=' + : `${Math.floor(stdcmData.rollingStock.mass / 1000)} t`} + + {!isFirstStep && !isLastStep ? '=' : stdcmData.rollingStock.metadata?.reference} +
+
+
+
+
+ {!isSimulationSelected ? ( +
+
+
+ ); +}; + +export default StcdmResultsTable; diff --git a/front/src/applications/stdcmV2/components/StdcmResults/index.ts b/front/src/applications/stdcmV2/components/StdcmResults/index.ts new file mode 100644 index 00000000000..9df53c47daa --- /dev/null +++ b/front/src/applications/stdcmV2/components/StdcmResults/index.ts @@ -0,0 +1,3 @@ +import StdcmResults from './StdcmResults'; + +export default StdcmResults; diff --git a/front/src/applications/stdcmV2/views/StdcmViewV2.tsx b/front/src/applications/stdcmV2/views/StdcmViewV2.tsx index 15c0b3e641d..a67cb48c182 100644 --- a/front/src/applications/stdcmV2/views/StdcmViewV2.tsx +++ b/front/src/applications/stdcmV2/views/StdcmViewV2.tsx @@ -2,19 +2,20 @@ import React, { useState } from 'react'; import { useSelector } from 'react-redux'; -import type { ManageTrainSchedulePathProperties } from 'applications/operationalStudies/types'; +import useStdcm from 'applications/stdcm/hooks/useStdcm'; import { useOsrdConfSelectors } from 'common/osrdContext'; import StdcmConfig from '../components/StdcmConfig'; import StdcmHeader from '../components/StdcmHeader'; +import StdcmResults from '../components/StdcmResults'; import type { StdcmSimulationResult } from '../types'; const StdcmViewV2 = () => { + const { launchStdcmRequest, cancelStdcmRequest, isPending, stdcmV2Results, pathProperties } = + useStdcm(); const { getScenarioID } = useOsrdConfSelectors(); const scenarioID = useSelector(getScenarioID); - const [pathProperties, setPathProperties] = useState(); - const [currentSimulationInputs, setCurrentSimulationInputs] = useState< StdcmSimulationResult['input'] | undefined >(undefined); @@ -26,10 +27,19 @@ const StdcmViewV2 = () => { )} + {stdcmV2Results?.stdcmResponse && !isPending && ( + + )} ); }; diff --git a/front/src/modules/pathfinding/hook/usePathfinding.ts b/front/src/modules/pathfinding/hook/usePathfinding.ts index 737862b4276..7d8af08df19 100644 --- a/front/src/modules/pathfinding/hook/usePathfinding.ts +++ b/front/src/modules/pathfinding/hook/usePathfinding.ts @@ -133,7 +133,7 @@ function init({ } export const usePathfindingV2 = ( - setPathProperties: (pathProperties?: ManageTrainSchedulePathProperties) => void, + setPathProperties?: (pathProperties?: ManageTrainSchedulePathProperties) => void | null, pathProperties?: ManageTrainSchedulePathProperties ) => { const { t } = useTranslation(['operationalStudies/manageTrainSchedule']); @@ -167,7 +167,7 @@ export const usePathfindingV2 = ( const { updatePathSteps } = useOsrdConfActions(); const generatePathfindingParams = (): PostV2InfraByInfraIdPathfindingBlocksApiArg | null => { - setPathProperties(undefined); + if (setPathProperties) setPathProperties(undefined); return getPathfindingQuery({ infraId, rollingStock, origin, destination, pathSteps }); }; @@ -268,7 +268,7 @@ export const usePathfindingV2 = ( compact(updatedPathSteps) ); - setPathProperties({ + setPathProperties?.({ electrifications, geometry, suggestedOperationalPoints, diff --git a/front/src/styles/scss/applications/stdcmV2/_home.scss b/front/src/styles/scss/applications/stdcmV2/_home.scss index ac7b4a05b1d..ed78935419f 100644 --- a/front/src/styles/scss/applications/stdcmV2/_home.scss +++ b/front/src/styles/scss/applications/stdcmV2/_home.scss @@ -1,90 +1,284 @@ .stdcm-v2 { - .stdcm-v2__body { - padding: 32px; - background-color: rgb(239, 243, 245); + .stdcm-v2__body { + padding: 32px; + background-color: rgb(239, 243, 245); + display: flex; + + .stdcm-v2-simulation-settings { + display: flex; + gap: 13px; + .stdcm-v2__separator { + border-radius: 4px; + background-color: rgba(0, 0, 0, 0.05); + width: 6px; + height: 280px; + margin: 12px 0; + } + .stdcm-v2-simulation-itinerary { display: flex; - - .stdcm-v2-simulation-settings { - display: flex; - gap: 13px; - .stdcm-v2__separator { - border-radius: 4px; - background-color: rgba(0, 0, 0, 0.05); - width: 6px; - height: 280px; - margin: 12px 0; - } - .stdcm-v2-simulation-itinerary { - display: flex; - flex-direction: column; - gap: 32px; - width: 450px; + flex-direction: column; + gap: 32px; + width: 450px; - .stdcm-v2-vias-list { - display: flex; - flex-direction: column; - gap: 2rem; - } + .stdcm-v2-vias-list { + display: flex; + flex-direction: column; + gap: 2rem; + } - /*TODO Waiting to fix the button in ui-core...*/ - .stdcm-v2-launch-request{ - padding-bottom: 0.15rem; - button { - justify-content: center; - width: 100%; - font-weight: 500; - } - } + /*TODO Waiting to fix the button in ui-core...*/ + .stdcm-v2-launch-request { + padding-bottom: 0.15rem; - .warning-box { - border-radius: 8px; - box-shadow: 0px 0px 0px 4px rgba(255, 255, 255, 1) inset, 0px 0px 0px 5px rgba(234, 167, 43, 1) inset, 0px 3px 7px -3px rgba(125, 82, 30, 0.55); - background-color: rgba(253, 245, 225, 1); - color: #7D521E; - display: flex; - flex-direction: column; - padding: 1rem 1.8125rem 2rem 1.8125rem; - margin-top: 0.75rem; + button { + justify-content: center; + width: 100%; + font-weight: 500; + } + } + .simulation-availaible { + width: 34.125rem; + height: 5rem; + display: flex; + flex-direction: column; + position: absolute; + margin-top: 2.5rem; + border-radius: 0.5rem; + background-color: rgb(230, 247, 238); + box-shadow: + 0px 0px 0px 4px rgba(255, 255, 255, 1) inset, + 0px 0px 0px 5px rgb(60, 202, 128) inset, + 0px 3px 7px -3px rgba(11, 114, 60, 0.4); - span { - color: #EAA72B; - align-self: center; - margin-bottom: 6px; - } + span { + color: rgb(11, 114, 60); + align-self: center; + padding-top: 1.438rem; + font-size: 1.5rem; + line-height: 2rem; + } + } - } + .warning-box { + border-radius: 0.5rem; + box-shadow: + 0px 0px 0px 4px rgba(255, 255, 255, 1) inset, + 0px 0px 0px 5px rgba(234, 167, 43, 1) inset, + 0px 3px 7px -3px rgba(125, 82, 30, 0.55); + background-color: rgba(253, 245, 225, 1); + color: #7d521e; + display: flex; + flex-direction: column; + padding: 1rem 1.8125rem 2rem 1.8125rem; + margin-top: 0.75rem; - .wizz-effect:active { - .warning-box { - animation: tilt-shaking 0.25s 0s; - } - } + span { + color: #eaa72b; + align-self: center; + margin-bottom: 6px; + } + } - @keyframes tilt-shaking { - 0% { transform: rotate(0deg); } - 12% { transform: rotate(1deg); } - 24% { transform: rotate(0eg); } - 36% { transform: rotate(-1deg); } - 47% { transform: rotate(0deg); } - 59% { transform: rotate(1deg); } - 70% { transform: rotate(0eg); } - 85% { transform: rotate(-1deg); } - 100% { transform: rotate(0deg); } - } + .wizz-effect:active { + .warning-box { + animation: tilt-shaking 0.25s 0s; + } + } - } + @keyframes tilt-shaking { + 0% { + transform: rotate(0deg); + } + 12% { + transform: rotate(1deg); + } + 24% { + transform: rotate(0eg); + } + 36% { + transform: rotate(-1deg); + } + 47% { + transform: rotate(0deg); + } + 59% { + transform: rotate(1deg); + } + 70% { + transform: rotate(0eg); + } + 85% { + transform: rotate(-1deg); + } + 100% { + transform: rotate(0deg); + } } - - .stdcm-v2-map { - border-radius: 8px; - border: 1px solid rgba(255, 255, 255, 1); - box-shadow: 0px 0px 0px 2px rgba(255, 255, 255, 0.75) inset, 0px 0px 0px 1px rgba(0, 0, 0, 0.25) inset; - height: auto; - min-height: 540px; - margin-left: 0.85rem; - width: 100%; - height: calc(100vh - 64px); + } + } + + .stdcm-v2-map { + border-radius: 8px; + border: 1px solid rgba(255, 255, 255, 1); + box-shadow: + 0px 0px 0px 2px rgba(255, 255, 255, 0.75) inset, + 0px 0px 0px 1px rgba(0, 0, 0, 0.25) inset; + height: auto; + min-height: 540px; + margin-left: 0.85rem; + width: 100%; + height: calc(100vh - 64px); + } + } + .stdcm-v2-results { + background-color: rgb(233, 239, 242); + .simuation-banner { + color: rgb(0, 0, 0); + font-weight: 600; + font-size: 1.125rem; + line-height: 1.5rem; + padding-top: 1.813rem; + margin-left: 2rem; + margin-right: 2rem; + border-bottom: 0.063rem solid rgb(182, 178, 175); + .creation-date { + color: rgb(121, 118, 113); + font-weight: 400; + font-size: 0.875rem; + line-height: 1.25rem; + padding-top: 0.25rem; + padding-bottom: 0.688rem; + } + .simulation-validated { + display: flex; + .check-circle { + color: rgb(60, 202, 128); + padding-left: 0.5rem; } + } } + .simuation-results { + display: flex; + justify-content: space-between; + .results-and-sheet { + display: flex; + flex-direction: column; + } + .table-container { + margin-top: 2.125rem; + margin-left: 2rem; + width: 50.25rem; + .table-results { + border-radius: 0.375rem; + background-color: rgba(0, 0, 0, 0.05); + + th { + height: 2rem; + font-size: 0.875rem; + font-weight: 400; + text-transform: capitalize; + color: rgb(121, 118, 113); + padding-top: 0.313rem; + padding-bottom: 0.313rem; + vertical-align: middle; + } + tbody tr:nth-child(odd) { + background-color: rgb(239, 243, 245); + } + tbody tr:nth-child(even) { + background-color: rgb(246, 248, 249); + } + td { + height: 2rem; + font-size: 0.875; + font-weight: 400; + color: rgb(49, 46, 43); + line-height: 1.25rem; + vertical-align: middle; + } + .index { + padding-left: 2rem; + } + .pr { + padding-right: 12.438rem; + } + .ch { + padding-right: 2.25rem; + } + .stop { + font-size: 0.875rem; + font-weight: 600; + color: rgb(0, 0, 0); + line-height: 1.25rem; + width: 4.688rem; + } + .stop-with-duration { + font-size: 0.875rem; + color: rgb(255, 255, 255); + background-color: rgb(33, 100, 130); + border-radius: 0.625rem; + margin-top: 0.375rem; + margin-bottom: 0.375rem; + margin-right: 1.813rem; + text-align: center; + } + .weight { + padding-left: 2.063rem; + } + .semi-bold-output { + font-weight: 600; + } + } + .display-all { + height: 6.5rem; + background-color: rgba(0, 0, 0, 0.05); + display: flex; + justify-content: space-between; + border-bottom-left-radius: 0.375rem; + border-bottom-right-radius: 0.375rem; + .button-display-all-PR { + padding-top: 2rem; + padding-left: 2.25rem; + } + .button-get-simulation { + padding-top: 2rem; + padding-right: 2.25rem; + } + .selected-simulation { + padding-top: 0.6rem; + } + } + } + } + .get-simulation { + margin-left: 2rem; + height: 10.75rem; + background-color: rgb(255, 255, 255); + border-bottom-left-radius: 0.375rem; + border-bottom-right-radius: 0.375rem; + .download-simulation { + padding-top: 2.813rem; + padding-left: 16.438rem; + } + .gesico-text { + font-weight: 400; + font-size: 1rem; + color: rgb(49, 46, 43); + padding-top: 1.313rem; + padding-left: 12.938rem; + } + } + .map-results { + width: 33.75rem; + height: 33.75rem; + margin-top: 2.313rem; + margin-right: 2rem; + border-radius: 0.5rem; + border: 0.063rem solid rgba(255, 255, 255, 1); + box-shadow: + 0rem 0rem 0rem 0.125rem rgba(255, 255, 255, 0.75) inset, + 0rem 0rem 0rem 0.063rem rgba(0, 0, 0, 0.25) inset; + } + } } diff --git a/front/src/utils/date.ts b/front/src/utils/date.ts index 6a58f029384..d477f775887 100644 --- a/front/src/utils/date.ts +++ b/front/src/utils/date.ts @@ -17,7 +17,11 @@ export function formatIsoDate(date: Date) { return date.toISOString().substring(0, 10); } -export function dateTimeFormatting(date: Date, withoutTime: boolean = false) { +export function dateTimeFormatting( + date: Date, + withoutTime: boolean = false, + formatType: string = 'default' +) { let locale; switch (i18n.language) { case 'fr': @@ -28,7 +32,17 @@ export function dateTimeFormatting(date: Date, withoutTime: boolean = false) { } // Force interpreting the date in UTC const dateToUTC = dayjs(date).utc(true); - const dateFormat = withoutTime ? 'D MMM YYYY' : 'D MMM YYYY HH:mm'; + let dateFormat; + switch (formatType) { + case 'default': + dateFormat = withoutTime ? 'D MMM YYYY' : 'D MMM YYYY HH:mm'; + break; + case 'alternate': + dateFormat = withoutTime ? 'DD/MM/YY' : 'DD/MM/YY HH:mm'; + break; + default: + throw new Error('Invalid format type'); + } const tz = dayjs.tz.guess(); return dateToUTC.locale(locale).tz(tz).format(dateFormat).replace(/\./gi, ''); }