diff --git a/lib/providers/programmer_day_data_provider.dart b/lib/providers/programmer_day_data_provider.dart index 51bae744..aa4ab298 100644 --- a/lib/providers/programmer_day_data_provider.dart +++ b/lib/providers/programmer_day_data_provider.dart @@ -200,6 +200,35 @@ final programmerDayDataProvider = return fetchDayActivityData(client, day: day, tasks: tasks, now: AppTime.now()); }); +/// Total help-given seconds for [userId] in the current Manila calendar month. +/// +/// Queries work logs with minutes > 0 authored by [userId] this month. +/// Re-fetches whenever [programmerActivitySignalProvider] fires. +final helpGivenThisMonthProvider = + FutureProvider.family((ref, userId) async { + ref.watch(programmerActivitySignalProvider); + final client = ref.watch(supabaseClientProvider); + final today = ref.watch(todayKeyProvider); + final monthStart = DateTime.utc(today.year, today.month, 1); + final nextMonthStart = today.month < 12 + ? DateTime.utc(today.year, today.month + 1, 1) + : DateTime.utc(today.year + 1, 1, 1); + + final raw = await client + .from('programmer_task_work_logs') + .select('minutes') + .eq('author_id', userId) + .gte('work_date', formatDayKey(monthStart)) + .lt('work_date', formatDayKey(nextMonthStart)) as List; + + int totalSec = 0; + for (final r in raw) { + final minutes = r['minutes'] as int?; + if (minutes != null && minutes > 0) totalSec += minutes * 60; + } + return totalSec; +}); + /// Run states for today's tasks, derived from today's [programmerDayDataProvider]. final programmerRunStatesProvider = Provider>((ref) { final today = ref.watch(todayKeyProvider); diff --git a/lib/screens/programmer_tasks/dashboard/programmer_dashboard.dart b/lib/screens/programmer_tasks/dashboard/programmer_dashboard.dart index db9c84b4..d39957db 100644 --- a/lib/screens/programmer_tasks/dashboard/programmer_dashboard.dart +++ b/lib/screens/programmer_tasks/dashboard/programmer_dashboard.dart @@ -47,6 +47,9 @@ class ProgrammerDashboard extends ConsumerWidget { final sheetsAsync = ref.watch(daySheetsForUserProvider(userId)); final sheets = sheetsAsync.valueOrNull ?? const []; + final liveHelpThisMonthSec = + ref.watch(helpGivenThisMonthProvider(userId)).valueOrNull; + final tasks = tasksAsync.valueOrNull ?? const []; final profileById = { for (final p in profilesAsync.valueOrNull ?? []) p.id: p, @@ -82,6 +85,7 @@ class ProgrammerDashboard extends ConsumerWidget { sheets: sheets, leaveDays: leaveDays, todayFocus: todayFocus, + liveHelpThisMonthSec: liveHelpThisMonthSec, ); final showSheetStats = diff --git a/lib/screens/programmer_tasks/programmer_tasks_list_screen.dart b/lib/screens/programmer_tasks/programmer_tasks_list_screen.dart index 82950f68..0290393e 100644 --- a/lib/screens/programmer_tasks/programmer_tasks_list_screen.dart +++ b/lib/screens/programmer_tasks/programmer_tasks_list_screen.dart @@ -1,3 +1,4 @@ +import 'package:flutter/foundation.dart' show listEquals; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; @@ -45,9 +46,7 @@ class _ProgrammerTasksListScreenState if (idx >= 0) initialIndex = idx; } - if (_tabsBuilt && - _tabs == tabs && - _tabController.length == tabs.length) { + if (_tabsBuilt && listEquals(_tabs, tabs)) { return; } diff --git a/lib/utils/programmer_stats.dart b/lib/utils/programmer_stats.dart index b6cda7d4..01b2bc20 100644 --- a/lib/utils/programmer_stats.dart +++ b/lib/utils/programmer_stats.dart @@ -41,6 +41,10 @@ DateTime _weekStart(DateTime dt) { } /// Compute all programmer statistics from raw data. +/// +/// [liveHelpThisMonthSec] — when provided (from a live work-log query), this +/// value is used directly for [ProgrammerStats.helpGivenThisMonth] instead of +/// the approved-snapshot sum, so the stat reflects pending work too. ProgrammerStats computeProgrammerStats({ required String userId, required DateTime now, @@ -48,6 +52,7 @@ ProgrammerStats computeProgrammerStats({ required List sheets, required Set leaveDays, required Duration todayFocus, + int? liveHelpThisMonthSec, }) { final today = _dateOnly(now); final thisWeekStart = _weekStart(today); @@ -121,7 +126,8 @@ ProgrammerStats computeProgrammerStats({ return ProgrammerStats( todayFocus: todayFocus, - helpGivenThisMonth: Duration(seconds: helpGivenThisMonthSec), + helpGivenThisMonth: Duration( + seconds: liveHelpThisMonthSec ?? helpGivenThisMonthSec), approvedTotal: Duration(seconds: approvedTotalSec), helpGivenTotal: Duration(seconds: helpGivenTotalSec), completedThisWeek: completedThisWeek,