feat(meals): вкладка «Питание» — напоминания о еде по времени суток
Новая модель Meal — напоминание по настенным часам (time HH:MM + дни недели), в отличие от interval-based Exercise. Отдельная вкладка «Питание» с пресетами быстрого добавления (Завтрак/Обед/Ужин/Перекус). - shared: тип Meal, meals в AppState, nextMealOccurrence (DST-safe), SAMPLE_MEALS, MEAL_PRESETS; IPC-каналы meal:* + evtFireMeal - main: валидация (строгая HH:MM-проверка диапазона), store-мутаторы с пересчётом nextFireAt, scheduler.checkDueMeals (гейт только globalEnabled, grace-окно 120с, игнор тихих часов/ВКС), notifications.fireMealReminder, IPC-хендлеры - renderer: вкладка Meals + MealEditor (время/дни/иконка), MealReminder в окне напоминания (Поел/Отложить, TTS), пункт в Sidebar, маршрут, i18n RU/EN, иконки UtensilsCrossed/Soup - persistence: meals additive (без bump схемы — старые state'ы получают []) - +24 теста (203 -> 227): nextMealOccurrence, валидаторы приёмов пищи, scheduler meal-gating (вкл/выкл, grace, игнор тихих часов) Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
39
CLAUDE.md
39
CLAUDE.md
@@ -12,7 +12,7 @@
|
||||
- **Build**: electron-vite 2 + Vite 5 + electron-builder 25 (NSIS, x64 only)
|
||||
- **UI**: React 18 + TypeScript 5 + Tailwind 3 + framer-motion + react-router (HashRouter) + zustand 5
|
||||
- **Auto-update**: electron-updater 6, generic provider, фиксированный канал
|
||||
- **Тесты**: Vitest 4 (203 теста, все зелёные)
|
||||
- **Тесты**: Vitest 4 (227 тестов, все зелёные)
|
||||
- **Lint/format**: ESLint 8 (flat-ish .eslintrc.cjs) + Prettier 3 + EditorConfig
|
||||
- **Иконки**: lucide-react (whitelisted lookup через `ICON_CHOICES`)
|
||||
- **Шрифты**: Plus Jakarta Sans, Bricolage Grotesque, JetBrains Mono (Google Fonts CDN)
|
||||
@@ -68,6 +68,20 @@
|
||||
- Wrap-around (22:00 → 07:00) корректно — при wrap-active проверяется день *начала* окна
|
||||
- Тесты в `src/shared/quiet-hours.test.ts`
|
||||
|
||||
### Питание / приёмы пищи (вкладка «Питание»)
|
||||
- **Отдельная модель `Meal`** (`src/shared/types.ts`): напоминание ПО ВРЕМЕНИ СУТОК
|
||||
(`time` HH:MM + `days` weekdays), в отличие от interval-based `Exercise`
|
||||
- `nextMealOccurrence(time, days, fromMs)` — следующее срабатывание, календарная
|
||||
арифметика (DST-safe, как history.ts). Тесты в `src/shared/meals.test.ts`
|
||||
- Scheduler `checkDueMeals()` (`src/main/scheduler.ts`): гейтит **только**
|
||||
`globalEnabled` (НЕ тихие часы / НЕ ВКС — время задано пользователем явно).
|
||||
Grace-окно `MEAL_GRACE_MS=120s`: приём, пропущенный давно (сон/выкл), тихо
|
||||
переносится без срабатывания, чтобы не вывалить пачку напоминаний разом
|
||||
- Окно напоминания: `evtFireMeal` → `MealReminder` в `ReminderApp.tsx` (зелёный
|
||||
акцент `bg-success`, кнопки «Поел» / «Отложить»)
|
||||
- Пресеты быстрого добавления — `MEAL_PRESETS` (имена через i18n-ключи)
|
||||
- Время валидируется строго (`validHHMM` в validate.ts — диапазон, не только форма)
|
||||
|
||||
### История / стрики
|
||||
- `src/renderer/src/lib/history.ts` — DST-safe через `shiftDays()` (calendar `setDate`, не ms-арифметика)
|
||||
- Cap 10k записей, trim oldest 10% на overflow
|
||||
@@ -119,38 +133,41 @@ npm run release -- -Bump patch
|
||||
| `package.json` | version, publish.url, scripts, deps |
|
||||
| `src/main/store.ts` | persistence, migrations, validation, atomic writes |
|
||||
| `src/main/ipc.ts` | IPC handlers с валидацией |
|
||||
| `src/main/scheduler.ts` | таймеры упражнений, powerMonitor |
|
||||
| `src/main/scheduler.ts` | таймеры упражнений (interval) + приёмы пищи (clock-time), powerMonitor |
|
||||
| `src/main/games/dota2.ts` + `gsi-server.ts` | GSI приём матчей |
|
||||
| `src/main/updater.ts` | auto-update logic, silent retries |
|
||||
| `src/shared/types.ts` | shared типы, дефолты, isQuietAt |
|
||||
| `src/shared/ipc.ts` | IPC channel types |
|
||||
| `src/renderer/src/i18n/dict.ts` | словари |
|
||||
| `src/renderer/src/pages/Dashboard.tsx` | главная |
|
||||
| `src/renderer/src/ReminderApp.tsx` | окно напоминания |
|
||||
| `src/renderer/src/pages/Meals.tsx` + `components/MealEditor.tsx` | вкладка «Питание» |
|
||||
| `src/renderer/src/ReminderApp.tsx` | окно напоминания (упражнение / еда / матч) |
|
||||
|
||||
## Тесты (203)
|
||||
## Тесты (227)
|
||||
|
||||
```
|
||||
src/main/validate.test.ts (68)
|
||||
src/main/validate.test.ts (78)
|
||||
src/renderer/src/lib/history.test.ts (31)
|
||||
src/renderer/src/i18n/i18n.test.ts (15)
|
||||
src/renderer/src/lib/format.test.ts (14)
|
||||
src/main/scheduler.test.ts (13) ← main: gating + приёмы пищи
|
||||
src/main/games/vdf.test.ts (11)
|
||||
src/main/store.test.ts (10) ← main: миграции/карантин/cap
|
||||
src/renderer/src/lib/achievements.test.ts (10)
|
||||
src/shared/release-notes.test.ts (9)
|
||||
src/main/scheduler.test.ts (8) ← main: gating-логика
|
||||
src/shared/meals.test.ts (8) ← nextMealOccurrence (DST-safe)
|
||||
src/main/meeting-detect.test.ts (7) ← main: детект ВКС + кэш/timeout
|
||||
src/shared/quiet-hours.test.ts (7)
|
||||
src/main/adaptive.test.ts (6)
|
||||
src/shared/types.test.ts (4)
|
||||
src/renderer/src/lib/icon-choices.test.ts (3)
|
||||
src/renderer/src/lib/icon-choices.test.ts (4)
|
||||
```
|
||||
|
||||
Покрываются: IPC-валидация, persistence (миграции/карантин/cap), scheduler-gating
|
||||
(тихие часы/ВКС/daily-goal), детект ВКС (мок child_process), helpers, история/стрики
|
||||
(DST), тихие часы (wrap+filter), VDF-парсер Steam, достижения, i18n с плюрализацией,
|
||||
дефолты.
|
||||
Покрываются: IPC-валидация (упражнения/челленджи/приёмы пищи), persistence
|
||||
(миграции/карантин/cap), scheduler-gating (тихие часы/ВКС/daily-goal), планирование
|
||||
приёмов пищи по времени суток (DST-safe, grace-окно, игнор тихих часов), детект ВКС
|
||||
(мок child_process), helpers, история/стрики (DST), тихие часы (wrap+filter),
|
||||
VDF-парсер Steam, достижения, i18n с плюрализацией, дефолты.
|
||||
|
||||
Паттерн для main-тестов: `vi.mock('electron'|'./store'|'node:child_process')` +
|
||||
`vi.resetModules()` + dynamic import (сброс module-level состояния между тестами).
|
||||
|
||||
Reference in New Issue
Block a user