adds syncing

This commit is contained in:
2025-08-27 16:17:21 +02:00
parent 1191d06e53
commit 709cf2cbd9
24 changed files with 3809 additions and 226 deletions

View File

@@ -1,7 +1,9 @@
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:intl/intl.dart';
import 'package:provider/provider.dart';
import '../providers/supplement_provider.dart';
import '../providers/sync_provider.dart';
class HistoryScreen extends StatefulWidget {
const HistoryScreen({super.key});
@@ -30,6 +32,32 @@ class _HistoryScreenState extends State<HistoryScreen> {
appBar: AppBar(
title: const Text('Intake History'),
backgroundColor: Theme.of(context).colorScheme.inversePrimary,
actions: [
Consumer<SyncProvider>(
builder: (context, syncProvider, child) {
if (!syncProvider.isConfigured) {
return const SizedBox.shrink();
}
return IconButton(
icon: syncProvider.isSyncing
? const SizedBox(
width: 20,
height: 20,
child: CircularProgressIndicator(strokeWidth: 2),
)
: syncProvider.status.name == 'success' &&
DateTime.now().difference(syncProvider.lastSyncTime ?? DateTime.now()).inSeconds < 5
? const Icon(Icons.check, color: Colors.green)
: const Icon(Icons.sync),
onPressed: syncProvider.isSyncing ? null : () {
syncProvider.performManualSync();
},
tooltip: syncProvider.isSyncing ? 'Syncing...' : 'Force Sync',
);
},
),
],
),
body: _buildCalendarView(),
);
@@ -106,7 +134,7 @@ class _HistoryScreenState extends State<HistoryScreen> {
return LayoutBuilder(
builder: (context, constraints) {
final isWideScreen = constraints.maxWidth > 800;
if (isWideScreen) {
// Desktop/tablet layout: side-by-side
return Row(
@@ -177,7 +205,7 @@ class _HistoryScreenState extends State<HistoryScreen> {
);
},
);
if (picked != null) {
setState(() {
_selectedMonth = picked.month;
@@ -203,13 +231,13 @@ class _HistoryScreenState extends State<HistoryScreen> {
onPressed: () async {
await context.read<SupplementProvider>().deleteIntake(intakeId);
Navigator.of(context).pop();
// Force refresh of the UI
setState(() {});
// Force refresh of the current view data
context.read<SupplementProvider>().loadMonthlyIntakes(_selectedYear, _selectedMonth);
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text('$supplementName intake deleted'),
@@ -230,11 +258,11 @@ class _HistoryScreenState extends State<HistoryScreen> {
final lastDayOfMonth = DateTime(_selectedYear, _selectedMonth + 1, 0);
final firstWeekday = firstDayOfMonth.weekday;
final daysInMonth = lastDayOfMonth.day;
// Calculate how many cells we need (including empty ones for alignment)
final totalCells = ((daysInMonth + firstWeekday - 1) / 7).ceil() * 7;
final weeks = (totalCells / 7).ceil();
return LayoutBuilder(
builder: (context, constraints) {
final isWideScreen = constraints.maxWidth > 800;
@@ -242,7 +270,7 @@ class _HistoryScreenState extends State<HistoryScreen> {
final cellHeight = isWideScreen ? 56.0 : 48.0;
final calendarContentHeight = (weeks * cellHeight) + 60; // +60 for headers and padding
final calendarHeight = isWideScreen ? 400.0 : calendarContentHeight;
return Card(
child: Container(
height: calendarHeight,
@@ -283,11 +311,11 @@ class _HistoryScreenState extends State<HistoryScreen> {
itemCount: totalCells,
itemBuilder: (context, index) {
final dayNumber = index - firstWeekday + 2;
if (dayNumber < 1 || dayNumber > daysInMonth) {
return const SizedBox(); // Empty cell
}
final date = DateTime(_selectedYear, _selectedMonth, dayNumber);
final dateKey = DateFormat('yyyy-MM-dd').format(date);
final hasIntakes = groupedIntakes.containsKey(dateKey);
@@ -295,7 +323,7 @@ class _HistoryScreenState extends State<HistoryScreen> {
final isSelected = _selectedDay != null &&
DateFormat('yyyy-MM-dd').format(_selectedDay!) == dateKey;
final isToday = DateFormat('yyyy-MM-dd').format(DateTime.now()) == dateKey;
return GestureDetector(
onTap: () {
setState(() {
@@ -305,12 +333,12 @@ class _HistoryScreenState extends State<HistoryScreen> {
child: Container(
margin: const EdgeInsets.all(1),
decoration: BoxDecoration(
color: isSelected
color: isSelected
? Theme.of(context).colorScheme.primary
: hasIntakes
: hasIntakes
? Theme.of(context).colorScheme.primaryContainer
: null,
border: isToday
border: isToday
? Border.all(color: Theme.of(context).colorScheme.secondary, width: 2)
: null,
borderRadius: BorderRadius.circular(8),
@@ -321,9 +349,9 @@ class _HistoryScreenState extends State<HistoryScreen> {
child: Text(
'$dayNumber',
style: TextStyle(
color: isSelected
color: isSelected
? Theme.of(context).colorScheme.onPrimary
: hasIntakes
: hasIntakes
? Theme.of(context).colorScheme.onPrimaryContainer
: Theme.of(context).colorScheme.onSurface,
fontWeight: isToday ? FontWeight.bold : FontWeight.normal,
@@ -338,7 +366,7 @@ class _HistoryScreenState extends State<HistoryScreen> {
child: Container(
padding: EdgeInsets.all(isWideScreen ? 3 : 2),
decoration: BoxDecoration(
color: isSelected
color: isSelected
? Theme.of(context).colorScheme.onPrimary
: Theme.of(context).colorScheme.primary,
borderRadius: BorderRadius.circular(8),
@@ -350,7 +378,7 @@ class _HistoryScreenState extends State<HistoryScreen> {
child: Text(
'$intakeCount',
style: TextStyle(
color: isSelected
color: isSelected
? Theme.of(context).colorScheme.primary
: Theme.of(context).colorScheme.onPrimary,
fontSize: isWideScreen ? 11 : 10,
@@ -380,7 +408,7 @@ class _HistoryScreenState extends State<HistoryScreen> {
return LayoutBuilder(
builder: (context, constraints) {
final isWideScreen = constraints.maxWidth > 600;
if (_selectedDay == null) {
return Card(
child: Center(