Skip to content

Commit 766377e

Browse files
committed
consolidate color usage
1 parent 6acd51e commit 766377e

2 files changed

Lines changed: 30 additions & 82 deletions

File tree

src/pathDetails/elevationWidget/colors.ts

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,13 +68,22 @@ export const TOLL_COLORS: Record<string, string> = {
6868
hgv: '#FF9800',
6969
}
7070

71+
export const NETWORK_COLORS: Record<string, string> = {
72+
international: '#2E7D32',
73+
national: '#66BB6A',
74+
regional: '#1565C0',
75+
local: '#42A5F5',
76+
}
77+
7178
// Named color maps for known detail keys
72-
const NAMED_COLOR_MAPS: Record<string, Record<string, string>> = {
79+
export const NAMED_COLOR_MAPS: Record<string, Record<string, string>> = {
7380
surface: SURFACE_COLORS,
7481
road_class: ROAD_CLASS_COLORS,
7582
road_environment: ROAD_ENVIRONMENT_COLORS,
7683
track_type: TRACK_TYPE_COLORS,
7784
toll: TOLL_COLORS,
85+
bike_network: NETWORK_COLORS,
86+
foot_network: NETWORK_COLORS,
7887
}
7988

8089
// Incline categories: grouped by absolute slope percentage

src/sidebar/RouteStats.tsx

Lines changed: 20 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -5,61 +5,7 @@ import { calcDist } from '@/utils'
55
import { ApiImpl } from '@/api/Api'
66
import { tr } from '@/translation/Translation'
77
import styles from './RouteStats.module.css'
8-
9-
// Stable color map: same value always gets the same color regardless of route
10-
const VALUE_COLORS: Record<string, string> = {
11-
// Surface - paved (greens)
12-
asphalt: '#2E7D32',
13-
paved: '#43A047',
14-
concrete: '#66BB6A',
15-
paving_stones: '#81C784',
16-
'concrete:plates': '#A5D6A7',
17-
'concrete:lanes': '#388E3C',
18-
metal: '#00897B',
19-
// Surface - unpaved (warm/natural tones)
20-
compacted: '#FFB74D',
21-
gravel: '#FF8A65',
22-
fine_gravel: '#FFCC80',
23-
unpaved: '#C68642',
24-
ground: '#9E9D24',
25-
earth: '#8D6E63',
26-
grass: '#7CB342',
27-
grass_paver: '#AED581',
28-
sand: '#FFD54F',
29-
mud: '#5D4037',
30-
// Surface - rough/uncomfortable (reds/pinks)
31-
dirt: '#E53935',
32-
wood: '#C62828',
33-
cobblestone: '#D81B60',
34-
sett: '#AD1457',
35-
unhewn_cobblestone: '#880E4F',
36-
// Road classes
37-
motorway: '#D32F2F',
38-
trunk: '#E64A19',
39-
primary: '#F57C00',
40-
secondary: '#FFA726',
41-
tertiary: '#42A5F5',
42-
residential: '#66BB6A',
43-
unclassified: '#78909C',
44-
living_street: '#81C784',
45-
service: '#A5D6A7',
46-
cycleway: '#2E7D32',
47-
path: '#66BB6A',
48-
track: '#81C784',
49-
bridleway: '#795548',
50-
footway: '#EC407A',
51-
pedestrian: '#F48FB1',
52-
steps: '#FF5722',
53-
// Network levels
54-
international: '#2E7D32',
55-
national: '#66BB6A',
56-
regional: '#1565C0',
57-
local: '#42A5F5',
58-
}
59-
60-
const INCLINE_COLORS = ['#2E7D32', '#FF9800', '#F44336', '#7B1FA2']
61-
const INCLINE_LABELS = ['flat (<3%)', 'mild (3–6%)', 'steep (6–10%)', 'very steep (≥10%)']
62-
const SPEED_COLORS = ['#F44336', '#FF9800', '#FFD54F', '#66BB6A', '#2E7D32']
8+
import { NAMED_COLOR_MAPS, INCLINE_CATEGORIES, SPEED_COLORS, getSpeedThresholds, getSpeedLabels } from '@/pathDetails/elevationWidget/colors'
639

6410
const PAVED = new Set(['asphalt', 'concrete', 'paved', 'paving_stones', 'concrete:plates', 'concrete:lanes', 'metal'])
6511
const UNPAVED = new Set([
@@ -102,7 +48,7 @@ function computeInclineDistances(coords: Position[], thresholds: number[]): numb
10248
if (dist > 100) {
10349
const slope = (100 * Math.abs(c[2] - prevEle[2])) / dist
10450
for (let t = 0; t < thresholds.length; t++)
105-
if (slope >= thresholds[t]) distAbove[t] += dist
51+
if (slope > thresholds[t]) distAbove[t] += dist
10652
prevEle = c
10753
dist = 0
10854
}
@@ -145,12 +91,6 @@ function formatTime(minutes: number): string {
14591
return h > 0 ? `${h} h ${m} min` : `${m} min`
14692
}
14793

148-
function getSpeedThresholds(profile: string): number[] {
149-
if (ApiImpl.isMotorVehicle(profile)) return [30, 50, 80]
150-
if (ApiImpl.isFootLike(profile)) return [3, 4, 5]
151-
return [5, 10, 15, 20]
152-
}
153-
15494
// --- Detail entries & components ---
15595

15696
interface DetailEntry {
@@ -168,26 +108,26 @@ interface SummaryEntry {
168108
}
169109

170110
/** Get colors of the top N contributors and whether there are more */
171-
function topColors(distMap: Map<string, number>, keys: Iterable<string>, n: number = 4) {
111+
function topColors(colorMap: Record<string, string>, distMap: Map<string, number>, keys: Iterable<string>, n: number = 4) {
172112
const sorted = [...keys]
173113
.map(k => ({ key: k, dist: distMap.get(k) || 0 }))
174114
.filter(e => e.dist > 0)
175115
.sort((a, b) => b.dist - a.dist)
176116
return {
177-
colors: sorted.slice(0, n).map(e => VALUE_COLORS[e.key] || '#BDBDBD'),
117+
colors: sorted.slice(0, n).map(e => colorMap[e.key] || '#BDBDBD'),
178118
more: sorted.length > n,
179119
}
180120
}
181121

182122
/** Build detail entries from a distance map, sorted by distance descending */
183-
function detailEntries(distMap: Map<string, number>, totalDist: number, missingLabel = 'unknown'): DetailEntry[] {
123+
function detailEntries(colorMap: Record<string, string>, distMap: Map<string, number>, totalDist: number, missingLabel = 'unknown'): DetailEntry[] {
184124
return [...distMap.entries()]
185125
.filter(([, d]) => d > 0)
186126
.sort((a, b) => b[1] - a[1])
187127
.map(([name, d]) => ({
188128
name: (!name || name === 'missing') ? missingLabel : name,
189129
km: fmtKm(d),
190-
color: VALUE_COLORS[name] || '#BDBDBD',
130+
color: colorMap[name] || '#BDBDBD',
191131
fraction: d / totalDist,
192132
}))
193133
}
@@ -276,16 +216,17 @@ export default function RouteStats({ path, profile }: { path: Path; profile: str
276216
const lines: React.ReactNode[] = []
277217

278218
// Surface
219+
const surfaceColors = NAMED_COLOR_MAPS['surface'] || {}
279220
if (path.details.surface) {
280221
const dist = computeDetailDistances(coords, path.details.surface)
281222
if (dist.size > 0) {
282223
const pavedDist = sumForKeys(dist, PAVED)
283224
const unpavedDist = sumForKeys(dist, UNPAVED)
284225
const extra: SummaryEntry[] = []
285-
if (pavedDist > 0) extra.push({ name: 'paved', value: pct(pavedDist, totalDist), ...topColors(dist, PAVED) })
286-
if (unpavedDist > 0) extra.push({ name: 'unpaved', value: pct(unpavedDist, totalDist), ...topColors(dist, UNPAVED) })
226+
if (pavedDist > 0) extra.push({ name: 'paved', value: pct(pavedDist, totalDist), ...topColors(surfaceColors, dist, PAVED) })
227+
if (unpavedDist > 0) extra.push({ name: 'unpaved', value: pct(unpavedDist, totalDist), ...topColors(surfaceColors, dist, UNPAVED) })
287228
lines.push(
288-
<ExpandableStat key="surface" label={tr('route_stats_surface')} details={detailEntries(dist, totalDist)} extraInfo={extra} />,
229+
<ExpandableStat key="surface" label={tr('route_stats_surface')} details={detailEntries(surfaceColors, dist, totalDist)} extraInfo={extra} />,
289230
)
290231
}
291232
}
@@ -297,34 +238,36 @@ export default function RouteStats({ path, profile }: { path: Path; profile: str
297238
]
298239
for (const [key, label, details, active] of networks) {
299240
if (active && details) {
241+
const colors = NAMED_COLOR_MAPS[key] || {}
300242
const dist = computeDetailDistances(coords, details)
301243
const onNetwork = sumForKeys(dist, NETWORK_KEYS)
302244
if (dist.size > 0) {
303245
lines.push(
304246
<ExpandableStat
305247
key={key}
306248
label={label}
307-
details={detailEntries(dist, totalDist, 'none')}
308-
extraInfo={[{ name: 'on network', value: pct(onNetwork, totalDist), ...topColors(dist, NETWORK_KEYS) }]}
249+
details={detailEntries(colors, dist, totalDist, 'none')}
250+
extraInfo={[{ name: 'on network', value: pct(onNetwork, totalDist), ...topColors(colors, dist, NETWORK_KEYS) }]}
309251
/>,
310252
)
311253
}
312254
}
313255
}
314256

315257
// Roads
258+
const roadColors = NAMED_COLOR_MAPS['road_class'] || {}
316259
if (path.details.road_class) {
317260
const dist = computeDetailDistances(coords, path.details.road_class)
318261
if (dist.size > 0) {
319262
const extra: SummaryEntry[] = []
320263
const big = sumForKeys(dist, BIG_ROADS)
321264
const medium = sumForKeys(dist, MEDIUM_ROADS)
322265
const small = sumForKeys(dist, SMALL_ROADS)
323-
if (big > 0) extra.push({ name: 'big roads', value: pct(big, totalDist), ...topColors(dist, BIG_ROADS) })
324-
if (medium > 0) extra.push({ name: 'medium', value: pct(medium, totalDist), ...topColors(dist, MEDIUM_ROADS) })
325-
if (small > 0) extra.push({ name: 'small', value: pct(small, totalDist), ...topColors(dist, SMALL_ROADS) })
266+
if (big > 0) extra.push({ name: 'big roads', value: pct(big, totalDist), ...topColors(roadColors, dist, BIG_ROADS) })
267+
if (medium > 0) extra.push({ name: 'medium', value: pct(medium, totalDist), ...topColors(roadColors, dist, MEDIUM_ROADS) })
268+
if (small > 0) extra.push({ name: 'small', value: pct(small, totalDist), ...topColors(roadColors, dist, SMALL_ROADS) })
326269
lines.push(
327-
<ExpandableStat key="roads" label={tr('route_stats_roads')} details={detailEntries(dist, totalDist)} extraInfo={extra} />,
270+
<ExpandableStat key="roads" label={tr('route_stats_roads')} details={detailEntries(roadColors, dist, totalDist)} extraInfo={extra} />,
328271
)
329272
}
330273
}
@@ -335,7 +278,7 @@ export default function RouteStats({ path, profile }: { path: Path; profile: str
335278
if (distAbove[0] > 0) {
336279
const segments = [totalDist - distAbove[0], distAbove[0] - distAbove[1], distAbove[1] - distAbove[2], distAbove[2]]
337280
const inclineDetails = segments
338-
.map((d, i) => ({ name: INCLINE_LABELS[i], km: fmtKm(d), color: INCLINE_COLORS[i], fraction: d / totalDist }))
281+
.map((d, i) => ({ name: INCLINE_CATEGORIES[i].label, km: fmtKm(d), color: INCLINE_CATEGORIES[i].color, fraction: d / totalDist }))
339282
.filter(d => d.fraction > 0)
340283
lines.push(
341284
<ExpandableStat
@@ -356,11 +299,7 @@ export default function RouteStats({ path, profile }: { path: Path; profile: str
356299
const thresholds = getSpeedThresholds(profile)
357300
const distBelow = computeSpeedDistances(coords, path.details.average_speed, thresholds)
358301
const boundaries = [0, ...distBelow, totalDist]
359-
const speedLabels = [
360-
`< ${thresholds[0]}`,
361-
...thresholds.slice(0, -1).map((t, i) => `${t}${thresholds[i + 1]}`),
362-
`≥ ${thresholds[thresholds.length - 1]}`,
363-
].map(s => `${s} km/h`)
302+
const speedLabels = getSpeedLabels(thresholds).map(s => `${s} km/h`)
364303
const speedDetails = boundaries
365304
.slice(0, -1)
366305
.map((_, i) => ({

0 commit comments

Comments
 (0)