batchCooking/apps/web/src/features/planning/week-navigator.scss
kyuno053 109dde9c7b
feat(shopping-list): liste de courses agrégée depuis le planning (#73)
GET /shopping-list?date= (shopping-list.service.ts/.routes.ts) somme les
ingrédients de chaque recette planifiée sur la semaine, mis à l'échelle par
les portions de chaque créneau (PlanningItem.portions / Recipe.portions),
regroupés par paire (ingredientId, unitId) — jamais null contrairement à
GET /planning, une semaine vide redescend en items: [].

Côté web, ShoppingListPage rend cette liste groupée par rayon (même
IngredientCategory que IngredientPicker), triée alphabétiquement en
français à l'intérieur d'un rayon (shopping-list.ts, logique pure extraite
du composant). WeekNavigator (flèches + calendrier) est extrait de
PlanningPage vers features/planning/ pour être partagé entre les deux
pages ; ses libellés migrent de planning.* vers common.weekNav.*/
common.calendar.*/common.days.*, plus génériques pour une page qui n'est
plus seulement le planning.

ComingSoonPage retiré (plus aucun appelant, Liste de courses avait le
dernier stub restant).

Tests : Mocha (agrégation, mise à l'échelle par portions, unités non
fusionnées) + Cucumber (shopping-list.feature : liste vide, groupement/tri,
navigation de semaine) + mise à jour de layout.cy.ts/planning-page.cy.ts
pour le nouveau rendu.

Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-22 22:45:06 +02:00

143 lines
3.4 KiB
SCSS

// =============================================================================
// Styles for WeekNavigator.tsx (arrows + label + calendar popover) —
// colocated next to the component since nothing else uses these classes.
// Extracted from planning-page.scss once ShoppingListPage started reusing
// the component — same design tokens, no light/dark duplication needed
// (every `var(--color-*)` below already resolves per-theme globally, see
// styles/_theme.scss).
// =============================================================================
.week-nav {
position: relative;
display: flex;
align-items: center;
gap: var(--space-xs);
&__arrow {
width: 2rem;
height: 2rem;
display: grid;
place-items: center;
border: 1px solid var(--color-border);
border-radius: var(--radius-base);
background: var(--color-surface);
color: var(--color-text);
font-size: var(--font-size-md);
cursor: pointer;
&:hover {
background: var(--color-surface-alt);
}
}
&__label {
display: flex;
align-items: center;
gap: var(--space-xs);
padding: 0.45rem var(--space-md);
border: 1px solid var(--color-border);
border-radius: var(--radius-base);
background: var(--color-surface);
color: var(--color-text);
font-weight: 600;
font-size: var(--font-size-sm);
cursor: pointer;
&:hover {
background: var(--color-surface-alt);
}
}
}
.today-badge {
font-size: var(--font-size-xs);
font-weight: 600;
color: var(--color-primary);
background: color-mix(in srgb, var(--color-primary) 14%, transparent);
padding: 0.1rem 0.4rem;
border-radius: var(--radius-pill);
}
// --- Calendar popover -------------------------------------------------------
.calendar-popover {
position: absolute;
top: calc(100% + var(--space-xs));
right: 0;
z-index: 10;
width: 18rem;
padding: var(--space-md);
background: var(--color-surface);
border: 1px solid var(--color-border);
border-radius: var(--radius-md);
box-shadow: var(--shadow-md);
&__header {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: var(--space-sm);
font-weight: 700;
font-size: var(--font-size-sm);
text-transform: capitalize;
button {
width: 1.6rem;
height: 1.6rem;
border: none;
background: none;
cursor: pointer;
font-size: var(--font-size-base);
color: var(--color-text-muted);
border-radius: var(--radius-base);
&:hover {
background: var(--color-surface-alt);
}
}
}
}
.calendar-grid {
display: grid;
grid-template-columns: repeat(7, 1fr);
gap: 2px;
&__weekday {
text-align: center;
font-size: var(--font-size-xs);
color: var(--color-text-muted);
font-weight: 600;
padding-bottom: var(--space-xs);
}
&__day {
aspect-ratio: 1;
display: grid;
place-items: center;
font-size: var(--font-size-sm);
border-radius: var(--radius-base);
cursor: pointer;
color: var(--color-text);
border: none;
background: none;
font: inherit;
&:hover {
background: var(--color-surface-alt);
}
&--muted {
color: var(--color-border);
}
&--in-selected-week {
background: color-mix(in srgb, var(--color-primary) 14%, transparent);
border-radius: 0;
}
&--today {
box-shadow: inset 0 0 0 2px var(--color-primary);
font-weight: 700;
}
}
}