import 'package:auto_route/auto_route.dart'; import 'package:flutter/material.dart'; import 'package:image_picker/image_picker.dart'; import 'dart:io'; import '../../../common/theme/theme.dart'; // Model untuk question item class TaskQuestion { final String id; final String question; bool? answer; File? photo; TaskQuestion({ required this.id, required this.question, this.answer, this.photo, }); } // Model untuk task section class TaskSection { final String title; final List questions; TaskSection({required this.title, required this.questions}); } @RoutePage() class DailyTasksFormPage extends StatefulWidget { const DailyTasksFormPage({super.key}); @override State createState() => _DailyTasksFormPageState(); } class _DailyTasksFormPageState extends State with SingleTickerProviderStateMixin { late TabController _tabController; final ImagePicker _picker = ImagePicker(); // Sample data untuk OPEN dan CLOSING tasks List taskSections = [ TaskSection( title: "OPENING", questions: [ TaskQuestion(id: "open_1", question: "Apakah meja sudah dibersihkan?"), TaskQuestion( id: "open_2", question: "Apakah alat kerja sudah disiapkan?", ), TaskQuestion( id: "open_3", question: "Apakah ruangan sudah dalam kondisi bersih?", ), TaskQuestion( id: "open_4", question: "Apakah penerangan sudah memadai?", ), ], ), TaskSection( title: "CLOSING", questions: [ TaskQuestion( id: "close_1", question: "Apakah meja sudah dibersihkan kembali?", ), TaskQuestion( id: "close_2", question: "Apakah alat kerja sudah disimpan dengan rapi?", ), TaskQuestion(id: "close_3", question: "Apakah lampu sudah dimatikan?"), TaskQuestion(id: "close_4", question: "Apakah pintu sudah dikunci?"), ], ), ]; @override void initState() { super.initState(); _tabController = TabController(length: 2, vsync: this); } @override void dispose() { _tabController.dispose(); super.dispose(); } Future _pickImage(TaskQuestion question) async { try { final XFile? image = await _picker.pickImage( source: ImageSource.camera, maxWidth: 1920, maxHeight: 1080, imageQuality: 85, ); if (image != null) { setState(() { question.photo = File(image.path); }); } } catch (e) { ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Text('Error mengambil foto: $e'), backgroundColor: AppColor.error, ), ); } } void _removePhoto(TaskQuestion question) { setState(() { question.photo = null; }); } bool _isFormComplete() { for (var section in taskSections) { for (var question in section.questions) { if (question.answer == null || question.photo == null) { return false; } } } return true; } void _submitForm() { if (!_isFormComplete()) { ScaffoldMessenger.of(context).showSnackBar( const SnackBar( content: Text('Mohon lengkapi semua pertanyaan dan foto'), backgroundColor: AppColor.error, ), ); return; } // Logic untuk submit form ScaffoldMessenger.of(context).showSnackBar( const SnackBar( content: Text('Daily tasks berhasil disimpan!'), backgroundColor: AppColor.success, ), ); } @override Widget build(BuildContext context) { return Scaffold( backgroundColor: AppColor.background, appBar: AppBar( title: const Text( 'Daily Tasks', style: TextStyle( color: AppColor.textWhite, fontWeight: FontWeight.bold, ), ), backgroundColor: AppColor.primary, elevation: 0, bottom: TabBar( controller: _tabController, indicatorColor: AppColor.textWhite, labelColor: AppColor.textWhite, unselectedLabelColor: AppColor.textWhite.withOpacity(0.7), labelStyle: const TextStyle(fontWeight: FontWeight.bold), tabs: taskSections .map((section) => Tab(text: section.title)) .toList(), ), ), body: Column( children: [ Expanded( child: TabBarView( controller: _tabController, children: taskSections.map((section) { return SingleChildScrollView( padding: const EdgeInsets.all(16), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ _buildSectionHeader(section.title), const SizedBox(height: 16), ...section.questions.map((question) { return _buildQuestionCard(question); }).toList(), ], ), ); }).toList(), ), ), _buildSubmitButton(), ], ), ); } Widget _buildSectionHeader(String title) { return Container( padding: const EdgeInsets.symmetric(vertical: 12, horizontal: 16), decoration: BoxDecoration( gradient: LinearGradient( colors: [AppColor.primary, AppColor.primaryLight], begin: Alignment.centerLeft, end: Alignment.centerRight, ), borderRadius: BorderRadius.circular(12), ), child: Row( children: [ Icon( title == "OPENING" ? Icons.wb_sunny : Icons.nightlight_round, color: AppColor.textWhite, size: 24, ), const SizedBox(width: 12), Text( '$title CHECKLIST', style: const TextStyle( color: AppColor.textWhite, fontSize: 18, fontWeight: FontWeight.bold, ), ), ], ), ); } Widget _buildQuestionCard(TaskQuestion question) { return Container( margin: const EdgeInsets.only(bottom: 16), decoration: BoxDecoration( color: AppColor.white, borderRadius: BorderRadius.circular(12), boxShadow: [ BoxShadow( color: AppColor.black.withOpacity(0.05), blurRadius: 8, offset: const Offset(0, 2), ), ], ), child: Padding( padding: const EdgeInsets.all(16), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( question.question, style: const TextStyle( fontSize: 16, fontWeight: FontWeight.w600, color: AppColor.textPrimary, ), ), const SizedBox(height: 16), // Yes/No buttons Row( children: [ Expanded( child: _buildAnswerButton( question: question, value: true, label: "YES", icon: Icons.check_circle, color: AppColor.success, ), ), const SizedBox(width: 12), Expanded( child: _buildAnswerButton( question: question, value: false, label: "NO", icon: Icons.cancel, color: AppColor.error, ), ), ], ), const SizedBox(height: 16), // Photo section _buildPhotoSection(question), ], ), ), ); } Widget _buildAnswerButton({ required TaskQuestion question, required bool value, required String label, required IconData icon, required Color color, }) { bool isSelected = question.answer == value; return GestureDetector( onTap: () { setState(() { question.answer = value; }); }, child: Container( padding: const EdgeInsets.symmetric(vertical: 12, horizontal: 16), decoration: BoxDecoration( color: isSelected ? color : AppColor.backgroundLight, border: Border.all( color: isSelected ? color : AppColor.border, width: 1.5, ), borderRadius: BorderRadius.circular(8), ), child: Row( mainAxisAlignment: MainAxisAlignment.center, children: [ Icon( icon, color: isSelected ? AppColor.white : AppColor.textSecondary, size: 20, ), const SizedBox(width: 8), Text( label, style: TextStyle( color: isSelected ? AppColor.white : AppColor.textSecondary, fontWeight: FontWeight.w600, ), ), ], ), ), ); } Widget _buildPhotoSection(TaskQuestion question) { return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( children: [ const Icon( Icons.camera_alt, color: AppColor.textSecondary, size: 18, ), const SizedBox(width: 8), const Text( 'Foto Bukti', style: TextStyle( fontSize: 14, fontWeight: FontWeight.w600, color: AppColor.textSecondary, ), ), const Text(' *', style: TextStyle(color: AppColor.error)), ], ), const SizedBox(height: 8), if (question.photo == null) GestureDetector( onTap: () => _pickImage(question), child: Container( height: 120, width: double.infinity, decoration: BoxDecoration( color: AppColor.borderLight, borderRadius: BorderRadius.circular(8), border: Border.all( color: AppColor.border, style: BorderStyle.solid, ), ), child: const Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Icon(Icons.add_a_photo, size: 32, color: AppColor.textLight), SizedBox(height: 8), Text( 'Tap untuk mengambil foto', style: TextStyle(color: AppColor.textLight, fontSize: 14), ), ], ), ), ) else Stack( children: [ ClipRRect( borderRadius: BorderRadius.circular(8), child: Image.file( question.photo!, height: 200, width: double.infinity, fit: BoxFit.cover, ), ), Positioned( top: 8, right: 8, child: GestureDetector( onTap: () => _removePhoto(question), child: Container( padding: const EdgeInsets.all(4), decoration: const BoxDecoration( color: AppColor.error, shape: BoxShape.circle, ), child: const Icon( Icons.close, color: AppColor.white, size: 16, ), ), ), ), ], ), ], ); } Widget _buildSubmitButton() { return Container( padding: const EdgeInsets.all(16), decoration: const BoxDecoration( color: AppColor.white, border: Border(top: BorderSide(color: AppColor.border, width: 1)), ), child: SizedBox( width: double.infinity, child: ElevatedButton( onPressed: _submitForm, style: ElevatedButton.styleFrom( backgroundColor: AppColor.primary, padding: const EdgeInsets.symmetric(vertical: 16), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(8), ), elevation: 2, ), child: const Text( 'SUBMIT DAILY TASKS', style: TextStyle( color: AppColor.textWhite, fontSize: 16, fontWeight: FontWeight.bold, ), ), ), ), ); } }