import 'package:tasq/models/programmer_task.model.dart'; import 'package:tasq/models/programmer_task_activity_log.model.dart'; import 'package:tasq/models/programmer_task_work_log.model.dart'; import 'package:tasq/widgets/quill_field.dart'; import 'programmer_daily_time.dart'; /// A single row in a programmer's day sheet (assignee or helper work). class DaySheetRow { final String taskId; final String title; final String category; final String kind; // 'assignee' or 'helper' final String? projectName; final String? helpedName; final int seconds; final List notes; DaySheetRow({ required this.taskId, required this.title, required this.category, required this.kind, this.projectName, this.helpedName, required this.seconds, required this.notes, }); Map toJson() => { 'task_id': taskId, 'title': title, 'category': category, 'project_name': projectName, 'kind': kind, 'helped_name': helpedName, 'seconds': seconds, 'notes': notes, }; factory DaySheetRow.fromJson(Map json) => DaySheetRow( taskId: json['task_id'] as String, title: json['title'] as String, category: json['category'] as String, kind: json['kind'] as String, projectName: json['project_name'] as String?, helpedName: json['helped_name'] as String?, seconds: json['seconds'] as int, notes: List.from(json['notes'] as List? ?? []), ); } /// Build day rows for a programmer on a specific day. /// Returns rows for assignee tasks (by seconds desc) then helper tasks (by seconds desc). List buildDayRows({ required String userId, required DateTime day, required List tasks, required Map> logsByTask, required List workLogs, required Map projectNames, required Map profileNames, required DateTime now, }) { final taskMap = {for (final t in tasks) t.id: t}; final workLogsByTaskAndAuthor = >{}; // Group work logs by task and author for quick lookup for (final log in workLogs) { final key = '${log.taskId}:${log.authorId}'; workLogsByTaskAndAuthor.putIfAbsent(key, () => []).add(log); } final rows = []; // Process each task for (final task in tasks) { final assigneeId = task.assigneeId; // Compute daily seconds for this task final logs = logsByTask[task.id] ?? []; final dailyByAssignee = dailySecondsByAssignee( task: task, logs: logs, now: now, ); final userDailySeconds = dailyByAssignee[userId] ?? {}; final assigneeSeconds = userDailySeconds[day] ?? 0; // Check for assignee row: has seconds that day OR (is assignee AND authored notes-only log that day) final assigneeLogsKey = '${task.id}:$userId'; final assigneeLogsThisDay = (userId == assigneeId) ? (workLogsByTaskAndAuthor[assigneeLogsKey] ?.where((l) => l.workDate == day && l.minutes == null) .toList() ?? []) : []; if (assigneeSeconds > 0 || assigneeLogsThisDay.isNotEmpty) { final notes = assigneeLogsThisDay .map((l) => deltaJsonToPlainText(l.description)) .where((n) => n.isNotEmpty) .toList(); rows.add(DaySheetRow( taskId: task.id, title: task.title, category: task.category, kind: 'assignee', projectName: task.projectId != null ? projectNames[task.projectId] : null, helpedName: null, seconds: assigneeSeconds, notes: notes, )); } // Check for helper row: userId != assigneeId AND has minutes logs that day if (userId != assigneeId) { final helperLogsKey = '${task.id}:$userId'; final helperLogs = workLogsByTaskAndAuthor[helperLogsKey] ?.where((l) => l.workDate == day && l.minutes != null && l.minutes! > 0) .toList() ?? []; if (helperLogs.isNotEmpty) { final totalMinutes = helperLogs.fold(0, (sum, l) => sum + (l.minutes ?? 0)); final seconds = totalMinutes * 60; final notes = helperLogs .map((l) => deltaJsonToPlainText(l.description)) .where((n) => n.isNotEmpty) .toList(); rows.add(DaySheetRow( taskId: task.id, title: task.title, category: task.category, kind: 'helper', projectName: task.projectId != null ? projectNames[task.projectId] : null, helpedName: assigneeId != null ? profileNames[assigneeId] : null, seconds: seconds, notes: notes, )); } } } // Sort: assignee rows by seconds desc, then helper rows by seconds desc rows.sort((a, b) { if (a.kind != b.kind) { return a.kind == 'assignee' ? -1 : 1; } return b.seconds.compareTo(a.seconds); }); return rows; } /// Calculate total seconds from day sheet rows. int totalSeconds(List rows) { return rows.fold(0, (sum, row) => sum + row.seconds); }