Add Programmer Tasks module (work-log + time tracking)
Separate feature for the `programmer` role to record dev work by category, distinct from the IT help-desk `tasks` feature. Modeled on the IT Service Requests pattern (Brick offline-first model -> Riverpod stream/controller -> list/detail screens); seed of a future Project Management workflow. - programmer_tasks + programmer_task_activity_logs (category enum, RLS, realtime) via supabase migration - single assignee, self-logged or lead-assigned; assign/reassign logged - pause-on-switch: starting a task while another runs prompts to pause the running one, keeping one active task per user for accurate time attribution - worked-duration math shared with help-desk tasks via a generic core in task_duration.dart (existing callers unchanged) - list distinguishes running vs paused with a per-task Resume shortcut - accessible dialog labels; route /programmer-tasks + nav gated to admin/programmer - unit/widget tests: controller lifecycle, duration math, pause-switch dialog Co-Authored-By: claude-flow <ruv@ruv.net>
This commit is contained in:
@@ -30,6 +30,8 @@ import '../widgets/app_shell.dart';
|
||||
import '../screens/teams/teams_screen.dart';
|
||||
import '../screens/it_service_requests/it_service_requests_list_screen.dart';
|
||||
import '../screens/it_service_requests/it_service_request_detail_screen.dart';
|
||||
import '../screens/programmer_tasks/programmer_tasks_list_screen.dart';
|
||||
import '../screens/programmer_tasks/programmer_task_detail_screen.dart';
|
||||
import '../screens/network_map/network_map_overview_screen.dart';
|
||||
import '../screens/network_map/network_map_site_screen.dart';
|
||||
import '../screens/network_map/network_map_device_screen.dart';
|
||||
@@ -93,6 +95,10 @@ final appRouterProvider = Provider<GoRouter>((ref) {
|
||||
role == 'it_staff' ||
|
||||
role == 'dispatcher' ||
|
||||
role == 'programmer';
|
||||
final isProgrammerTasksRoute =
|
||||
state.matchedLocation.startsWith('/programmer-tasks');
|
||||
final hasProgrammerTasksAccess =
|
||||
role == 'admin' || role == 'programmer';
|
||||
|
||||
if (!isSignedIn && !isAuthRoute) {
|
||||
return '/login';
|
||||
@@ -125,6 +131,9 @@ final appRouterProvider = Provider<GoRouter>((ref) {
|
||||
if (isNetworkMapRoute && !hasNetworkMapAccess) {
|
||||
return '/tickets';
|
||||
}
|
||||
if (isProgrammerTasksRoute && !hasProgrammerTasksAccess) {
|
||||
return '/tickets';
|
||||
}
|
||||
// Attendance & Whereabouts: not accessible to standard users
|
||||
final isStandardOnly = role == 'standard';
|
||||
final isAttendanceRoute =
|
||||
@@ -207,6 +216,21 @@ final appRouterProvider = Provider<GoRouter>((ref) {
|
||||
),
|
||||
],
|
||||
),
|
||||
GoRoute(
|
||||
path: '/programmer-tasks',
|
||||
pageBuilder: _page(const ProgrammerTasksListScreen()),
|
||||
routes: [
|
||||
GoRoute(
|
||||
path: ':id',
|
||||
pageBuilder: (context, state) => M3ContainerTransformPage(
|
||||
key: state.pageKey,
|
||||
child: ProgrammerTaskDetailScreen(
|
||||
taskId: state.pathParameters['id'] ?? '',
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
GoRoute(
|
||||
path: '/announcements',
|
||||
pageBuilder: _page(const AnnouncementsScreen()),
|
||||
|
||||
Reference in New Issue
Block a user