@@ -14,14 +14,15 @@ export const ROAD_CONDITION_SEVERITY_RANK: Record<string, number> = {
1414const POPUP_SPEC : PopupCardSpec = {
1515 titleField : "headline" ,
1616 severityField : "severity" ,
17+ severityLabelField : "severityText" ,
1718 attributionField : "attribution" ,
1819 rows : [
19- { field : "type " , labelKey : "panel.type" , format : "label ", variant : "chip" } ,
20- { field : "roadState " , labelKey : "panel.roadState" , format : "label ", variant : "chip" } ,
20+ { field : "typeText " , labelKey : "panel.type" , variant : "chip" } ,
21+ { field : "roadStateText " , labelKey : "panel.roadState" , variant : "chip" } ,
2122 { field : "roads" , labelKey : "panel.roads" , variant : "row" } ,
2223 { field : "recordId" , labelKey : "panel.sourceRecord" , variant : "row" } ,
2324 { field : "validity" , labelKey : "panel.validity" , variant : "row" } ,
24- { field : "startsAt" , variant : "row" } ,
25+ { field : "startsAt" , labelKey : "panel.startsAt" , variant : "row" } ,
2526 { field : "delayText" , labelKey : "panel.delay" , variant : "row" } ,
2627 { field : "description" , labelKey : "panel.description" , variant : "block" } ,
2728 ] ,
@@ -30,9 +31,10 @@ const POPUP_SPEC: PopupCardSpec = {
3031const SOURCE_DETAIL_SPEC : PopupCardSpec = {
3132 titleField : "headline" ,
3233 severityField : "severity" ,
34+ severityLabelField : "severityText" ,
3335 rows : [
34- { field : "type " , labelKey : "panel.type" , format : "label ", variant : "chip" } ,
35- { field : "roadState " , labelKey : "panel.roadState" , format : "label ", variant : "chip" } ,
36+ { field : "typeText " , labelKey : "panel.type" , variant : "chip" } ,
37+ { field : "roadStateText " , labelKey : "panel.roadState" , variant : "chip" } ,
3638 { field : "roads" , labelKey : "panel.roads" , variant : "row" } ,
3739 { field : "recordId" , labelKey : "panel.sourceRecord" , variant : "row" } ,
3840 { field : "validity" , labelKey : "panel.validity" , variant : "row" } ,
@@ -73,19 +75,26 @@ function formatValidity(
7375 to : unknown ,
7476 fmtDateTime : ( value : string | number | Date ) => string ,
7577 fmtDate : ( value : string | number | Date ) => string ,
78+ translate : RoadConditionTranslate ,
7679) : string {
7780 if ( typeof scheduleJson === "string" && scheduleJson ) {
7881 try {
7982 const windows = JSON . parse ( scheduleJson ) as ScheduleEntry [ ] ;
8083 const hhmm = ( time ?: string ) => ( time ? time . slice ( 0 , 5 ) : "" ) ;
8184 const parts = windows
8285 . map ( ( window ) => {
83- const days = window . byDay && window . byDay . length > 0 ? window . byDay . join ( ", " ) : "" ;
86+ const days =
87+ window . byDay && window . byDay . length > 0
88+ ? window . byDay
89+ . map ( ( day ) => scheduleDayLabel ( day , translate ) )
90+ . filter ( Boolean )
91+ . join ( ", " )
92+ : "" ;
8493 const band =
8594 window . startTime && window . endTime
8695 ? `${ hhmm ( window . startTime ) } –${ hhmm ( window . endTime ) } `
8796 : window . startTime
88- ? `from ${ hhmm ( window . startTime ) } `
97+ ? `${ translate ( "schedule. from" ) } ${ hhmm ( window . startTime ) } `
8998 : "" ;
9099 const range =
91100 window . startDate && window . endDate
@@ -107,6 +116,53 @@ function formatValidity(
107116 return `${ f || "…" } – ${ t || "…" } ` ;
108117}
109118
119+ const ROAD_CONDITION_TYPES = new Set < RoadConditionType > ( [
120+ "accident" ,
121+ "roadworks" ,
122+ "road_closure" ,
123+ "lane_closure" ,
124+ "hazard" ,
125+ "congestion" ,
126+ "weather" ,
127+ "event" ,
128+ "restriction" ,
129+ "other" ,
130+ ] ) ;
131+
132+ const ROAD_CONDITION_STATES = new Set ( [
133+ "open" ,
134+ "closed" ,
135+ "some_lanes_closed" ,
136+ "single_lane_alternating" ,
137+ ] ) ;
138+
139+ const ROAD_CONDITION_SEVERITIES = new Set ( Object . keys ( ROAD_CONDITION_SEVERITY_RANK ) ) ;
140+ const SCHEDULE_WEEKDAY_CODES = new Set ( [ "MO" , "TU" , "WE" , "TH" , "FR" , "SA" , "SU" ] ) ;
141+
142+ function humanizeToken ( raw : string ) : string {
143+ const value = raw . replace ( / [ _ - ] + / g, " " ) . trim ( ) ;
144+ return value . length === 0 ? value : value . charAt ( 0 ) . toUpperCase ( ) + value . slice ( 1 ) ;
145+ }
146+
147+ function localizedTokenList (
148+ raw : unknown ,
149+ prefix : string ,
150+ known : ReadonlySet < string > ,
151+ translate : RoadConditionTranslate ,
152+ ) : string | undefined {
153+ if ( typeof raw !== "string" ) return undefined ;
154+ const tokens = distinctNonEmpty ( raw . split ( "," ) ) ;
155+ if ( tokens . length === 0 ) return undefined ;
156+ return tokens
157+ . map ( ( token ) => ( known . has ( token ) ? translate ( `${ prefix } .${ token } ` ) : humanizeToken ( token ) ) )
158+ . join ( ", " ) ;
159+ }
160+
161+ function scheduleDayLabel ( day : string , translate : RoadConditionTranslate ) : string {
162+ const code = day . trim ( ) . toUpperCase ( ) ;
163+ return SCHEDULE_WEEKDAY_CODES . has ( code ) ? translate ( `schedule.days.${ code } ` ) : day . trim ( ) ;
164+ }
165+
110166function attributionString ( raw : unknown ) : string {
111167 if ( typeof raw === "string" ) return raw ;
112168 if ( raw && typeof raw === "object" ) {
@@ -246,10 +302,29 @@ function formatPopupEntry(
246302 sourceEntry . validTo ,
247303 input . formatDateTime ,
248304 input . formatDate ,
305+ input . translate ,
306+ ) ;
307+ const typeText = localizedTokenList (
308+ sourceEntry . type ,
309+ "type" ,
310+ ROAD_CONDITION_TYPES ,
311+ input . translate ,
312+ ) ;
313+ const roadStateText = localizedTokenList (
314+ sourceEntry . roadState ,
315+ "roadState" ,
316+ ROAD_CONDITION_STATES ,
317+ input . translate ,
318+ ) ;
319+ const severityText = localizedTokenList (
320+ sourceEntry . severity ,
321+ "sev" ,
322+ ROAD_CONDITION_SEVERITIES ,
323+ input . translate ,
249324 ) ;
250325 const startsAt =
251326 sourceEntry . future === true && typeof sourceEntry . validFrom === "string"
252- ? input . translate ( "startsAt" , { date : input . formatDateTime ( sourceEntry . validFrom ) } )
327+ ? input . formatDateTime ( sourceEntry . validFrom )
253328 : undefined ;
254329 const delaySeconds = Number ( sourceEntry . delaySeconds ) ;
255330 const delayText =
@@ -258,6 +333,9 @@ function formatPopupEntry(
258333 : undefined ;
259334 return {
260335 ...sourceEntry ,
336+ ...( typeText ? { typeText } : { } ) ,
337+ ...( roadStateText ? { roadStateText } : { } ) ,
338+ ...( severityText ? { severityText } : { } ) ,
261339 ...( validity ? { validity } : { } ) ,
262340 ...( startsAt ? { startsAt } : { } ) ,
263341 ...( delayText ? { delayText } : { } ) ,
0 commit comments