Skip to content

Commit 8775fea

Browse files
committed
front: refacto import modal and clean button colors
1 parent 6d21dd0 commit 8775fea

File tree

3 files changed

+116
-53
lines changed

3 files changed

+116
-53
lines changed

front/public/locales/en/operationalStudies/importTrainSchedule.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727
"startTime": "START",
2828
"status": {
2929
"calculatingTrainSchedule": "Calculating train schedules...",
30-
"calculatingTrainScheduleComplete": "Calculating train schedules is over (path {{pathId}}) {{trainIndex}}/{{trainsCount}}",
30+
"calculatingTrainScheduleComplete": "Calculating train schedules is over (path {{pathId}}) {{createdTrainsCount}}/{{trainsCount}}",
3131
"calculatingTrainScheduleCompleteAll_one": "All train schedules have been calculated : {{successfulTrainsCount}}/{{trainsCount}} train created.",
3232
"calculatingTrainScheduleCompleteAll_other": "All train schedules have been calculated : {{successfulTrainsCount}}/{{trainsCount}} trains created.",
3333
"calculatingTrainScheduleCompleteAllFailure": "All train schedule creations failed.",

front/public/locales/fr/operationalStudies/importTrainSchedule.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727
"startTime": "DÉBUT",
2828
"status": {
2929
"calculatingTrainSchedule": "Calculs de marches en cours…",
30-
"calculatingTrainScheduleComplete": "Calcul de marche terminé (path {{pathId}}) {{trainIndex}}/{{trainsCount}}",
30+
"calculatingTrainScheduleComplete": "Calcul de marche terminé (path {{pathId}}) {{createdTrainsCount}}/{{trainsCount}}",
3131
"calculatingTrainScheduleCompleteAll_one": "Tous les calculs de marches sont terminés: {{successfulTrainsCount}}/{{trainsCount}} train créé.",
3232
"calculatingTrainScheduleCompleteAll_other": "Tous les calculs de marches sont terminés: {{successfulTrainsCount}}/{{trainsCount}} trains créés.",
3333
"calculatingTrainScheduleCompleteAllFailure": "Tous les calculs de marche ont échoué.",

front/src/modules/trainschedule/components/ImportTrainSchedule/ImportTrainScheduleModal.tsx

+114-51
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import React, { useEffect, useState } from 'react';
1+
import React, { useEffect, useMemo, useState } from 'react';
22
import cx from 'classnames';
33

44
import ModalBodySNCF from 'common/BootstrapSNCF/ModalSNCF/ModalBodySNCF';
@@ -39,6 +39,25 @@ import { Point } from './types';
3939
*
4040
*/
4141

42+
enum IMPORT_STATUS {
43+
READY = 'ready',
44+
COMPLETING_POINTS = 'completing-points',
45+
ALL_POINTS_COMPLETED = 'all-points-completed',
46+
MISSING_ROLLING_STOCK = 'missing-rolling-stock',
47+
PATHFINDINGS_RUNNING = 'pathfindings-running',
48+
PATHFINDINGS_COMPLETED = 'pathfindings-completed',
49+
PATHFINDINGS_FAILED = 'pathfindings-failed',
50+
CREATING_TRAINS = 'creating-trains',
51+
CREATING_TRAINS_COMPLETED = 'creating-trains-completed',
52+
CREATING_TRAINS_FAILED = 'creating-trains-failed',
53+
}
54+
55+
const IMPORT_STATUS_ERROR = [
56+
IMPORT_STATUS.MISSING_ROLLING_STOCK,
57+
IMPORT_STATUS.PATHFINDINGS_FAILED,
58+
IMPORT_STATUS.CREATING_TRAINS_FAILED,
59+
];
60+
4261
interface ImportTrainScheduleModalProps {
4362
infraId: number;
4463
rollingStocks: LightRollingStock[];
@@ -72,20 +91,51 @@ const ImportTrainScheduleModal = ({
7291
{ trainNumber: string; pathString: string }[]
7392
>([]);
7493

75-
const [importStatus, setImportStatus] = useState(<span>{t('status.ready')}</span>);
76-
7794
const [viewport, setViewport] = useState(initialViewport);
7895
const [status, setStatus] = useState(initialStatus);
7996

97+
const [importStatus, setImportStatus] = useState<IMPORT_STATUS>(IMPORT_STATUS.READY);
98+
const [message, setMessage] = useState('');
99+
100+
const updateImportStatus = (newStatus: IMPORT_STATUS, newMessage = '') => {
101+
if (newStatus !== importStatus) setImportStatus(newStatus);
102+
if (newMessage !== '') {
103+
setMessage(newMessage);
104+
} else {
105+
switch (newStatus) {
106+
case IMPORT_STATUS.MISSING_ROLLING_STOCK:
107+
setMessage(
108+
[t('status.noImportationPossible'), t('status.missingRollingStock')].join('\n')
109+
);
110+
break;
111+
case IMPORT_STATUS.ALL_POINTS_COMPLETED:
112+
setMessage(t('status.uicComplete'));
113+
break;
114+
case IMPORT_STATUS.PATHFINDINGS_COMPLETED:
115+
setMessage(t('status.pathComplete'));
116+
break;
117+
case IMPORT_STATUS.PATHFINDINGS_FAILED:
118+
setMessage(t('status.pathsFailed'));
119+
break;
120+
case IMPORT_STATUS.CREATING_TRAINS_FAILED:
121+
setMessage(t('status.calculatingTrainScheduleCompleteAllFailure'));
122+
break;
123+
default:
124+
setMessage('');
125+
}
126+
}
127+
};
128+
129+
const importStatusIsError = useMemo(
130+
() => IMPORT_STATUS_ERROR.includes(importStatus),
131+
[importStatus]
132+
);
133+
80134
function testMissingInfos() {
81135
if (!rollingStockID) {
82-
setImportStatus(
83-
<span className="text-danger">
84-
{[t('status.noImportationPossible'), t('status.missingRollingStock')].join('\n')}
85-
</span>
86-
);
136+
updateImportStatus(IMPORT_STATUS.MISSING_ROLLING_STOCK);
87137
} else {
88-
setImportStatus(t('status.ready'));
138+
updateImportStatus(IMPORT_STATUS.READY);
89139
}
90140
}
91141

@@ -112,15 +162,16 @@ const ImportTrainScheduleModal = ({
112162
setUicNumberToComplete(uicNumberToCompleteLocal);
113163
const pointToComplete = pointsDictionnary[uic2complete[uicNumberToCompleteLocal]];
114164
getTrackSectionID(pointToComplete.latitude, pointToComplete.longitude);
115-
setImportStatus(
165+
updateImportStatus(
166+
IMPORT_STATUS.COMPLETING_POINTS,
116167
t('status.complete', {
117168
uicNumber: uicNumberToCompleteLocal,
118169
uicTotalCount: uic2complete.length,
119170
uicName: pointToComplete.name,
120171
})
121172
);
122173
} else {
123-
setImportStatus(t('status.uicComplete'));
174+
updateImportStatus(IMPORT_STATUS.ALL_POINTS_COMPLETED);
124175
setUicNumberToComplete(undefined);
125176
setStatus({ ...status, uicComplete: true });
126177
}
@@ -132,10 +183,10 @@ const ImportTrainScheduleModal = ({
132183

133184
function endGeneratePaths(newTrainsWithPath: TrainScheduleWithPath[]) {
134185
if (newTrainsWithPath.length > 0) {
135-
setImportStatus(t('status.pathComplete'));
136-
} else setImportStatus(<span className="text-danger">{t('status.pathsFailed')}</span>);
186+
updateImportStatus(IMPORT_STATUS.PATHFINDINGS_COMPLETED);
187+
} else updateImportStatus(IMPORT_STATUS.PATHFINDINGS_FAILED);
137188
setTrainsWithPath(newTrainsWithPath);
138-
setStatus({ ...status, uicComplete: true, pathFindingDone: true });
189+
setStatus({ ...status, pathFindingDone: true });
139190
}
140191

141192
/**
@@ -163,7 +214,8 @@ const ImportTrainScheduleModal = ({
163214
autocomplete,
164215
pointsDictionnary
165216
);
166-
setImportStatus(
217+
updateImportStatus(
218+
IMPORT_STATUS.PATHFINDINGS_RUNNING,
167219
t('status.searchingPath', {
168220
pathFindingsDoneCount,
169221
pathFindingsCount,
@@ -227,34 +279,33 @@ const ImportTrainScheduleModal = ({
227279

228280
async function generateTrainSchedules() {
229281
const payloads = generateTrainSchedulesPayload(trainsWithPath, timetableId);
230-
const trainsCount = payloads.length;
231-
setImportStatus(t('status.calculatingTrainSchedule'));
282+
const trainsCount = payloads.reduce((result, payload) => result + payload.schedules.length, 0);
283+
updateImportStatus(IMPORT_STATUS.CREATING_TRAINS, t('status.calculatingTrainSchedule'));
232284
const messages = [];
233285
let successfulTrainsCount = 0;
234-
let idx = 0;
235286
// eslint-disable-next-line no-restricted-syntax
236287
for await (const payload of payloads) {
237288
const success = await launchTrainSchedules(payload);
238-
const message = `${t(
239-
!success
289+
if (success) {
290+
successfulTrainsCount += payload.schedules.length;
291+
}
292+
const msg = `${t(
293+
success
240294
? 'status.calculatingTrainScheduleComplete'
241295
: 'errorMessages.unableToCreateTrainSchedule',
242296
{
243297
pathId: payload.path,
244-
trainIndex: idx,
245-
trainsCount: payloads.length,
298+
createdTrainsCount: successfulTrainsCount,
299+
trainsCount,
246300
}
247301
)}`;
248-
messages.push(message);
249-
if (success) {
250-
successfulTrainsCount += 1;
251-
}
252-
setImportStatus(<>{messages.join('\n')}</>);
253-
idx += 1;
302+
messages.push(msg);
303+
updateImportStatus(IMPORT_STATUS.CREATING_TRAINS, messages.join('\n'));
254304
}
255305
if (successfulTrainsCount > 0) {
256306
setStatus({ ...status, trainSchedulesDone: true, success: true });
257-
setImportStatus(
307+
updateImportStatus(
308+
IMPORT_STATUS.CREATING_TRAINS_COMPLETED,
258309
t('status.calculatingTrainScheduleCompleteAll', {
259310
count: successfulTrainsCount,
260311
successfulTrainsCount,
@@ -263,11 +314,7 @@ const ImportTrainScheduleModal = ({
263314
);
264315
} else {
265316
setStatus({ ...status, trainSchedulesDone: true });
266-
setImportStatus(
267-
<span className="text-danger">
268-
{t('status.calculatingTrainScheduleCompleteAllFailure')}
269-
</span>
270-
);
317+
updateImportStatus(IMPORT_STATUS.CREATING_TRAINS_FAILED);
271318
}
272319
}
273320

@@ -304,19 +351,27 @@ const ImportTrainScheduleModal = ({
304351
{!infraId || !timetableId || !rollingStockID ? null : (
305352
<>
306353
<button
307-
className={`btn btn-sm btn-block d-flex justify-content-between ${
308-
status.uicComplete ? 'btn-outline-success' : 'btn-primary'
309-
}`}
354+
className={cx('btn', 'btn-sm', 'btn-block', 'd-flex', 'justify-content-between', {
355+
'btn-primary': !status.uicComplete && !status.pathFindingDone,
356+
'btn-outline-success': status.uicComplete,
357+
'btn-outline-secondary': !status.uicComplete && status.pathFindingDone,
358+
})}
310359
type="button"
311360
onClick={() => completePaths(true)}
312361
>
313362
<span>1 — {t('completeTrackSectionID')}</span>
314363
<span>{Object.keys(pointsDictionnary).length}</span>
315364
</button>
316365
<button
317-
className={`btn btn-sm btn-block d-flex justify-content-between ${
318-
status.pathFindingDone ? 'btn-outline-success' : 'btn-primary'
319-
}`}
366+
className={cx('btn', 'btn-sm', 'btn-block', 'd-flex', 'justify-content-between', {
367+
'btn-primary': !status.pathFindingDone,
368+
'btn-outline-danger':
369+
status.uicComplete && importStatus === IMPORT_STATUS.PATHFINDINGS_FAILED,
370+
'btn-outline-success':
371+
status.uicComplete &&
372+
status.pathFindingDone &&
373+
importStatus !== IMPORT_STATUS.PATHFINDINGS_FAILED,
374+
})}
320375
disabled={!status.uicComplete}
321376
type="button"
322377
onClick={() => generatePaths()}
@@ -327,25 +382,33 @@ const ImportTrainScheduleModal = ({
327382
<div className="my-1 text-center">{t('or')}</div>
328383
<button
329384
className={cx(
330-
'btn btn-sm btn-block d-flex justify-content-between text-wrap text-left',
331-
!status.pathFindingDone && 'btn-primary',
332-
status.pathFindingDone && trainsWithPath.length && 'btn-outline-success',
333-
status.pathFindingDone && !trainsWithPath.length && 'btn-outline-danger'
385+
'btn',
386+
'btn-sm',
387+
'btn-block',
388+
'd-flex',
389+
'justify-content-between',
390+
'text-wrap',
391+
'text-left',
392+
{
393+
'btn-primary': !status.pathFindingDone,
394+
'btn-outline-success': status.pathFindingDone && !status.uicComplete,
395+
'btn-outline-danger': status.pathFindingDone && !trainsWithPath.length,
396+
}
334397
)}
335398
type="button"
399+
disabled={status.pathFindingDone && status.uicComplete}
336400
onClick={generateAutocompletePaths}
337401
>
338402
<span>1/2 — {t('generatePathsAuto')}</span>
339403
<span>{pathsDictionnary.length}</span>
340404
</button>
341405
<Spacer height={50} />
342406
<button
343-
className={cx(
344-
'btn btn-sm btn-block d-flex justify-content-between',
345-
!status.trainSchedulesDone && 'btn-primary',
346-
status.trainSchedulesDone && !status.success && 'btn-outline-danger',
347-
status.trainSchedulesDone && status.success && 'btn-outline-success'
348-
)}
407+
className={cx('btn', 'btn-sm', 'btn-block', 'd-flex', 'justify-content-between', {
408+
'btn-primary': !status.trainSchedulesDone,
409+
'btn-outline-danger': importStatus === IMPORT_STATUS.CREATING_TRAINS_FAILED,
410+
'btn-outline-success': importStatus === IMPORT_STATUS.CREATING_TRAINS_COMPLETED,
411+
})}
349412
disabled={!status.pathFindingDone || trainsWithPath.length === 0}
350413
type="button"
351414
onClick={generateTrainSchedules}
@@ -358,7 +421,7 @@ const ImportTrainScheduleModal = ({
358421
</>
359422
)}
360423

361-
<pre>{importStatus}</pre>
424+
<p className={cx({ 'text-danger': importStatusIsError })}>{message}</p>
362425

363426
{uicNumberToComplete !== undefined && (
364427
<div className="automated-map">

0 commit comments

Comments
 (0)