import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:go_router/go_router.dart'; import '../../models/programmer_project.model.dart'; import '../../models/programmer_task.model.dart'; import '../../providers/programmer_projects_provider.dart'; import '../../providers/programmer_tasks_provider.dart'; import '../../theme/app_status_colors.dart'; import '../../widgets/app_section_header.dart'; import '../../widgets/m3_card.dart'; import '../../widgets/responsive_body.dart'; import '../../widgets/status_pill.dart'; import '../programmer_tasks/programmer_task_create.dart'; import '../programmer_tasks/programmer_task_status_kind.dart'; class ProgrammerProjectDetailScreen extends ConsumerWidget { const ProgrammerProjectDetailScreen({super.key, required this.projectId}); final String projectId; @override Widget build(BuildContext context, WidgetRef ref) { final project = ref.watch(programmerProjectByIdProvider(projectId)); final tasks = (ref.watch(programmerTasksProvider).valueOrNull ?? const []) .where((t) => t.projectId == projectId) .toList(); return Scaffold( appBar: AppBar( title: Text(project?.name ?? 'Project'), actions: [ if (project != null) IconButton( tooltip: project.isArchived ? 'Unarchive' : 'Archive', icon: Icon(project.isArchived ? Icons.unarchive_outlined : Icons.archive_outlined), onPressed: () async { final messenger = ScaffoldMessenger.of(context); await ref.read(programmerProjectsControllerProvider).setArchived( projectId: projectId, archived: !project.isArchived, ); messenger.showSnackBar(SnackBar( content: Text( project.isArchived ? 'Project unarchived' : 'Project archived'), )); }, ), ], ), floatingActionButton: project == null ? null : FloatingActionButton.extended( heroTag: 'project_new_task', onPressed: () => showCreateProgrammerTaskDialog( context, ref, initialProjectId: projectId, ), icon: const Icon(Icons.add), label: const Text('New Task'), ), body: project == null ? const Center(child: CircularProgressIndicator()) : ResponsiveBody( child: ListView( padding: const EdgeInsets.symmetric(vertical: 16), children: [ M3Card.elevated( child: Padding( padding: const EdgeInsets.all(16), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( children: [ Expanded( child: Text(project.name, style: Theme.of(context) .textTheme .titleLarge ?.copyWith(fontWeight: FontWeight.w700)), ), StatusPill.kind( project.isArchived ? StatusKind.neutral : StatusKind.success, label: ProgrammerProjectStatus.label( project.status), ), ], ), if (project.description != null && project.description!.trim().isNotEmpty) ...[ const SizedBox(height: 12), Text(project.description!, style: Theme.of(context).textTheme.bodyMedium), ], ], ), ), ), const SizedBox(height: 24), AppSectionHeader('Tasks (${tasks.length})'), if (tasks.isEmpty) Text('No tasks in this project yet.', style: Theme.of(context).textTheme.bodySmall?.copyWith( color: Theme.of(context).colorScheme.onSurfaceVariant)) else for (final t in tasks) _ProjectTaskTile(task: t), const SizedBox(height: 80), ], ), ), ); } } class _ProjectTaskTile extends StatelessWidget { const _ProjectTaskTile({required this.task}); final ProgrammerTask task; @override Widget build(BuildContext context) { return Padding( padding: const EdgeInsets.symmetric(vertical: 5), child: M3Card.outlined( onTap: () => context.go('/programmer-tasks/${task.id}'), child: Padding( padding: const EdgeInsets.all(12), child: Row( children: [ Expanded( child: Text(task.title, style: Theme.of(context).textTheme.bodyLarge, maxLines: 1, overflow: TextOverflow.ellipsis), ), const SizedBox(width: 8), StatusPill.kind( programmerTaskStatusKind(task.status), label: ProgrammerTaskStatus.label(task.status), ), ], ), ), ), ); } }