Compare commits
2 Commits
feat/meals
...
fix/meals-
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ad000c722e | ||
|
|
c0827f887f |
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "laude",
|
||||
"version": "0.5.8",
|
||||
"version": "0.6.0",
|
||||
"description": "Exercise reminder — Windows desktop app",
|
||||
"main": "out/main/index.js",
|
||||
"author": "AnRil",
|
||||
|
||||
@@ -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',
|
||||
|
||||
@@ -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<Meal | null>(null)
|
||||
const { t } = useT()
|
||||
|
||||
const enabled = meals.filter((m) => m.enabled)
|
||||
const disabled = meals.filter((m) => !m.enabled)
|
||||
// Единый список (включённые сверху). Важно: НЕ разбиваем на два <Card>, иначе
|
||||
// при переключении строка переезжает между списками → её 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 {
|
||||
))}
|
||||
</div>
|
||||
|
||||
{enabled.length > 0 && (
|
||||
{meals.length > 0 && (
|
||||
<>
|
||||
<SectionHeader
|
||||
title={t('meals.section.active', { n: enabled.length })}
|
||||
/>
|
||||
<Card className="mb-6">
|
||||
{enabled.map((m, i) => (
|
||||
<MealRow
|
||||
key={m.id}
|
||||
meal={m}
|
||||
last={i === enabled.length - 1}
|
||||
meta={`${m.time} · ${daysLabel(m.days, t)}`}
|
||||
onEdit={() => {
|
||||
setEditing(m)
|
||||
setEditorOpen(true)
|
||||
}}
|
||||
/>
|
||||
))}
|
||||
</Card>
|
||||
</>
|
||||
)}
|
||||
|
||||
{disabled.length > 0 && (
|
||||
<>
|
||||
<SectionHeader
|
||||
title={t('meals.section.disabled', { n: disabled.length })}
|
||||
/>
|
||||
<SectionHeader title={t('meals.schedule')} />
|
||||
<Card>
|
||||
{disabled.map((m, i) => (
|
||||
<MealRow
|
||||
<AnimatePresence initial={false}>
|
||||
{ordered.map((m, i) => (
|
||||
<motion.div
|
||||
key={m.id}
|
||||
layout
|
||||
initial={{ opacity: 0 }}
|
||||
animate={{ opacity: 1 }}
|
||||
exit={{ opacity: 0 }}
|
||||
transition={{ duration: 0.18, ease: 'easeOut' }}
|
||||
>
|
||||
<MealRow
|
||||
meal={m}
|
||||
last={i === disabled.length - 1}
|
||||
last={i === ordered.length - 1}
|
||||
meta={`${m.time} · ${daysLabel(m.days, t)}`}
|
||||
onEdit={() => {
|
||||
setEditing(m)
|
||||
setEditorOpen(true)
|
||||
}}
|
||||
/>
|
||||
</motion.div>
|
||||
))}
|
||||
</AnimatePresence>
|
||||
</Card>
|
||||
</>
|
||||
)}
|
||||
@@ -169,7 +163,7 @@ function MealRow({
|
||||
<Row last={last}>
|
||||
<div
|
||||
className={[
|
||||
'w-9 h-9 rounded-lg grid place-items-center shrink-0',
|
||||
'w-9 h-9 rounded-lg grid place-items-center shrink-0 transition-colors duration-200',
|
||||
meal.enabled ? 'bg-accent text-white' : 'bg-text/15 text-text/45'
|
||||
].join(' ')}
|
||||
>
|
||||
|
||||
Reference in New Issue
Block a user