- {{ day.getDate() }} -
+ {{ day.getDate() }} + @if (status) { + {{ + getStatusMarker(day) + }} + } + } } diff --git a/src/app/components/calendar-month/calendar-month.scss b/src/app/components/calendar-month/calendar-month.scss index e163de5..7848abe 100644 --- a/src/app/components/calendar-month/calendar-month.scss +++ b/src/app/components/calendar-month/calendar-month.scss @@ -22,6 +22,7 @@ } .day { + position: relative; text-align: center; display: flex; align-items: center; @@ -32,7 +33,10 @@ margin-top: 2px; margin-bottom: 2px; border-radius: 30%; + border: 1px solid transparent; color: var(--number-color); + font: inherit; + padding: 0; &.empty { visibility: hidden; @@ -41,7 +45,17 @@ &.number:hover { background-color: var(--number-bg-hover); color: var(--number-color-hover); - cursor: default; + cursor: pointer; + } + + &.number:focus-visible { + outline: 3px solid var(--today-border-color, #1976d2); + outline-offset: 2px; + } + + &.context-only { + opacity: 0.38; + cursor: not-allowed; } &.past { @@ -49,8 +63,66 @@ } } + .status-marker { + position: absolute; + inset-block-start: -0.35rem; + inset-inline-end: -0.2rem; + min-width: 0.85rem; + font-size: 0.65rem; + font-weight: 800; + line-height: 1; + background: var(--ui-card-bg, #fff); + border-radius: 999px; + } + + .current { + outline: 3px double var(--today-border-color, #1976d2); + outline-offset: 1px; + } + + .eligible, + .chosen { + border-block-end: 3px solid var(--ui-success-text, #174d26); + } + + .ineligible, + .evaluated-rejected { + text-decoration: line-through; + text-decoration-thickness: 2px; + } + + .pruned { + border: 2px dotted currentColor; + } + + .not-examined { + border: 2px dashed currentColor; + } + + .change-added, + .change-moved-to { + box-shadow: inset 0 -3px var(--ui-success-text, #174d26); + } + + .change-moved-from, + .change-removed { + box-shadow: inset 0 3px var(--ui-error-text, #8b1a1a); + } + + .change-shared { + box-shadow: inset 3px 0 var(--today-border-color, #1976d2); + } + + .change-unchanged { + box-shadow: inset 0 0 0 1px currentColor; + } + .selected { - cursor: help !important; + cursor: pointer; + } + + .context-only.selected { + cursor: not-allowed; } .selected:not(.start):not(.end) { diff --git a/src/app/components/calendar-month/calendar-month.ts b/src/app/components/calendar-month/calendar-month.ts index d668d30..e247219 100644 --- a/src/app/components/calendar-month/calendar-month.ts +++ b/src/app/components/calendar-month/calendar-month.ts @@ -1,10 +1,19 @@ -import { Component, Input, OnInit, inject } from '@angular/core'; +import { Component, EventEmitter, Input, OnInit, Output, inject } from '@angular/core'; import { CalendarService, Month, SelectedDates } from '../../services/calendar-service'; import { MatTooltip } from '@angular/material/tooltip'; import { CalendarSettingsService } from '../../services/calendar-settings-service'; import { DateCacheService } from '../../services/date-cache.service'; import { TranslationService } from '../../services/translation-service'; +export interface CalendarDayStatus { + kind: 'eligible' | 'ineligible' | 'chosen' | 'evaluated-rejected' | 'pruned' | 'not-examined'; + label: string; + reason?: string; + historicalLabel?: string; + change?: 'added' | 'moved-from' | 'moved-to' | 'removed' | 'shared' | 'unchanged'; + changeLabel?: string; +} + @Component({ selector: 'app-calendar-month', imports: [MatTooltip], @@ -38,6 +47,89 @@ export class CalendarMonth implements OnInit { @Input({ required: true }) selectedDates!: SelectedDates; + @Input() + horizonStart?: string; + + @Input() + horizonEnd?: string; + + @Input() + currentDate: string | null = null; + + @Input() + dateStatuses: Readonly{{ liveMessage() }}
+ @if (isLoading()) {