9a40ffec81
NowWorkingCard was watching clockTickerProvider but received pre-computed Duration values from ProgrammerDashboard, which never rebuilt on ticks. Move ref.watch(clockTickerProvider) to ProgrammerDashboard.build() so the parent rebuilds every 30 s and passes fresh durations to the card. Remove the now-unused clockTickerProvider watch (and its import) from NowWorkingCard. Co-Authored-By: claude-flow <ruv@ruv.net>
118 lines
3.8 KiB
Dart
118 lines
3.8 KiB
Dart
import 'package:flutter/material.dart';
|
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
|
|
|
import '../../../models/profile.model.dart';
|
|
import '../../../models/programmer_task.model.dart';
|
|
import '../../../providers/profile_provider.dart';
|
|
import '../../../providers/programmer_day_data_provider.dart';
|
|
import '../../../providers/programmer_tasks_provider.dart';
|
|
import '../../../utils/programmer_daily_time.dart';
|
|
import 'now_working_card.dart';
|
|
import 'task_sections.dart';
|
|
|
|
/// The programmer's own work dashboard — hero card, stat tiles (Task 8), and
|
|
/// task sections. Drop it into the Mine tab with `userId: me`.
|
|
class ProgrammerDashboard extends ConsumerWidget {
|
|
const ProgrammerDashboard({
|
|
super.key,
|
|
required this.userId,
|
|
this.readOnly = false,
|
|
});
|
|
|
|
final String userId;
|
|
final bool readOnly;
|
|
|
|
@override
|
|
Widget build(BuildContext context, WidgetRef ref) {
|
|
// Drive 30-second rebuilds so duration values stay fresh.
|
|
ref.watch(clockTickerProvider);
|
|
|
|
final tasksAsync = ref.watch(programmerTasksProvider);
|
|
final runStates = ref.watch(programmerRunStatesProvider);
|
|
final todayKey = ref.watch(todayKeyProvider);
|
|
final dayDataAsync = ref.watch(programmerDayDataProvider(todayKey));
|
|
final profilesAsync = ref.watch(profilesProvider);
|
|
|
|
final tasks = tasksAsync.valueOrNull ?? const [];
|
|
final profileById = <String, Profile>{
|
|
for (final p in profilesAsync.valueOrNull ?? <Profile>[]) p.id: p,
|
|
};
|
|
|
|
final groups = groupTasksForDashboard(tasks, runStates, userId);
|
|
final runningTask =
|
|
groups.running.isNotEmpty ? groups.running.first : null;
|
|
final nextUp =
|
|
groups.notStarted.isNotEmpty ? groups.notStarted.first : null;
|
|
|
|
final todayOnTask = _computeTodayDuration(
|
|
runningTask: runningTask,
|
|
dayDataAsync: dayDataAsync,
|
|
userId: userId,
|
|
todayKey: todayKey,
|
|
);
|
|
final totalOnTask = _computeTotalDuration(
|
|
runningTask: runningTask,
|
|
dayDataAsync: dayDataAsync,
|
|
userId: userId,
|
|
);
|
|
|
|
return ListView(
|
|
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
|
|
children: [
|
|
NowWorkingCard(
|
|
running: runningTask,
|
|
nextUp: nextUp,
|
|
todayOnTask: todayOnTask,
|
|
totalOnTask: totalOnTask,
|
|
readOnly: readOnly,
|
|
),
|
|
const SizedBox(height: 16),
|
|
// TODO: Task 8 inserts StatTiles + BadgesStrip here
|
|
TaskSections(
|
|
groups: groups,
|
|
profileById: profileById,
|
|
readOnly: readOnly,
|
|
),
|
|
],
|
|
);
|
|
}
|
|
|
|
Duration _computeTodayDuration({
|
|
required ProgrammerTask? runningTask,
|
|
required AsyncValue<dynamic> dayDataAsync,
|
|
required String userId,
|
|
required DateTime todayKey,
|
|
}) {
|
|
if (runningTask == null) return Duration.zero;
|
|
final dayData = dayDataAsync.valueOrNull;
|
|
if (dayData == null) return Duration.zero;
|
|
final logs = dayData.logsByTask[runningTask.id] ?? const [];
|
|
final dailyByAssignee = dailySecondsByAssignee(
|
|
task: runningTask,
|
|
logs: logs,
|
|
now: DateTime.now().toUtc(),
|
|
);
|
|
final secs = dailyByAssignee[userId]?[todayKey] ?? 0;
|
|
return Duration(seconds: secs);
|
|
}
|
|
|
|
Duration _computeTotalDuration({
|
|
required ProgrammerTask? runningTask,
|
|
required AsyncValue<dynamic> dayDataAsync,
|
|
required String userId,
|
|
}) {
|
|
if (runningTask == null) return Duration.zero;
|
|
final dayData = dayDataAsync.valueOrNull;
|
|
if (dayData == null) return Duration.zero;
|
|
final logs = dayData.logsByTask[runningTask.id] ?? const [];
|
|
final dailyByAssignee = dailySecondsByAssignee(
|
|
task: runningTask,
|
|
logs: logs,
|
|
now: DateTime.now().toUtc(),
|
|
);
|
|
final totalSecs =
|
|
(dailyByAssignee[userId] ?? const {}).values.fold<int>(0, (s, v) => s + v);
|
|
return Duration(seconds: totalSecs);
|
|
}
|
|
}
|