From ad000c722ece981cb3dea203c27eacce54c41391 Mon Sep 17 00:00:00 2001 From: AnRil Date: Sat, 6 Jun 2026 00:13:07 +0700 Subject: [PATCH] =?UTF-8?q?fix(meals):=20=D0=BF=D0=BB=D0=B0=D0=B2=D0=BD?= =?UTF-8?q?=D0=B0=D1=8F=20=D0=B0=D0=BD=D0=B8=D0=BC=D0=B0=D1=86=D0=B8=D1=8F?= =?UTF-8?q?=20=D0=BF=D0=B5=D1=80=D0=B5=D0=BA=D0=BB=D1=8E=D1=87=D0=B0=D1=82?= =?UTF-8?q?=D0=B5=D0=BB=D1=8F=20=D0=B2=20=D0=BE=D0=B1=D0=B5=20=D1=81=D1=82?= =?UTF-8?q?=D0=BE=D1=80=D0=BE=D0=BD=D1=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Список «Питания» разбивался на два (активные/выключенные). При переключении строка переезжала между списками → её Switch размонтировался и монтировался заново, и ползунок анимировался только при включении (mount x:0→20), а при выключении — нет. Теперь единый keyed-список (включённые сверху): Switch остаётся смонтированным, ползунок плавно ездит в обе стороны, а строка «переезжает» в свою группу через framer layout-анимацию. Иконке добавлен transition-colors. Глобальный Switch не трогал — Упражнения/Дашборд не затронуты. Co-Authored-By: Claude Opus 4.8 --- src/renderer/src/i18n/dict.ts | 2 + src/renderer/src/pages/Meals.tsx | 76 +++++++++++++++----------------- 2 files changed, 37 insertions(+), 41 deletions(-) diff --git a/src/renderer/src/i18n/dict.ts b/src/renderer/src/i18n/dict.ts index b36973b..090a059 100644 --- a/src/renderer/src/i18n/dict.ts +++ b/src/renderer/src/i18n/dict.ts @@ -100,6 +100,7 @@ export const ru: Dict = { 'meals.kicker': 'Режим питания', 'meals.title': 'Питание', 'meals.presets': 'Быстрое добавление', + 'meals.schedule': 'Расписание', 'meals.section.active': 'Активные · {n}', 'meals.section.disabled': 'Выключенные · {n}', 'meals.empty': 'Пока нет приёмов пищи — добавь первый или выбери пресет', @@ -460,6 +461,7 @@ export const en: Dict = { 'meals.kicker': 'Eating schedule', 'meals.title': 'Meals', 'meals.presets': 'Quick add', + 'meals.schedule': 'Schedule', 'meals.section.active': 'Active · {n}', 'meals.section.disabled': 'Disabled · {n}', 'meals.empty': 'No meals yet — add one or pick a preset', diff --git a/src/renderer/src/pages/Meals.tsx b/src/renderer/src/pages/Meals.tsx index 72c635d..68eb937 100644 --- a/src/renderer/src/pages/Meals.tsx +++ b/src/renderer/src/pages/Meals.tsx @@ -1,5 +1,6 @@ import { useState } from 'react' import { Plus, ChevronRight, UtensilsCrossed } from 'lucide-react' +import { AnimatePresence, motion } from 'framer-motion' import { useAppStore } from '../store/appStore' import { MealEditor, type MealDraft } from '../components/MealEditor' import { Button } from '../components/ui/Button' @@ -27,8 +28,15 @@ export default function Meals(): JSX.Element { const [editing, setEditing] = useState(null) const { t } = useT() - const enabled = meals.filter((m) => m.enabled) - const disabled = meals.filter((m) => !m.enabled) + // Единый список (включённые сверху). Важно: НЕ разбиваем на два , иначе + // при переключении строка переезжает между списками → её Switch + // размонтируется/монтируется заново, и анимация ползунка есть только при + // включении (mount с x:0→20), а при выключении нет. В одном keyed-списке + // компонент остаётся смонтированным → ползунок плавно ездит в обе стороны, + // а строка «переезжает» в свою группу через layout-анимацию. + const ordered = [...meals].sort((a, b) => + a.enabled === b.enabled ? 0 : a.enabled ? -1 : 1 + ) async function addPreset( preset: (typeof MEAL_PRESETS)[number] @@ -82,46 +90,32 @@ export default function Meals(): JSX.Element { ))} - {enabled.length > 0 && ( + {meals.length > 0 && ( <> - - - {enabled.map((m, i) => ( - { - setEditing(m) - setEditorOpen(true) - }} - /> - ))} - - - )} - - {disabled.length > 0 && ( - <> - + - {disabled.map((m, i) => ( - { - setEditing(m) - setEditorOpen(true) - }} - /> - ))} + + {ordered.map((m, i) => ( + + { + setEditing(m) + setEditorOpen(true) + }} + /> + + ))} + )} @@ -169,7 +163,7 @@ function MealRow({