import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:intl/intl.dart'; import 'package:on_field_work/helpers/utils/mixins/ui_mixin.dart'; import 'package:on_field_work/helpers/widgets/custom_app_bar.dart'; import 'package:on_field_work/helpers/widgets/pill_tab_bar.dart'; import 'package:on_field_work/helpers/utils/permission_constants.dart'; import 'package:on_field_work/helpers/utils/launcher_utils.dart'; import 'package:on_field_work/helpers/widgets/my_spacing.dart'; import 'package:on_field_work/helpers/widgets/my_text.dart'; import 'package:on_field_work/helpers/widgets/my_refresh_indicator.dart'; import 'package:on_field_work/controller/dynamicMenu/dynamic_menu_controller.dart'; import 'package:on_field_work/controller/infra_project/infra_project_screen_details_controller.dart'; import 'package:on_field_work/view/taskPlanning/daily_progress_report.dart'; import 'package:on_field_work/view/taskPlanning/daily_task_planning.dart'; class InfraProjectDetailsScreen extends StatefulWidget { final String projectId; final String? projectName; const InfraProjectDetailsScreen({ super.key, required this.projectId, this.projectName, }); @override State createState() => _InfraProjectDetailsScreenState(); } class _InfraProjectDetailsScreenState extends State with SingleTickerProviderStateMixin, UIMixin { late final TabController _tabController; final DynamicMenuController menuController = Get.find(); final List<_InfraTab> _tabs = []; @override void initState() { super.initState(); _prepareTabs(); } void _prepareTabs() { // Profile tab is always added _tabs.add(_InfraTab(name: "Profile", view: _buildProfileTab())); final allowedMenu = menuController.menuItems.where((m) => m.available); if (allowedMenu.any((m) => m.id == MenuItems.dailyTaskPlanning)) { _tabs.add( _InfraTab( name: "Task Planning", view: DailyTaskPlanningScreen(projectId: widget.projectId), ), ); } if (allowedMenu.any((m) => m.id == MenuItems.dailyProgressReport)) { _tabs.add( _InfraTab( name: "Task Progress", view: DailyProgressReportScreen(projectId: widget.projectId), ), ); } _tabController = TabController(length: _tabs.length, vsync: this); } @override void dispose() { _tabController.dispose(); super.dispose(); } Widget _buildProfileTab() { final controller = Get.put(InfraProjectDetailsController(projectId: widget.projectId)); return Obx(() { if (controller.isLoading.value) { return const Center(child: CircularProgressIndicator()); } if (controller.errorMessage.isNotEmpty) { return Center(child: Text(controller.errorMessage.value)); } final data = controller.projectDetails.value; if (data == null) { return const Center(child: Text("No project data available")); } return MyRefreshIndicator( onRefresh: controller.fetchProjectDetails, backgroundColor: Colors.indigo, color: Colors.white, child: SingleChildScrollView( physics: const AlwaysScrollableScrollPhysics(), padding: const EdgeInsets.all(12), child: Column( crossAxisAlignment: CrossAxisAlignment.center, children: [ _buildHeaderCard(data), MySpacing.height(16), _buildProjectInfoSection(data), if (data.promoter != null) MySpacing.height(12), if (data.promoter != null) _buildPromoterInfo(data.promoter!), if (data.pmc != null) MySpacing.height(12), if (data.pmc != null) _buildPMCInfo(data.pmc!), MySpacing.height(40), ], ), ), ); }); } Widget _buildHeaderCard(dynamic data) { return Card( elevation: 2, shadowColor: Colors.black12, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(5)), child: Padding( padding: const EdgeInsets.all(16), child: Row( children: [ const Icon(Icons.work_outline, size: 35), MySpacing.width(16), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ MyText.titleMedium(data.name ?? "-", fontWeight: 700), MySpacing.height(6), MyText.bodySmall(data.shortName ?? "-", fontWeight: 500), ], ), ), ], ), ), ); } Widget _buildProjectInfoSection(dynamic data) { return _buildSectionCard( title: 'Project Information', titleIcon: Icons.info_outline, children: [ _buildDetailRow( icon: Icons.location_on_outlined, label: 'Address', value: data.projectAddress ?? "-"), _buildDetailRow( icon: Icons.calendar_today_outlined, label: 'Start Date', value: data.startDate != null ? DateFormat('d/M/yyyy').format(data.startDate!) : "-"), _buildDetailRow( icon: Icons.calendar_today_outlined, label: 'End Date', value: data.endDate != null ? DateFormat('d/M/yyyy').format(data.endDate!) : "-"), _buildDetailRow( icon: Icons.flag_outlined, label: 'Status', value: data.projectStatus?.status ?? "-"), _buildDetailRow( icon: Icons.person_outline, label: 'Contact Person', value: data.contactPerson ?? "-", isActionable: true, onTap: () { if (data.contactPerson != null) { LauncherUtils.launchPhone(data.contactPerson!); } }), ], ); } Widget _buildPromoterInfo(dynamic promoter) { return _buildSectionCard( title: 'Promoter Information', titleIcon: Icons.business_outlined, children: [ _buildDetailRow( icon: Icons.person_outline, label: 'Name', value: promoter.name ?? "-"), _buildDetailRow( icon: Icons.phone_outlined, label: 'Contact', value: promoter.contactNumber ?? "-", isActionable: true, onTap: () => LauncherUtils.launchPhone(promoter.contactNumber ?? "")), _buildDetailRow( icon: Icons.email_outlined, label: 'Email', value: promoter.email ?? "-", isActionable: true, onTap: () => LauncherUtils.launchEmail(promoter.email ?? "")), ], ); } Widget _buildPMCInfo(dynamic pmc) { return _buildSectionCard( title: 'PMC Information', titleIcon: Icons.engineering_outlined, children: [ _buildDetailRow( icon: Icons.person_outline, label: 'Name', value: pmc.name ?? "-"), _buildDetailRow( icon: Icons.phone_outlined, label: 'Contact', value: pmc.contactNumber ?? "-", isActionable: true, onTap: () => LauncherUtils.launchPhone(pmc.contactNumber ?? "")), _buildDetailRow( icon: Icons.email_outlined, label: 'Email', value: pmc.email ?? "-", isActionable: true, onTap: () => LauncherUtils.launchEmail(pmc.email ?? "")), ], ); } Widget _buildDetailRow({ required IconData icon, required String label, required String value, VoidCallback? onTap, bool isActionable = false, }) { return Padding( padding: const EdgeInsets.symmetric(vertical: 8), child: InkWell( onTap: isActionable ? onTap : null, borderRadius: BorderRadius.circular(5), child: Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ Container( padding: const EdgeInsets.all(8), child: Icon(icon, size: 20)), MySpacing.width(16), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ MyText.bodySmall( label, fontSize: 12, color: Colors.grey[600], fontWeight: 500, ), MySpacing.height(4), MyText.bodyMedium( value, fontSize: 15, fontWeight: 500, color: isActionable ? Colors.blueAccent : Colors.black87, decoration: isActionable ? TextDecoration.underline : TextDecoration.none, ), ], ), ), ], ), ), ); } Widget _buildSectionCard({ required String title, required IconData titleIcon, required List children, }) { return Card( elevation: 2, shadowColor: Colors.black12, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(5)), child: Padding( padding: const EdgeInsets.all(16), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( children: [ Icon(titleIcon, size: 20), MySpacing.width(8), MyText.bodyLarge( title, fontSize: 16, fontWeight: 700, color: Colors.black87, ), ], ), MySpacing.height(8), const Divider(), ...children, ], ), ), ); } @override Widget build(BuildContext context) { final Color appBarColor = contentTheme.primary; return Scaffold( backgroundColor: const Color(0xFFF1F1F1), appBar: CustomAppBar( title: "Infra Projects", onBackPressed: () => Get.back(), projectName: widget.projectName, backgroundColor: appBarColor, ), body: Stack( children: [ Container( height: 50, decoration: BoxDecoration( gradient: LinearGradient( begin: Alignment.topCenter, end: Alignment.bottomCenter, colors: [appBarColor, appBarColor.withOpacity(0)], ), ), ), SafeArea( top: false, bottom: true, child: Column( children: [ PillTabBar( controller: _tabController, tabs: _tabs.map((e) => e.name).toList(), selectedColor: contentTheme.primary, unselectedColor: Colors.grey.shade600, indicatorColor: contentTheme.primary, ), Expanded( child: TabBarView( controller: _tabController, children: _tabs.map((e) => e.view).toList(), ), ), ], ), ), ], ), ); } } /// INTERNAL MODEL class _InfraTab { final String name; final Widget view; _InfraTab({required this.name, required this.view}); }