RELEASE V.1.2.1 - Voici les fonctionnalités :
->Refonte visuelle + Prise en charge du mode sombre par l'ensemble des composants.
This commit is contained in:
1 parent
d61422ddbf
commit
37ab831aac
44 files changed
+17261
-7636
No files matched your search
@@ -146,7 +146,7 @@ export default function CreerPerturbation() {
|
||||
|
||||
const handleSelectSingleHoraire = useCallback((h) => {
|
||||
setSelectedHoraires([h]);
|
||||
setSearchQuery(`${h.numero_train} - ${h.gare_depart_nom} → ${h.gare_arrivee_nom}`);
|
||||
setSearchQuery(`${h.numero_train} - ${h.gare_depart_nom} vers ${h.gare_arrivee_nom}`);
|
||||
setShowResults(false);
|
||||
setPerturbationsArretsMap({ [h.id]: buildArretFromHoraire(h) });
|
||||
setOpenTrains({ [h.id]: true });
|
||||
@@ -184,13 +184,33 @@ export default function CreerPerturbation() {
|
||||
|
||||
if (checked) {
|
||||
if (!types.includes(typeValue)) types.push(typeValue);
|
||||
if (typeValue === 'retard') { a.manual_retard = true; a.retard_minutes = a.retard_minutes || 0; }
|
||||
if (typeValue === 'arret_prolonge') { a.manual_arret_prolonge = true; a.arret_prolonge_minutes = a.arret_prolonge_minutes || 0; }
|
||||
if (typeValue === 'retard') {
|
||||
a.manual_retard = true;
|
||||
a.retard_minutes = Number(a.retard_minutes) > 0 ? a.retard_minutes : 15;
|
||||
}
|
||||
if (typeValue === 'reduction_retard') {
|
||||
a.manual_reduction = true;
|
||||
a.reduction_retard_minutes = Number(a.reduction_retard_minutes) > 0 ? a.reduction_retard_minutes : 5;
|
||||
}
|
||||
if (typeValue === 'arret_prolonge') {
|
||||
a.manual_arret_prolonge = true;
|
||||
a.arret_prolonge_minutes = Number(a.arret_prolonge_minutes) > 0 ? a.arret_prolonge_minutes : 5;
|
||||
}
|
||||
if (typeValue === 'modification_parcours') { a.is_nouveau_terminus = false; a.is_nouvelle_origine = false; }
|
||||
} else {
|
||||
types = types.filter(t => t !== typeValue);
|
||||
if (typeValue === 'retard') { a.manual_retard = false; a.retard_minutes = 0; }
|
||||
if (typeValue === 'arret_prolonge') { a.manual_arret_prolonge = false; a.arret_prolonge_minutes = 0; }
|
||||
if (typeValue === 'retard') {
|
||||
a.manual_retard = false;
|
||||
a.retard_minutes = 0;
|
||||
}
|
||||
if (typeValue === 'reduction_retard') {
|
||||
a.manual_reduction = false;
|
||||
a.reduction_retard_minutes = 0;
|
||||
}
|
||||
if (typeValue === 'arret_prolonge') {
|
||||
a.manual_arret_prolonge = false;
|
||||
a.arret_prolonge_minutes = 0;
|
||||
}
|
||||
if (typeValue === 'arret_supprime') { a.is_nouveau_terminus = false; a.is_nouvelle_origine = false; }
|
||||
if (typeValue === 'modification_parcours') { a.is_nouveau_terminus = false; a.is_nouvelle_origine = false; }
|
||||
}
|
||||
@@ -209,10 +229,24 @@ export default function CreerPerturbation() {
|
||||
nextArr[index] = { ...nextArr[index], [field]: value };
|
||||
|
||||
if (field === 'retard_minutes') {
|
||||
nextArr[index].manual_retard = true;
|
||||
nextArr[index].retard_minutes = Number(value) || 0;
|
||||
const mins = Number(value) || 0;
|
||||
nextArr[index].retard_minutes = mins;
|
||||
nextArr[index].manual_retard = mins > 0;
|
||||
const types = [...(nextArr[index].types_perturbation || [])];
|
||||
if (!types.includes('retard')) types.push('retard');
|
||||
if (mins > 0 && !types.includes('retard')) types.push('retard');
|
||||
nextArr[index].types_perturbation = types;
|
||||
nextArr[index].type_perturbation = getPrimaryType(types);
|
||||
}
|
||||
if (field === 'reduction_retard_minutes') {
|
||||
const mins = Number(value) || 0;
|
||||
nextArr[index].reduction_retard_minutes = mins;
|
||||
nextArr[index].manual_reduction = mins > 0;
|
||||
const types = [...(nextArr[index].types_perturbation || [])];
|
||||
if (mins > 0 && !types.includes('reduction_retard')) types.push('reduction_retard');
|
||||
else if (mins === 0) {
|
||||
const idx = types.indexOf('reduction_retard');
|
||||
if (idx !== -1) types.splice(idx, 1);
|
||||
}
|
||||
nextArr[index].types_perturbation = types;
|
||||
nextArr[index].type_perturbation = getPrimaryType(types);
|
||||
}
|
||||
@@ -538,8 +572,10 @@ export default function CreerPerturbation() {
|
||||
</div>
|
||||
<div className="horaire-display-content" style={{ maxHeight: '200px', overflowY: 'auto' }}>
|
||||
{selectedHoraires.map(h => (
|
||||
<div key={h.id} style={{ padding: '8px 0', borderBottom: '1px solid #eee' }}>
|
||||
<strong>Train {h.numero_train}</strong> ({h.ligne_nom || 'N/A'}) - {h.gare_depart_nom} → {h.gare_arrivee_nom}
|
||||
<div key={h.id} style={{ padding: '8px 0', borderBottom: '1px solid #eee', display: 'flex', alignItems: 'center', gap: '6px' }}>
|
||||
<strong>Train {h.numero_train}</strong> ({h.ligne_nom || 'N/A'}) - {h.gare_depart_nom}
|
||||
<wcs-mat-icon icon="arrow_forward" style={{ fontSize: '13px', margin: '0 4px', color: '#94a3b8' }}></wcs-mat-icon>
|
||||
{h.gare_arrivee_nom}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
@@ -573,8 +609,8 @@ export default function CreerPerturbation() {
|
||||
style={{ padding: '12px 16px', background: '#e9ecef', cursor: 'pointer', display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}
|
||||
onClick={() => toggleTrainAccordion(h.id)}
|
||||
>
|
||||
<h4 style={{ margin: 0, fontSize: '1rem', color: '#333' }}>
|
||||
Train {h.numero_train} ({h.gare_depart_nom} → {h.gare_arrivee_nom})
|
||||
<h4 style={{ margin: 0, fontSize: '1rem', color: '#333', display: 'flex', alignItems: 'center', gap: '6px' }}>
|
||||
Train {h.numero_train} ({h.gare_depart_nom} <wcs-mat-icon icon="arrow_forward" style={{ fontSize: '13px' }}></wcs-mat-icon> {h.gare_arrivee_nom})
|
||||
</h4>
|
||||
<wcs-mat-icon icon={openTrains[h.id] ? 'expand_less' : 'expand_more'} style={{ color: '#555' }} />
|
||||
</div>
|
||||
@@ -677,8 +713,10 @@ export default function CreerPerturbation() {
|
||||
Départ : {formatHeure(h.heure_depart)}
|
||||
</span>
|
||||
</div>
|
||||
<div>
|
||||
{h.gare_depart_nom} → {h.gare_arrivee_nom}
|
||||
<div style={{ display: 'flex', alignItems: 'center', gap: '4px' }}>
|
||||
<span>{h.gare_depart_nom}</span>
|
||||
<wcs-mat-icon icon="arrow_forward" style={{ fontSize: '13px', margin: '0 4px', color: '#94a3b8' }}></wcs-mat-icon>
|
||||
<span>{h.gare_arrivee_nom}</span>
|
||||
</div>
|
||||
<div style={{ fontSize: '0.9rem', color: '#4b5563' }}>
|
||||
Matériel actuel : {h.composition_train?.map(c => `${c.materiel_nom}`).join(', ') || 'Aucun'}
|
||||
@@ -717,7 +755,7 @@ export default function CreerPerturbation() {
|
||||
<select id="sillon" value={sillonSubstitutionId} onChange={e => setSillonSubstitutionId(e.target.value)} className="form-select">
|
||||
<option value="">Aucun</option>
|
||||
{horaires.filter(h => h.id !== selectedHoraires[0].id).slice(0, 50).map(h => (
|
||||
<option key={h.id} value={h.id}>{h.numero_train} - {h.gare_depart_nom} → {h.gare_arrivee_nom}</option>
|
||||
<option key={h.id} value={h.id}>{h.numero_train} - {h.gare_depart_nom} vers {h.gare_arrivee_nom}</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
@@ -762,29 +800,76 @@ export default function CreerPerturbation() {
|
||||
|
||||
// ── Rendu principal ───────────────────────────────────────────────────────
|
||||
return (
|
||||
<div className="sncf-groupe">
|
||||
<div className="sncf-groupe perturbations-page-root">
|
||||
<div className="panel-layout">
|
||||
<div className="panel-nav"><NavPanel /></div>
|
||||
<div className="panel-content">
|
||||
<header className="page-header">
|
||||
<h1>Créer une perturbation</h1>
|
||||
<p className="page-description">
|
||||
Étape {currentStep === 'horaire' ? '1' : '2'} / 2 —{' '}
|
||||
{currentStep === 'horaire' ? 'Sélection des horaires' : 'Configuration'}
|
||||
</p>
|
||||
<div className="panel-content perturbations-modern-container">
|
||||
{/* Header Banner */}
|
||||
<header className="page-header-modern">
|
||||
<div className="header-info">
|
||||
<div className="perturbations-hero-tags" style={{ marginBottom: '8px' }}>
|
||||
<span className="perturbations-kicker-pill">
|
||||
<wcs-mat-icon icon="add_alert"></wcs-mat-icon>
|
||||
Déclaration d'incident
|
||||
</span>
|
||||
{scopedRegionId && (
|
||||
<span className="perturbations-region-badge">
|
||||
<wcs-mat-icon icon="place"></wcs-mat-icon>
|
||||
Région : {scopedRegionId}
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
<h1>Déclarer une perturbation sur les circulations</h1>
|
||||
<p>Signalez un retard, une suppression d'arrêt ou une modification de parcours en temps réel.</p>
|
||||
</div>
|
||||
|
||||
<div className="header-actions">
|
||||
<wcs-button className="wcs-secondary" mode="stroked" onClick={handleCancel}>
|
||||
<wcs-mat-icon icon="close" style={{ marginRight: '6px' }}></wcs-mat-icon>
|
||||
Annuler
|
||||
</wcs-button>
|
||||
</div>
|
||||
</header>
|
||||
<div className="creation-container">
|
||||
<div className="creation-main">
|
||||
|
||||
{/* Stepper */}
|
||||
<div className="stepper-horizontal">
|
||||
<div
|
||||
className={`step-item ${currentStep === 'horaire' ? 'active' : 'completed'}`}
|
||||
onClick={() => setCurrentStep('horaire')}
|
||||
style={{ cursor: 'pointer' }}
|
||||
>
|
||||
<div className="step-icon">
|
||||
{currentStep === 'perturbation' ? <wcs-mat-icon icon="check" style={{ fontSize: '14px' }}></wcs-mat-icon> : '1'}
|
||||
</div>
|
||||
<span>1. Sélection des trains</span>
|
||||
</div>
|
||||
<div className="step-divider"></div>
|
||||
<div
|
||||
className={`step-item ${currentStep === 'perturbation' ? 'active' : ''}`}
|
||||
onClick={() => selectedHoraires.length > 0 && setCurrentStep('perturbation')}
|
||||
style={{ cursor: selectedHoraires.length > 0 ? 'pointer' : 'not-allowed' }}
|
||||
>
|
||||
<div className="step-icon">2</div>
|
||||
<span>2. Configuration de l'incident & Parcours</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="creation-layout-modern">
|
||||
<div className="creation-main-content">
|
||||
{currentStep === 'horaire' && renderStepHoraire()}
|
||||
{currentStep === 'perturbation' && renderStepPerturbation()}
|
||||
</div>
|
||||
<div className="creation-preview">
|
||||
|
||||
<div className="sticky-sidebar">
|
||||
{selectedHoraires.length === 1 && (
|
||||
<ParcoursPreview arrets={perturbationsArretsMap[selectedHoraires[0].id]} />
|
||||
)}
|
||||
{selectedHoraires.length > 1 && (
|
||||
<div style={{ padding: '15px', color: '#666', fontStyle: 'italic', background: '#f9f9f9', borderRadius: '8px', border: '1px solid #ddd' }}>
|
||||
Aperçu du parcours non disponible lors de la sélection multiple. Veuillez vous référer aux accordéons détaillés.
|
||||
<div className="summary-card">
|
||||
<h3>Sélection multiple ({selectedHoraires.length} trains)</h3>
|
||||
<p style={{ fontSize: '13px', color: '#64748b', margin: 0 }}>
|
||||
Configurez le motif commun et ajustez les arrêts de chaque train via les accordéons.
|
||||
</p>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
Reference in new issue
Block a user