import 'package:flutter/material.dart'; import 'package:font_awesome_flutter/font_awesome_flutter.dart'; import 'package:get/get.dart'; import 'package:marco/helpers/utils/mixins/ui_mixin.dart'; import 'package:marco/helpers/widgets/my_spacing.dart'; import 'package:marco/helpers/widgets/my_text.dart'; import 'package:marco/helpers/widgets/my_refresh_indicator.dart'; import 'package:marco/helpers/widgets/avatar.dart'; import 'package:marco/controller/project_controller.dart'; class ServiceProjectScreen extends StatefulWidget { const ServiceProjectScreen({super.key}); @override State createState() => _ServiceProjectScreenState(); } class _ServiceProjectScreenState extends State with UIMixin { final TextEditingController searchController = TextEditingController(); final RxList> allProjects = >[].obs; final RxList> filteredProjects = >[].obs; @override void initState() { super.initState(); _loadProjects(); } void _loadProjects() { final staticProjects = [ { "name": "Website Redesign", "description": "Revamping the corporate website UI/UX", "status": "In Progress", "manager": "John Doe", "email": "john@company.com", "phone": "+91 9876543210", "tags": ["UI", "Frontend", "High Priority"] }, { "name": "Mobile App Development", "description": "Cross-platform mobile app for customers", "status": "Completed", "manager": "Priya Sharma", "email": "priya@company.com", "phone": "+91 9812345678", "tags": ["Flutter", "Backend"] }, { "name": "Data Migration", "description": "Migrating legacy data to AWS", "status": "Pending", "manager": "Arun Mehta", "email": "arun@company.com", "phone": "+91 9999988888", "tags": ["Database", "Cloud"] }, ]; allProjects.assignAll(staticProjects); filteredProjects.assignAll(staticProjects); } void _filterProjects(String query) { if (query.isEmpty) { filteredProjects.assignAll(allProjects); } else { filteredProjects.assignAll(allProjects .where((p) => p["name"].toLowerCase().contains(query.toLowerCase()) || p["manager"].toLowerCase().contains(query.toLowerCase())) .toList()); } } Future _refreshProjects() async { await Future.delayed(const Duration(seconds: 1)); } Widget _buildProjectCard(Map project) { return Card( shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(5)), elevation: 3, shadowColor: Colors.grey.withOpacity(0.3), color: Colors.white, child: InkWell( borderRadius: BorderRadius.circular(5), onTap: () { // TODO: Navigate to Project Details screen }, child: Padding( padding: const EdgeInsets.all(12), child: Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ Avatar( firstName: project["name"].split(" ").first, lastName: project["name"].split(" ").length > 1 ? project["name"].split(" ").last : "", size: 40, ), MySpacing.width(12), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ MyText.titleSmall(project["name"], fontWeight: 600, overflow: TextOverflow.ellipsis), MyText.bodySmall(project["description"], color: Colors.grey[700], overflow: TextOverflow.ellipsis), MySpacing.height(6), Row( children: [ Icon(Icons.person_outline, size: 16, color: Colors.indigo), MySpacing.width(4), MyText.labelSmall(project["manager"], color: Colors.indigo), ], ), MySpacing.height(4), Row( children: [ Icon(Icons.email_outlined, size: 16, color: Colors.indigo), MySpacing.width(4), Expanded( child: MyText.labelSmall( project["email"], color: Colors.indigo, decoration: TextDecoration.underline, overflow: TextOverflow.ellipsis, ), ), ], ), MySpacing.height(4), Row( children: [ Icon(Icons.phone_outlined, size: 16, color: Colors.indigo), MySpacing.width(4), Expanded( child: MyText.labelSmall( project["phone"], color: Colors.indigo, decoration: TextDecoration.underline, overflow: TextOverflow.ellipsis, ), ), MySpacing.width(8), const FaIcon(FontAwesomeIcons.whatsapp, color: Colors.green, size: 20), ], ), MySpacing.height(6), Wrap( spacing: 6, runSpacing: 2, children: (project["tags"] as List) .map((tag) => Chip( label: Text(tag), backgroundColor: Colors.indigo.shade50, labelStyle: const TextStyle( color: Colors.indigo, fontSize: 12), visualDensity: VisualDensity.compact, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(5), ), )) .toList(), ), ], ), ), Column( children: [ Container( padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4), decoration: BoxDecoration( color: project["status"] == "Completed" ? Colors.green.shade100 : project["status"] == "In Progress" ? Colors.orange.shade100 : Colors.red.shade100, borderRadius: BorderRadius.circular(12), ), child: MyText.labelSmall( project["status"], fontWeight: 600, color: project["status"] == "Completed" ? Colors.green : project["status"] == "In Progress" ? Colors.orange : Colors.red, ), ), const SizedBox(height: 10), const Icon(Icons.arrow_forward_ios, color: Colors.grey, size: 20), ], ), ], ), ), ), ); } Widget _buildEmptyState() { return Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ const Icon(Icons.work_outline, size: 60, color: Colors.grey), MySpacing.height(18), MyText.titleMedium('No matching projects found.', fontWeight: 600, color: Colors.grey), MySpacing.height(10), MyText.bodySmall('Try adjusting your filters or refresh.', color: Colors.grey), ], ), ); } @override Widget build(BuildContext context) { return Scaffold( backgroundColor: const Color(0xFFF5F5F5), /// --- SAME APPBAR AS DETAILS SCREEN --- appBar: PreferredSize( preferredSize: const Size.fromHeight(72), child: AppBar( backgroundColor: const Color(0xFFF5F5F5), elevation: 0.5, automaticallyImplyLeading: false, titleSpacing: 0, title: Padding( padding: MySpacing.xy(16, 0), child: Row( crossAxisAlignment: CrossAxisAlignment.center, children: [ IconButton( icon: const Icon(Icons.arrow_back_ios_new, color: Colors.black, size: 20), onPressed: () => Get.offNamed('/dashboard'), ), MySpacing.width(8), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, mainAxisSize: MainAxisSize.min, children: [ MyText.titleLarge( 'Service Projects', fontWeight: 700, color: Colors.black, ), MySpacing.height(2), GetBuilder( builder: (projectController) { final projectName = projectController.selectedProject?.name ?? 'All Projects'; return Row( children: [ const Icon(Icons.work_outline, size: 14, color: Colors.grey), MySpacing.width(4), Expanded( child: MyText.bodySmall( projectName, fontWeight: 600, overflow: TextOverflow.ellipsis, color: Colors.grey[700], ), ), ], ); }, ), ], ), ), ], ), ), ), ), body: Column( children: [ /// --- SEARCH + FILTER BAR --- Padding( padding: MySpacing.xy(8, 8), child: Row( children: [ Expanded( child: SizedBox( height: 35, child: TextField( controller: searchController, onChanged: _filterProjects, decoration: InputDecoration( contentPadding: const EdgeInsets.symmetric(horizontal: 12), prefixIcon: const Icon(Icons.search, size: 20, color: Colors.grey), suffixIcon: ValueListenableBuilder( valueListenable: searchController, builder: (context, value, _) { if (value.text.isEmpty) { return const SizedBox.shrink(); } return IconButton( icon: const Icon(Icons.clear, size: 20, color: Colors.grey), onPressed: () { searchController.clear(); _filterProjects(''); }, ); }, ), hintText: 'Search projects...', filled: true, fillColor: Colors.white, border: OutlineInputBorder( borderRadius: BorderRadius.circular(5), borderSide: BorderSide(color: Colors.grey.shade300), ), enabledBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(5), borderSide: BorderSide(color: Colors.grey.shade300), ), ), ), ), ), MySpacing.width(8), Container( height: 35, width: 35, decoration: BoxDecoration( color: Colors.white, border: Border.all(color: Colors.grey.shade300), borderRadius: BorderRadius.circular(5), ), child: IconButton( icon: const Icon(Icons.tune, size: 20, color: Colors.black87), onPressed: () { // TODO: Open filter bottom sheet }, ), ), MySpacing.width(10), Container( height: 35, width: 35, decoration: BoxDecoration( color: Colors.white, border: Border.all(color: Colors.grey.shade300), borderRadius: BorderRadius.circular(5), ), child: PopupMenuButton( padding: EdgeInsets.zero, icon: const Icon(Icons.more_vert, size: 20, color: Colors.black87), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(5)), itemBuilder: (context) => [ const PopupMenuItem( enabled: false, height: 30, child: Text("Actions", style: TextStyle( fontWeight: FontWeight.bold, color: Colors.grey)), ), const PopupMenuItem( value: 1, child: Row( children: [ SizedBox(width: 10), Expanded(child: Text("Manage Projects")), Icon(Icons.chevron_right, size: 20, color: Colors.indigo), ], ), ), ], ), ), ], ), ), /// --- PROJECT LIST --- Expanded( child: Obx(() => MyRefreshIndicator( onRefresh: _refreshProjects, backgroundColor: Colors.indigo, color: Colors.white, child: filteredProjects.isEmpty ? _buildEmptyState() : ListView.separated( physics: const AlwaysScrollableScrollPhysics(), padding: MySpacing.only( left: 8, right: 8, top: 4, bottom: 80), itemCount: filteredProjects.length, separatorBuilder: (_, __) => MySpacing.height(12), itemBuilder: (_, index) => _buildProjectCard(filteredProjects[index]), ), )), ), ], ), ); } }