55const API_KEY = 'SvPHVJ5fPXkfJPKsu6958pwLCh5Oidhq' ;
66const API_URL = 'https://prim.iledefrance-mobilites.fr/marketplace/stop-monitoring' ;
77
8+ // Configuration de l'affichage des horaires
9+ const MAX_SCHEDULES_METRO_TRAM = 5 ; // Nombre d'horaires affichés pour Métro/Tram
10+ const MAX_SCHEDULES_RAIL = 10 ; // Nombre d'horaires affichés pour RER/TER/Transilien
11+
812/**
913 * Extrait l'ID numérique d'un stop_id complexe
1014 * Exemples:
@@ -153,23 +157,34 @@ function parseSchedulesData(data) {
153157 const destinationName = journey . DestinationName ?. [ 0 ] ?. value ||
154158 journey . DestinationName ?. value ||
155159 'Destination inconnue' ;
156- const departureTime = journey . MonitoredCall ?. ExpectedDepartureTime ||
157- journey . MonitoredCall ?. AimedDepartureTime ;
160+ const aimedTime = journey . MonitoredCall ?. AimedDepartureTime ;
161+ const expectedTime = journey . MonitoredCall ?. ExpectedDepartureTime ;
158162 const platform = journey . MonitoredCall ?. DeparturePlatformName ?. value ||
159163 journey . MonitoredCall ?. ArrivalPlatformName ?. value ||
160164 '-' ;
161165
162- if ( departureTime ) {
166+ // Vérifier si le train est annulé
167+ const isCancelled = journey . MonitoredCall ?. DepartureStatus === 'cancelled' ||
168+ journey . MonitoredCall ?. VehicleAtStop === false &&
169+ journey . MonitoredCall ?. ExpectedDepartureTime === undefined ;
170+
171+ if ( aimedTime || expectedTime ) {
163172 schedules . push ( {
164173 destination : destinationName ,
165- time : departureTime ,
166- platform : platform
174+ aimedTime : aimedTime ,
175+ expectedTime : expectedTime ,
176+ platform : platform ,
177+ isCancelled : isCancelled
167178 } ) ;
168179 }
169180 } ) ;
170181
171- // Trier par heure
172- schedules . sort ( ( a , b ) => new Date ( a . time ) - new Date ( b . time ) ) ;
182+ // Trier par heure (utiliser expectedTime si disponible, sinon aimedTime)
183+ schedules . sort ( ( a , b ) => {
184+ const timeA = new Date ( a . expectedTime || a . aimedTime ) ;
185+ const timeB = new Date ( b . expectedTime || b . aimedTime ) ;
186+ return timeA - timeB ;
187+ } ) ;
173188
174189 console . log ( `Parsed ${ schedules . length } schedules` ) ;
175190
@@ -191,49 +206,84 @@ export function generateSchedulesHTML(schedules, routeType) {
191206 // Déterminer si on affiche la colonne voie (uniquement pour RER, TER, Transilien)
192207 const showPlatform = routeType === 'RER' || routeType === 'TER' || routeType === 'Transilien' ;
193208
194- // Construire le tableau HTML
209+ // Déterminer le nombre d'horaires à afficher selon le type de transport
210+ const maxSchedules = showPlatform ? MAX_SCHEDULES_RAIL : MAX_SCHEDULES_METRO_TRAM ;
211+
212+ // Construire le tableau HTML avec scroll si nécessaire pour RER/TER/Transilien
213+ const tableStyle = showPlatform ? 'max-height: 300px; overflow-y: auto;' : '' ;
214+
195215 let html = `
196216 <div style="font-size: 11px;">
197217 <h5 style="margin: 0 0 6px 0; font-size: 12px; font-weight: 600;">Prochains passages</h5>
198- <table style="width: 100%; border-collapse: collapse; font-size: 11px;">
199- <thead>
200- <tr style="border-bottom: 1px solid #ddd;">
201- <th style="text-align: left; padding: 4px; font-weight: 600;">Heure</th>
202- <th style="text-align: left; padding: 4px; font-weight: 600;">Direction</th>
203- ${ showPlatform ? '<th style="text-align: center; padding: 4px; font-weight: 600;">Voie</th>' : '' }
204- </tr>
205- </thead>
206- <tbody>
218+ <div style="${ tableStyle } ">
219+ <table style="width: 100%; border-collapse: collapse; font-size: 11px;">
220+ <thead>
221+ <tr style="border-bottom: 1px solid #ddd;">
222+ <th style="text-align: left; padding: 4px; font-weight: 600;">Heure</th>
223+ <th style="text-align: left; padding: 4px; font-weight: 600;">Direction</th>
224+ ${ showPlatform ? '<th style="text-align: center; padding: 4px; font-weight: 600;">Voie</th>' : '' }
225+ </tr>
226+ </thead>
227+ <tbody>
207228 ` ;
208229
209- // Limiter à 5 horaires maximum
210- schedules . slice ( 0 , 5 ) . forEach ( schedule => {
211- const time = new Date ( schedule . time ) ;
230+ // Limiter selon le type de transport
231+ schedules . slice ( 0 , maxSchedules ) . forEach ( schedule => {
212232 const now = new Date ( ) ;
213- const diffMinutes = Math . round ( ( time - now ) / 60000 ) ;
233+ const aimedTime = schedule . aimedTime ? new Date ( schedule . aimedTime ) : null ;
234+ const expectedTime = schedule . expectedTime ? new Date ( schedule . expectedTime ) : null ;
235+ const isCancelled = schedule . isCancelled || false ;
236+
237+ // Utiliser expectedTime si disponible, sinon aimedTime
238+ const displayTime = expectedTime || aimedTime ;
239+ const diffMinutes = Math . round ( ( displayTime - now ) / 60000 ) ;
214240
215- // Afficher "X min" si moins de 60 minutes, sinon l'heure
241+ // Style pour les trains annulés (barré en rouge)
242+ const cancelledStyle = isCancelled ? 'text-decoration: line-through; color: #dc2626;' : '' ;
243+
244+ // Pour RER, TER et Transilien : toujours afficher l'heure originale
245+ // Pour Métro et Tram : afficher "X min" basé sur le temps réel (avec retard)
216246 let timeStr ;
217- if ( diffMinutes < 0 ) {
218- timeStr = time . toLocaleTimeString ( 'fr-FR' , { hour : '2-digit' , minute : '2-digit' } ) ;
219- } else if ( diffMinutes < 60 ) {
220- timeStr = `${ diffMinutes } min` ;
247+ if ( routeType === 'RER' || routeType === 'TER' || routeType === 'Transilien' ) {
248+ // Toujours afficher l'heure originale
249+ timeStr = aimedTime . toLocaleTimeString ( 'fr-FR' , { hour : '2-digit' , minute : '2-digit' } ) ;
221250 } else {
222- timeStr = time . toLocaleTimeString ( 'fr-FR' , { hour : '2-digit' , minute : '2-digit' } ) ;
251+ // Pour métro/tram : afficher "X min" basé sur displayTime (temps réel avec retard)
252+ if ( diffMinutes < 0 ) {
253+ timeStr = displayTime . toLocaleTimeString ( 'fr-FR' , { hour : '2-digit' , minute : '2-digit' } ) ;
254+ } else if ( diffMinutes < 60 ) {
255+ timeStr = `${ diffMinutes } min` ;
256+ } else {
257+ timeStr = displayTime . toLocaleTimeString ( 'fr-FR' , { hour : '2-digit' , minute : '2-digit' } ) ;
258+ }
259+ }
260+
261+ // Calculer le retard si expectedTime existe et est différent
262+ // Pour RER/TER/Transilien : afficher l'heure de retard en orange
263+ // Pour Métro/Tram : ne pas afficher (déjà inclus dans "X min")
264+ let delayHTML = '' ;
265+ if ( ( routeType === 'RER' || routeType === 'TER' || routeType === 'Transilien' ) &&
266+ expectedTime && aimedTime && expectedTime > aimedTime ) {
267+ const delayMinutes = Math . round ( ( expectedTime - aimedTime ) / 60000 ) ;
268+ if ( delayMinutes > 0 ) {
269+ const expectedTimeStr = expectedTime . toLocaleTimeString ( 'fr-FR' , { hour : '2-digit' , minute : '2-digit' } ) ;
270+ delayHTML = ` <span style="color: #ff8800; font-weight: 600;">${ expectedTimeStr } </span>` ;
271+ }
223272 }
224273
225274 html += `
226- <tr style="border-bottom: 1px solid #eee;">
227- <td style="padding: 4px; white-space: nowrap;">${ timeStr } </td>
228- <td style="padding: 4px;">${ schedule . destination } </td>
229- ${ showPlatform ? `<td style="padding: 4px; text-align: center;">${ schedule . platform } </td>` : '' }
275+ <tr style="border-bottom: 1px solid #eee; ${ cancelledStyle } ">
276+ <td style="padding: 4px; white-space: nowrap; ${ cancelledStyle } ">${ timeStr } ${ delayHTML } </td>
277+ <td style="padding: 4px; ${ cancelledStyle } ">${ schedule . destination } </td>
278+ ${ showPlatform ? `<td style="padding: 4px; text-align: center; ${ cancelledStyle } ">${ schedule . platform } </td>` : '' }
230279 </tr>
231280 ` ;
232281 } ) ;
233282
234283 html += `
235- </tbody>
236- </table>
284+ </tbody>
285+ </table>
286+ </div>
237287 </div>
238288 ` ;
239289
0 commit comments