feat(web): Kalender-Widget zeigt je Kalender einen kleinen Kreis am Tag; Changelog
- Plaketten-Wrapper calendar-day-badges rendert buildDayBadges(day.events) statt der alten Einzel-Plakette - Ein Kalender: unveraendert eine Plakette in Kalenderfarbe/Akzentfarbe (Tests 3/3b/3c bleiben gruen) - Zwei/drei Kalender: je ein kleiner Kreis pro Kalender in Startreihenfolge (Test 3d) - Vier oder mehr Kalender: zwei Kreise plus grauer Restkreis bg-muted-foreground/text-background mit Summe (Test 3e) - CHANGELOG-Stichpunkt erweitert (mehrere Kalender am selben Tag) Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -8,6 +8,7 @@ import { fetchEvents, fetchSources } from '@/lib/calendar-api';
|
||||
import type { CalendarEvent } from '@/lib/calendar-api';
|
||||
import {
|
||||
buildCalendarDays,
|
||||
buildDayBadges,
|
||||
computeFetchWindow,
|
||||
formatEventDate,
|
||||
formatEventTime,
|
||||
@@ -30,9 +31,11 @@ const TOOLTIP_EDGE_PX = 4;
|
||||
*
|
||||
* Oben ein Monatsraster (Nav-Zeile Zurueck/Monat/Weiter, Wochentagskopf,
|
||||
* 42 Zellen ab Montag, Faehrmonatstage gedaempft, heutiger Tag hervorgehoben,
|
||||
* Zaehl-Plakette an Tagen mit Terminen in der Farbe des Kalenders des
|
||||
* fruehesten Termins des Tages (sonst Akzentfarbe), Tooltip beim Ueberfahren
|
||||
* mit Farbpunkt je Zeile (quick-260916-jvj)), darunter
|
||||
* Zaehl-Plakette an Tagen mit Terminen in der Farbe des Kalenders (ein
|
||||
* Kalender am Tag); bei mehreren Kalendern am selben Tag je ein kleiner
|
||||
* Kreis pro Kalender (max. drei, danach zwei plus grauer Restkreis mit
|
||||
* Summe, Logik in `buildDayBadges`, quick-260916-k2z), Tooltip beim
|
||||
* Ueberfahren mit Farbpunkt je Zeile (quick-260916-jvj)), darunter
|
||||
* der Block "Naechste Termine". Beide Bloecke lassen sich unabhaengig
|
||||
* ein-/ausblenden (Config `showMonth`/`maxEvents`, siehe calendar-month.ts).
|
||||
*
|
||||
@@ -219,6 +222,8 @@ export function CalendarWidget({ config }: WidgetProps) {
|
||||
<div className="grid grid-cols-7 gap-px">
|
||||
{days.map((day) => {
|
||||
const hasEvents = day.events.length > 0;
|
||||
const badges = buildDayBadges(day.events);
|
||||
const single = badges.length === 1;
|
||||
const cellClass = [
|
||||
'widgetNoDrag relative flex min-h-[clamp(16px,5.5cqh,40px)] items-start rounded bg-muted/50 px-1 py-0.5 text-[clamp(9px,2.4cqw,13px)] leading-none',
|
||||
day.inCurrentMonth ? 'text-foreground' : 'text-muted-foreground/60',
|
||||
@@ -243,25 +248,40 @@ export function CalendarWidget({ config }: WidgetProps) {
|
||||
onMouseLeave={() => setHover(null)}
|
||||
>
|
||||
<span>{day.date.getDate()}</span>
|
||||
{hasEvents &&
|
||||
(() => {
|
||||
const badgeColor = day.events[0]?.color;
|
||||
const badgeClass = [
|
||||
'absolute bottom-px right-px flex h-[clamp(10px,3cqw,16px)] min-w-[clamp(10px,3cqw,16px)] items-center justify-center rounded-full px-0.5 text-[clamp(7px,1.8cqw,10px)] font-semibold leading-none',
|
||||
badgeColor ? 'text-white' : 'bg-primary text-primary-foreground',
|
||||
]
|
||||
.filter(Boolean)
|
||||
.join(' ');
|
||||
return (
|
||||
<span
|
||||
data-testid="calendar-day-count"
|
||||
className={badgeClass}
|
||||
style={badgeColor ? { backgroundColor: badgeColor } : undefined}
|
||||
>
|
||||
{day.events.length}
|
||||
</span>
|
||||
);
|
||||
})()}
|
||||
{hasEvents && (
|
||||
// Wrapper traegt die Positionierung, die einzelnen Kreise nicht
|
||||
// mehr (mehrere Kreise stehen sonst uebereinander).
|
||||
<span
|
||||
data-testid="calendar-day-badges"
|
||||
className="absolute bottom-px right-px flex items-end gap-px"
|
||||
>
|
||||
{badges.map((badge) => {
|
||||
const badgeClass = [
|
||||
'flex items-center justify-center rounded-full px-0.5 font-semibold leading-none',
|
||||
single
|
||||
? 'h-[clamp(10px,3cqw,16px)] min-w-[clamp(10px,3cqw,16px)] text-[clamp(7px,1.8cqw,10px)]'
|
||||
: 'h-[clamp(8px,2.4cqw,12px)] min-w-[clamp(8px,2.4cqw,12px)] text-[clamp(6px,1.5cqw,8px)]',
|
||||
badge.rest
|
||||
? 'bg-muted-foreground text-background'
|
||||
: badge.color
|
||||
? 'text-white'
|
||||
: 'bg-primary text-primary-foreground',
|
||||
]
|
||||
.filter(Boolean)
|
||||
.join(' ');
|
||||
return (
|
||||
<span
|
||||
key={badge.key}
|
||||
data-testid={badge.rest ? 'calendar-day-count-rest' : 'calendar-day-count'}
|
||||
className={badgeClass}
|
||||
style={badge.color && !badge.rest ? { backgroundColor: badge.color } : undefined}
|
||||
>
|
||||
{badge.count}
|
||||
</span>
|
||||
);
|
||||
})}
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
|
||||
Reference in New Issue
Block a user