diet-guard/app/lib/widgets/streak_summary_row.dart
Krzysztof kuhy Rudnicki 957769ff0e
Some checks are pending
pre-commit / pre-commit (push) Waiting to run
Tests / test (3.10) (push) Waiting to run
Tests / test (3.11) (push) Waiting to run
Tests / test (3.12) (push) Waiting to run
Add budget-adherence calendar, streaks, and freely-editable synced budget
Both platforms gain a calendar tab/screen (green/yellow/red/not-logged
day coloring, logging/adherence streaks, year-to-date tally), and
tapping a day drills into that day's logged entries. This requires the
daily budget to become a normal, freely-editable value synced between
devices like the food log — replaces the previous chattr +i seal
(deliberately, per user decision) with plain last-edit-wins sync via a
new budget.json alongside food_log.json. The budget field defaults to
2200 kcal, starts read-only, and unlocks via an Edit/Save toggle on
both the PC gate's History tab and the phone app's Calendar screen.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016dHac1iYQKTMZEtL7xDJvA
2026-07-13 21:31:45 +02:00

54 lines
1.6 KiB
Dart

/// Streak and year-to-date tally summary row for the History screen.
library;
import 'package:diet_guard_app/models/day_status.dart';
import 'package:flutter/material.dart';
/// Displays the logging streak, adherence streak, and year-to-date tally.
///
/// Mirrors `_calendar_view.py`'s `streaks_text`/`ytd_text` formatting:
/// "Logging streak: N day(s) · Adherence streak: N day(s)" and
/// "This year: logged X/Y days · Z within budget".
class StreakSummaryRow extends StatelessWidget {
/// Creates a [StreakSummaryRow].
const StreakSummaryRow({
required this.loggingStreak,
required this.adherenceStreak,
required this.tally,
super.key,
});
/// Consecutive-day logging streak.
final int loggingStreak;
/// Consecutive-day budget-adherence streak.
final int adherenceStreak;
/// This year's logged/elapsed/adherent day counts.
final YtdTally tally;
static String _plural(int count) => count == 1 ? 'day' : 'days';
@override
Widget build(BuildContext context) {
final theme = Theme.of(context);
return Column(
children: [
Text(
'Logging streak: $loggingStreak ${_plural(loggingStreak)} · '
'Adherence streak: $adherenceStreak ${_plural(adherenceStreak)}',
textAlign: TextAlign.center,
style: theme.textTheme.titleSmall,
),
const SizedBox(height: 4),
Text(
'This year: logged ${tally.loggedDays}/${tally.elapsedDays} days · '
'${tally.adherentDays} within budget',
textAlign: TextAlign.center,
style: theme.textTheme.bodySmall,
),
],
);
}
}