Source: frontend/src/pages/Food.jsx

/**
 * Головна бізнес-логіка сторінки щоденника харчування.
 *
 * Цей модуль поєднує кілька сценаріїв роботи
 * - завантаження записів харчування за обрану дату
 * - пошук продуктів через USDA API
 * - додавання записів до щоденника
 * - роботу з власними продуктами користувача
 * - обчислення прогресу за денними нормами
 *
 * Сторінка виступає точкою взаємодії між інтерфейсом користувача,
 * локальним станом форми та backend API, тому разом містить
 * відображення та прикладну логіку роботи з харчуванням.
 */

import { useState, useEffect} from 'react'
import { api } from '../api/api'
import { today } from '../utils/dateUtils'
import { calcMacroGoals, pct } from '../utils/nutritionUtils'
import DateNavigator from '../components/DateNavigator'
import FoodTable from '../components/FoodTable'
import FoodModal from '../components/FoodModal'

/**
 * Варіанти прийомів їжі, доступні в щоденнику харчування.
 */
const MEALS = [
  { id: 'breakfast', label: 'Сніданок' },
  { id: 'lunch', label: 'Обід' },
  { id: 'dinner', label: 'Вечеря' },
  { id: 'snack', label: 'Перекус' }
]

/**
 * Сторінка щоденника харчування.
 *
 * Завантажує записи харчування і профіль користувача за вибрану дату,
 * дозволяє шукати продукти через USDA, додавати власні продукти,
 * створювати записи харчування та видаляти їх.
 * @returns {object} SX-елемент сторінки харчування.
 */
export default function Food() {
  const [date, setDate] = useState(today())
  const [logs, setLogs] = useState([])
  const [profile, setProfile] = useState({})
  const [showModal, setShowModal] = useState(false)
  const [currentMeal, setCurrentMeal] = useState('breakfast')

  /**
   * Завантажує записи харчування і профіль користувача за вказану дату.
   * @param {string} d Дата у форматі YYYY-MM-DD.
   * @returns {Promise<void>}
   */
  const load = async (d) => {
    try {
      const [l, p] = await Promise.all([api.getFoodLogs(d), api.getProfile()])

      setLogs(l)
      setProfile(p)
    } catch(err) {
      console.error(err)
    }
  }

  useEffect(() => {
    // eslint-disable-next-line react-hooks/set-state-in-effect
    load(date)
  }, [date])

  /**
   * Видаляє запис харчування за ідентифікатором і перезавантажує дані сторінки.
   * @param {number|string} id Ідентифікатор запису харчування.
   * @returns {Promise<void>}
   */
  const deleteLog = async (id) => {
    await api.deleteFoodLog(id)
    load(date)
  }

  /**
   * Закриває модальне вікно і скидає тимчасовий стан вибору продукту та форми.
   * @returns {void}
   */
  const closeModal = () => {
    setShowModal(false)
  }

  const goals = calcMacroGoals(profile.calorie_goal)

  const total = logs.reduce((a, i) => ({
    kcal: a.kcal + (+i.kcal || 0),
    protein: a.protein + (+i.protein_g || 0),
    fat: a.fat + (+i.fat_g || 0),
    carbs: a.carbs + (+i.carbs_g || 0)
  }), {kcal: 0, protein: 0, fat: 0, carbs: 0})

  return (
    <div>
      <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', marginBottom: 16 }}>
        <div style={{ fontSize: 18, fontWeight: 500 }}>Харчування</div>
        <DateNavigator date={date} onChange={setDate} />
      </div>

      <div className="stats-row" style={{ marginBottom: 12 }}>
        {[
          ['Калорії', Math.round(total.kcal), goals.kcal, 'ккал', 'var(--accent)'],
          ['Білки', Math.round(total.protein), goals.protein, 'г', 'var(--green)'],
          ['Жири', Math.round(total.fat), goals.fat, 'г', 'var(--amber)'],
          ['Вуглеводи', Math.round(total.carbs), goals.carbs, 'г', 'var(--purple)']
        ].map(([label, val, goal, unit, color]) => (
          <div key={label} className="stat-cell">
            <div className="stat-label">{label}</div>
            <div className="stat-value" style={{ color }}>
              {val}
              <span className="stat-unit"> {unit}</span>
            </div>
            <div className="stat-bar">
              <div className="stat-bar-fill" style={{ width: pct(val, goal) + '%', background: color }} />
            </div>
            <div className="stat-note">з {goal}{unit}</div>
          </div>
        ))}
      </div>

      <div style={{ display: 'grid', gridTemplateColumns: '1fr 320px', gap: 12 }}>
        <FoodTable
          logs={logs}
          onAdd={(mealId) => { setCurrentMeal(mealId); setShowModal(true) }}
          onDelete={deleteLog}
        />

        <div style={{ display: 'flex', flexDirection: 'column', gap: 12 }}>
          <div className="card" style={{ marginBottom: 0 }}>
            <div className="card-title">Баланс КБЖВ</div>

            {[
              ['Вуглеводи', Math.round(total.carbs), goals.carbs, 'var(--purple)'],
              ['Білки', Math.round(total.protein), goals.protein, 'var(--green)'],
              ['Жири', Math.round(total.fat), goals.fat, 'var(--amber)']
            ].map(([label, val, goal, color]) => (
              <div key={label} style={{ marginBottom: 10 }}>
                <div style={{ display: 'flex', justifyContent: 'space-between', fontSize: 13, marginBottom: 4 }}>
                  <span style={{ color: 'var(--text-secondary)' }}>{label}</span>
                  <span style={{ color, fontWeight: 500 }}>
                    {val}г{' '}
                    <span style={{ color: 'var(--text-faint)', fontWeight: 400, fontSize: 12 }}>
                      {pct(val, goal)}%
                    </span>
                  </span>
                </div>

                <div className="progress-bar">
                  <div className="progress-fill" style={{ width: pct(val, goal) + '%', background: color }} />
                </div>
              </div>
            ))}
          </div>

          <div className="card" style={{ marginBottom: 0 }}>
            <div className="card-title">Підсумок дня</div>

            {[
              ['Спожито', `${Math.round(total.kcal)} ккал`],
              ['Ціль', `${goals.kcal} ккал`],
              ['Залишок', `${Math.max(0, goals.kcal - Math.round(total.kcal))} ккал`],
              ['Прийомів', `${MEALS.filter(m => logs.some(l => l.meal_type === m.id)).length} з 4`],
              ['Записів', `${logs.length}`]
            ].map(([label, val]) => (
              <div
                key={label}
                style={{
                  display: 'flex',
                  justifyContent: 'space-between',
                  fontSize: 13,
                  padding: '6px 0',
                  borderBottom: '1px solid var(--border-light)'
                }}
              >
                <span style={{ color: 'var(--text-muted)' }}>{label}</span>
                <span style={{ fontWeight: 500 }}>{val}</span>
              </div>
            ))}
          </div>
        </div>
      </div>

      {showModal && (
        <FoodModal
          mealId={currentMeal}
          date={date}
          onClose={closeModal}
          onSaved={() => { closeModal(); load(date) }}
        />
      )}
    </div>
  )
}