Skip to content

Commit 137ae6f

Browse files
chtituxclaude
andauthored
Website: condenser les libellés de période (« du lundi au samedi ») (#8)
Les labels per-day-of-week d'un même hint sont regroupés et les jours consécutifs affichés en « du … au … » : la carte « Vacances scolaires (lun-sam) — lundis + … — samedis + samedis » devient « Vacances scolaires (lun-sam) : du lundi au samedi + samedis ». Appliqué aux cartes de synthèse et à la légende du calendrier. Claude-Session: https://claude.ai/code/session_01K46F5NwLZgpri9Nrw395rD Co-authored-by: Claude <noreply@anthropic.com>
1 parent d37de21 commit 137ae6f

3 files changed

Lines changed: 63 additions & 3 deletions

File tree

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,11 @@
22

33
## Upcoming release
44

5+
- Demo: period labels now group the per-day-of-week entries of a hint and
6+
condense consecutive weekdays into a range, e.g. « Vacances scolaires
7+
(lun-sam) : du lundi au samedi + samedis » instead of one « … — lundis »
8+
entry per weekday. Applies to the period cards and the calendar legend.
9+
510
- Demo: new « Sous le capot » section under the results with two collapsible,
611
syntax-highlighted (Prism) snippets: the exact `findCalendarPeriods` call of
712
the current analysis — real hints and options included — as a runnable

website/src/components/ResultsView.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { useMemo } from 'react'
22
import type { CalendarHintsResult, HintResult, Period } from '../../../src/calendar-hints'
3-
import { buildDayTypes, dayTypeBackground, frLabel, type DayTypeStyle } from '../day-types'
3+
import { buildDayTypes, dayTypeBackground, frLabel, periodLabel, type DayTypeStyle } from '../day-types'
44
import { eachDay, type GeneratedHints } from '../hints'
55
import CalendarGrid from './CalendarGrid'
66

@@ -50,7 +50,7 @@ function PeriodCard({ period, style }: { period: Period; style: DayTypeStyle })
5050
<div className="period-card" style={{ borderLeftColor: style.color }}>
5151
<div className="period-labels">
5252
<span className="day-type-swatch" style={{ background: dayTypeBackground(style) }} />
53-
{period.labels.map(frLabel).join(' + ')}
53+
{periodLabel(period.labels)}
5454
</div>
5555
<div className="muted">
5656
{period.days.length} jours ({period.days[0]}{period.days[period.days.length - 1]}) —{' '}

website/src/day-types.ts

Lines changed: 56 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,61 @@ export function frLabel(label: string): string {
2323
return LABEL_FR.reduce((s, [en, fr]) => s.replaceAll(en, fr), label)
2424
}
2525

26+
// Libellé d'une période : les labels « Hint — Mondays + Hint — Tuesdays + … »
27+
// issus de la politique per-day-of-week sont regroupés par hint, et les jours
28+
// consécutifs condensés en « du lundi au samedi ». Semaine à la française,
29+
// lundi en tête.
30+
const WEEKDAYS_EN = ['Mondays', 'Tuesdays', 'Wednesdays', 'Thursdays', 'Fridays', 'Saturdays', 'Sundays']
31+
const WEEKDAYS_FR = ['lundi', 'mardi', 'mercredi', 'jeudi', 'vendredi', 'samedi', 'dimanche']
32+
33+
function frWeekdays(indices: number[]): string {
34+
const sorted = [...new Set(indices)].sort((a, b) => a - b)
35+
const runs: number[][] = []
36+
for (const i of sorted) {
37+
const run = runs[runs.length - 1]
38+
if (run && i === run[run.length - 1] + 1) run.push(i)
39+
else runs.push([i])
40+
}
41+
return runs
42+
.map(run => {
43+
if (run.length === 7) return 'tous les jours'
44+
if (run.length >= 3) return `du ${WEEKDAYS_FR[run[0]]} au ${WEEKDAYS_FR[run[run.length - 1]]}`
45+
return run.map(i => `${WEEKDAYS_FR[i]}s`).join(' + ')
46+
})
47+
.join(' + ')
48+
}
49+
50+
export function periodLabel(labels: string[]): string {
51+
// Groupes dans l'ordre de première apparition ; ceux issus d'un même hint
52+
// per-day-of-week (même préfixe avant « — jour ») fusionnent leurs jours.
53+
const groups: { prefix: string | null; weekdays: number[] }[] = []
54+
const byPrefix = new Map<string, { prefix: string | null; weekdays: number[] }>()
55+
for (const label of labels) {
56+
const sep = label.lastIndexOf(' — ')
57+
const weekday = sep >= 0 ? WEEKDAYS_EN.indexOf(label.slice(sep + 3)) : -1
58+
if (weekday < 0) {
59+
groups.push({ prefix: frLabel(label), weekdays: [] })
60+
continue
61+
}
62+
// « Remaining days — lundis » s'affiche sans préfixe, comme frLabel
63+
const prefix = label.slice(0, sep) === 'Remaining days' ? null : frLabel(label.slice(0, sep))
64+
let group = byPrefix.get(prefix ?? '')
65+
if (!group) {
66+
group = { prefix, weekdays: [] }
67+
byPrefix.set(prefix ?? '', group)
68+
groups.push(group)
69+
}
70+
group.weekdays.push(weekday)
71+
}
72+
return groups
73+
.map(g => {
74+
if (g.weekdays.length === 0) return g.prefix
75+
const days = frWeekdays(g.weekdays)
76+
return g.prefix === null ? days : `${g.prefix} : ${days}`
77+
})
78+
.join(' + ')
79+
}
80+
2681
// Palette stable ; quand elle boucle, le motif change — 12 × 4 = 48 styles
2782
// distincts avant répétition, largement au-delà du nombre de signatures d'un
2883
// feed réel.
@@ -110,7 +165,7 @@ export function buildDayTypes(result: CalendarHintsResult, orderedPeriods: Perio
110165
return {
111166
signature,
112167
style: styleOf(i),
113-
label: period ? period.labels.map(frLabel).join(' + ') : 'non classé',
168+
label: period ? periodLabel(period.labels) : 'non classé',
114169
dayCount: dayCounts.get(signature) ?? 0,
115170
unclassifiedCount: group?.days.length ?? 0,
116171
tripCount: period?.tripCount ?? group?.tripCount ?? 0,

0 commit comments

Comments
 (0)