import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:on_field_work/controller/project_controller.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/utils/mixins/ui_mixin.dart'; class CustomAppBar extends StatefulWidget with UIMixin implements PreferredSizeWidget { final String title; final String? projectName; // If passed, show static text final VoidCallback? onBackPressed; final Color? backgroundColor; CustomAppBar({ super.key, required this.title, this.projectName, this.onBackPressed, this.backgroundColor, }); @override Size get preferredSize => const Size.fromHeight(72); @override State createState() => _CustomAppBarState(); } class _CustomAppBarState extends State with UIMixin { final ProjectController projectController = Get.find(); OverlayEntry? _overlayEntry; final LayerLink _layerLink = LayerLink(); void _toggleDropdown() { if (_overlayEntry == null) { _overlayEntry = _createOverlayEntry(); Overlay.of(context).insert(_overlayEntry!); } else { _overlayEntry?.remove(); _overlayEntry = null; } } OverlayEntry _createOverlayEntry() { final renderBox = context.findRenderObject() as RenderBox; final size = renderBox.size; final offset = renderBox.localToGlobal(Offset.zero); return OverlayEntry( builder: (context) => GestureDetector( onTap: () { _toggleDropdown(); }, behavior: HitTestBehavior.translucent, child: Stack( children: [ Positioned( left: offset.dx + 16, top: offset.dy + size.height, width: size.width - 32, child: Material( elevation: 4, borderRadius: BorderRadius.circular(5), child: Container( height: MediaQuery.of(context).size.height * 0.33, padding: const EdgeInsets.all(8), decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(5), ), child: Column( children: [ TextField( decoration: InputDecoration( hintText: "Search project...", isDense: true, prefixIcon: const Icon(Icons.search), border: OutlineInputBorder( borderRadius: BorderRadius.circular(5)), ), ), Expanded( child: ListView.builder( itemCount: projectController.projects.length, itemBuilder: (_, index) { final project = projectController.projects[index]; return RadioListTile( dense: true, value: project.id, groupValue: projectController.selectedProjectId.value, onChanged: (v) { if (v != null) { projectController.updateSelectedProject(v); _toggleDropdown(); } }, title: Text(project.name), ); }, ), ), ], ), ), ), ), ], ), ), ); } @override Widget build(BuildContext context) { final Color effectiveBackgroundColor = widget.backgroundColor ?? contentTheme.primary; const Color onPrimaryColor = Colors.white; final bool showDropdown = widget.projectName == null; return AppBar( backgroundColor: effectiveBackgroundColor, elevation: 0, automaticallyImplyLeading: false, titleSpacing: 0, shadowColor: Colors.transparent, leading: Padding( padding: MySpacing.only(left: 16), child: IconButton( icon: const Icon( Icons.arrow_back_ios_new, color: onPrimaryColor, size: 20, ), onPressed: widget.onBackPressed ?? () => Get.back(), padding: EdgeInsets.zero, constraints: const BoxConstraints(), ), ), title: Padding( padding: MySpacing.only(right: 16, left: 8), child: Row( children: [ Expanded( child: Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: [ MyText.titleLarge( widget.title, fontWeight: 800, color: onPrimaryColor, overflow: TextOverflow.ellipsis, maxLines: 1, ), MySpacing.height(3), showDropdown ? CompositedTransformTarget( link: _layerLink, child: GestureDetector( onTap: _toggleDropdown, child: Row( children: [ const Icon(Icons.folder_open, size: 14, color: onPrimaryColor), MySpacing.width(4), Flexible( child: Obx(() { final projectName = projectController .selectedProject?.name ?? 'Select Project'; return MyText.bodySmall( projectName, fontWeight: 500, color: onPrimaryColor.withOpacity(0.8), overflow: TextOverflow.ellipsis, maxLines: 1, ); }), ), MySpacing.width(2), const Icon(Icons.keyboard_arrow_down, size: 18, color: onPrimaryColor), ], ), ), ) : Row( children: [ const Icon(Icons.folder_open, size: 14, color: onPrimaryColor), MySpacing.width(4), Flexible( child: MyText.bodySmall( widget.projectName!, fontWeight: 500, color: onPrimaryColor.withOpacity(0.8), overflow: TextOverflow.ellipsis, maxLines: 1, ), ), ], ), ], ), ), ], ), ), actions: [ Padding( padding: MySpacing.only(right: 16), child: IconButton( icon: const Icon(Icons.home, color: onPrimaryColor, size: 24), onPressed: () => Get.offAllNamed('/dashboard'), ), ), ], ); } @override void dispose() { _overlayEntry?.remove(); super.dispose(); } }