'январь', 2 => 'февраль', 3 => 'март', 4 => 'апрель', 5 => 'май', 6 => 'июнь',
7 => 'июль', 8 => 'август', 9 => 'сентябрь', 10 => 'октябрь', 11 => 'ноябрь', 12 => 'декабрь',
];
$groups = $tree[0] ?? [];
// Строки плана для секции типа $type (income|expense): группа с подкатегориями — заголовком
// группы + строками по ним; группа без подкатегорий — одной строкой на саму группу (тот же
// приём, что и в App/view/Budgets/budgets.html). Показываем только план — факта (реальных
// transactions) в проекте ещё нет, а прогресс-бар, который всегда 0%, только запутывает
// (см. фидбек пользователя); добавим план/факт, когда появятся операции. Замыкание, не
// именованная функция — шаблон может быть include'ится не один раз за процесс (например
// в тестах), именованная функция дала бы "Cannot redeclare".
$renderBudgetList = static function (array $groups, array $tree, array $plan_month, string $type): void {
$type_groups = array_filter($groups, static fn ($g) => $g->type === $type);
if ($type_groups === []) {
echo '
Нет статей — добавьте их на странице «Статьи»
';
return;
}
echo '
';
foreach ($type_groups as $group) {
$children = $tree[$group->id] ?? [];
// Заголовок-плашка — ВСЕГДА, и у настоящей группы, и у самостоятельной статьи (тогда
// плашка — единственная строка на неё, показывает сразу и название, и сумму). Без этого
// самостоятельная статья визуально не отличалась от рядового члена предыдущей группы
// (см. фидбек пользователя — тонкой разницы фона недостаточно, нужна однозначная граница).
$head_plan = $children !== []
? array_sum(array_map(static fn ($c) => $plan_month[$c->id] ?? 0.0, $children))
: ($plan_month[$group->id] ?? 0.0);
echo '