Files
tasq/lib/providers/programmer_task_work_logs_provider.dart
T
redz1029 b307f66f2c Add PM extension (Projects, Work Logs, Comments) + Quill rich-text UI
Projects: Brick-backed model with list/detail screens and nav entry.
Work Logs: per-contributor time ledger, assignee running-clock +
helper logged minutes with Hours/Minutes input; pause-after-save and
helper-deduct prompts.
Comments: threaded comments with file attachments and Quill composer.
Detail screen: tabbed layout (Work Log / Comments / Activity),
editable title + description via edit dialog, Quill-rendered
descriptions with legacy plain-text fallback.
Create dialog: fixed-width (480px max), Quill description editor.
Shared QuillFieldEditor + QuillReadOnly widgets extracted for reuse.
RLS: hardened activity-log actor binding, immutable creator_id/
created_at triggers, SECURITY INVOKER visibility helper,
append-only work-log and scoped comment policies.
Brick migration for project_id FK on programmer_tasks.

Co-Authored-By: claude-flow <ruv@ruv.net>
2026-09-27 16:06:26 +08:00

45 lines
1.5 KiB
Dart

import 'package:flutter_riverpod/flutter_riverpod.dart';
import '../models/programmer_task_work_log.model.dart';
import 'supabase_provider.dart';
/// Work-log entries for a task (newest first), streamed live.
final programmerTaskWorkLogsProvider =
StreamProvider.family<List<ProgrammerTaskWorkLog>, String>((ref, taskId) {
final client = ref.watch(supabaseClientProvider);
return client
.from('programmer_task_work_logs')
.stream(primaryKey: ['id'])
.eq('task_id', taskId)
.order('created_at', ascending: false)
.map((rows) => rows.map(ProgrammerTaskWorkLog.fromMap).toList());
});
final programmerTaskWorkLogsControllerProvider =
Provider<ProgrammerTaskWorkLogsController>((ref) {
return ProgrammerTaskWorkLogsController(ref.watch(supabaseClientProvider));
});
class ProgrammerTaskWorkLogsController {
ProgrammerTaskWorkLogsController(this._client);
final dynamic _client;
/// Adds a work-log entry. [minutes] is null for the assignee's progress notes
/// (their time comes from the running clock) and set for a helper's
/// Time Consumed.
Future<void> addWorkLog({
required String taskId,
required String description,
int? minutes,
}) async {
final userId = _client.auth.currentUser?.id;
if (userId == null) throw Exception('Not authenticated');
await _client.from('programmer_task_work_logs').insert({
'task_id': taskId,
'author_id': userId,
'description': description,
'minutes': ?minutes,
});
}
}