diff --git a/packages/chicken/lib/presentation/pages/sales_out_of_province_buyers/view.dart b/packages/chicken/lib/presentation/pages/sales_out_of_province_buyers/view.dart index 1ff77c3..f6bc1de 100644 --- a/packages/chicken/lib/presentation/pages/sales_out_of_province_buyers/view.dart +++ b/packages/chicken/lib/presentation/pages/sales_out_of_province_buyers/view.dart @@ -34,7 +34,7 @@ class SalesOutOfProvinceBuyersPage child: itemListWidget(item), secondChild: itemListExpandedWidget(item), labelColor: AppColor.blueLight, - labelIcon: Assets.vec.timerSvg.path, + labelIcon: Assets.vec.userRaduisSvg.path, ); }, controller.isExpandedList); }, @@ -121,6 +121,8 @@ class SalesOutOfProvinceBuyersPage Widget submitButtonWidget(bool isOnEdit) { return ObxValue((data) { return RElevated( + isFullWidth: true, + backgroundColor: AppColor.greenNormal, text: isOnEdit ? 'ویرایش' : 'ثبت', onPressed: data.value ? () async { @@ -137,7 +139,7 @@ class SalesOutOfProvinceBuyersPage Widget _provinceWidget() { return Obx(() { - return OverlayDropdownWidget( + return OverlayDropdownWidget2( items: controller.rootLogic.provinces, onChanged: (value) { controller.selectedProvince.value = value; @@ -223,27 +225,8 @@ class SalesOutOfProvinceBuyersPage spacing: 8, children: [ Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, + mainAxisAlignment: MainAxisAlignment.start, children: [ - GestureDetector( - onTap: () { - controller.setEditDataBuyer(item); - Get.bottomSheet( - addOrEditBuyerBottomSheet(true), - isScrollControlled: true, - ).whenComplete(() { - controller.resetSubmitForm(); - }); - }, - child: Assets.vec.editSvg.svg( - width: 20, - height: 20, - colorFilter: ColorFilter.mode( - AppColor.blueNormal, - BlendMode.srcIn, - ), - ), - ), Text( '${item.province}-${item.city}', @@ -265,6 +248,29 @@ class SalesOutOfProvinceBuyersPage title: 'وزن', value: '${item.requestsInfo?.totalWeight.separatedByComma}', ), + + Row( + mainAxisAlignment: MainAxisAlignment.center, + spacing: 16.w, + children: [ + RElevated( + text: 'ویرایش', + width: 150.w, + height: 40.h, + onPressed: () { + controller.setEditDataBuyer(item); + Get.bottomSheet( + addOrEditBuyerBottomSheet(true), + isScrollControlled: true, + ).whenComplete(() { + controller.resetSubmitForm(); + }); + }, + textStyle: AppFonts.yekan20.copyWith(color: Colors.white), + backgroundColor: AppColor.greenNormal, + ), + ], + ), ], ), ); diff --git a/packages/chicken/lib/presentation/pages/sales_out_of_province_sales_list/view.dart b/packages/chicken/lib/presentation/pages/sales_out_of_province_sales_list/view.dart index 14bfa20..8bcfeaa 100644 --- a/packages/chicken/lib/presentation/pages/sales_out_of_province_sales_list/view.dart +++ b/packages/chicken/lib/presentation/pages/sales_out_of_province_sales_list/view.dart @@ -34,7 +34,7 @@ class SalesOutOfProvinceSalesListPage onTap: () => controller.isExpandedList.toggle(index), index: index, child: itemListWidget(item), - secondChild: itemListExpandedWidget(item), + secondChild: itemListExpandedWidget(item, index), labelColor: AppColor.blueLight, labelIcon: Assets.vec.timerSvg.path, ); @@ -70,6 +70,7 @@ class SalesOutOfProvinceSalesListPage Expanded( flex: 5, child: Column( + mainAxisAlignment: MainAxisAlignment.center, children: [ Text( item.buyer?.fullname ?? 'N/A', @@ -90,6 +91,7 @@ class SalesOutOfProvinceSalesListPage Expanded( flex: 4, child: Column( + mainAxisAlignment: MainAxisAlignment.center, spacing: 8, children: [ Text( @@ -117,7 +119,7 @@ class SalesOutOfProvinceSalesListPage ); } - itemListExpandedWidget(StewardFreeSaleBar item) { + itemListExpandedWidget(StewardFreeSaleBar item, int index) { return Container( padding: EdgeInsets.fromLTRB(8, 12, 14, 12), @@ -129,51 +131,13 @@ class SalesOutOfProvinceSalesListPage spacing: 8, children: [ Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, + mainAxisAlignment: MainAxisAlignment.start, children: [ - GestureDetector( - onTap: () { - controller.setEditDataSales(item); - Get.bottomSheet( - addOrEditSaleBottomSheet(true), - isScrollControlled: true, - ).whenComplete(() { - controller.resetSubmitForm(); - }); - }, - child: Assets.vec.editSvg.svg( - width: 20, - height: 20, - colorFilter: ColorFilter.mode( - AppColor.blueNormal, - BlendMode.srcIn, - ), - ), - ), - Text( '${item.province}-${item.city}', textAlign: TextAlign.center, style: AppFonts.yekan16.copyWith(color: AppColor.greenDark), ), - - GestureDetector( - onTap: () { - buildDeleteDialog( - onConfirm: () => controller - .deleteStewardPurchaseOutOfProvince(item.key!), - onRefresh: () => controller.getOutProvinceSales(), - ); - }, - child: Assets.vec.trashSvg.svg( - width: 20, - height: 20, - colorFilter: ColorFilter.mode( - AppColor.error, - BlendMode.srcIn, - ), - ), - ), ], ), Container( @@ -201,6 +165,45 @@ class SalesOutOfProvinceSalesListPage title: 'وزن لاشه', value: '${item.weightOfCarcasses?.separatedByComma}', ), + + Row( + mainAxisAlignment: MainAxisAlignment.center, + spacing: 16.w, + children: [ + RElevated( + text: 'ویرایش', + width: 150.w, + height: 40.h, + onPressed: () { + controller.setEditDataSales(item); + Get.bottomSheet( + addOrEditSaleBottomSheet(true), + isScrollControlled: true, + ).whenComplete(() { + controller.resetSubmitForm(); + }); + }, + textStyle: AppFonts.yekan20.copyWith(color: Colors.white), + backgroundColor: AppColor.greenNormal, + ), + ROutlinedElevated( + text: 'حذف', + textStyle: AppFonts.yekan20.copyWith(color: AppColor.redNormal), + width: 150.w, + height: 40.h, + onPressed: () { + buildDeleteDialog( + onConfirm: () async { + controller.isExpandedList.remove(index); + controller.deleteStewardPurchaseOutOfProvince(item.key!); + }, + onRefresh: () => controller.getOutProvinceSales(), + ); + }, + borderColor: AppColor.redNormal, + ), + ], + ), ], ), ); @@ -277,6 +280,8 @@ class SalesOutOfProvinceSalesListPage Widget submitButtonWidget(bool isOnEdit) { return ObxValue((data) { return RElevated( + isFullWidth: true, + backgroundColor: AppColor.greenNormal, text: isOnEdit ? 'ویرایش' : 'ثبت', onPressed: data.value ? () async { diff --git a/packages/core/lib/presentation/widget/overlay_dropdown_widget/view.dart b/packages/core/lib/presentation/widget/overlay_dropdown_widget/view.dart index 1973c9f..a8c8a5f 100644 --- a/packages/core/lib/presentation/widget/overlay_dropdown_widget/view.dart +++ b/packages/core/lib/presentation/widget/overlay_dropdown_widget/view.dart @@ -139,3 +139,185 @@ class _OverlayDropdownState extends State> { ); } } + + +class OverlayDropdownWidget2 extends StatefulWidget { + final List items; + final T? selectedItem; + final T? initialValue; + final Widget Function(T item) itemBuilder; + final Widget Function(T? selected) labelBuilder; + final void Function(T selected)? onChanged; + final EdgeInsets? contentPadding; + final String Function(T item)? itemToString; + + const OverlayDropdownWidget2({ + super.key, + required this.items, + required this.itemBuilder, + required this.labelBuilder, + this.initialValue, + this.onChanged, + this.selectedItem, + this.contentPadding, + this.itemToString, + }); + + @override + State> createState() => _OverlayDropdownState2(); +} + +class _OverlayDropdownState2 extends State> { + final GlobalKey _key = GlobalKey(); + OverlayEntry? _overlayEntry; + final RxBool _isOpen = false.obs; + T? selectedItem; + + late TextEditingController _searchController; + late RxList _filteredItems; + + @override + void initState() { + super.initState(); + selectedItem = widget.selectedItem ?? widget.initialValue; + _searchController = TextEditingController(); + _filteredItems = RxList(widget.items); + } + + void _showOverlay() { + final renderBox = _key.currentContext!.findRenderObject() as RenderBox; + final size = renderBox.size; + final offset = renderBox.localToGlobal(Offset.zero); + final screenHeight = MediaQuery.of(context).size.height; + + final bool openUp = offset.dy + size.height + 300 > screenHeight; + + _searchController.clear(); + _filteredItems.value = widget.items; + + _overlayEntry = OverlayEntry( + builder: (_) => GestureDetector( + onTap: _removeOverlay, + behavior: HitTestBehavior.translucent, + child: Stack( + children: [ + Positioned( + left: offset.dx, + top: openUp ? offset.dy - 300 - 4 : offset.dy + size.height + 4, + width: size.width, + child: Material( + elevation: 4, + borderRadius: BorderRadius.circular(8), + child: Obx(() => Container( + decoration: BoxDecoration( + color: AppColor.bgLight, + border: Border.all(color: AppColor.darkGreyLight), + borderRadius: BorderRadius.circular(8), + ), + constraints: BoxConstraints(maxHeight: 300), + child: Column( + children: [ + Padding( + padding: const EdgeInsets.all(8), + child: TextField( + controller: _searchController, + decoration: const InputDecoration( + hintText: 'جستجو...', + isDense: true, + contentPadding: EdgeInsets.symmetric(horizontal: 12, vertical: 8), + border: OutlineInputBorder(), + ), + onChanged: (query) { + _filteredItems.value = widget.items + .where((item) => + widget.itemToString?.call(item).toLowerCase().contains(query.toLowerCase()) ?? + false) + .toList(); + }, + ), + ), + if (_filteredItems.isEmpty) + const Padding( + padding: EdgeInsets.all(16.0), + child: Text("نتیجه‌ای یافت نشد."), + ), + if (_filteredItems.isNotEmpty) + Expanded( + child: ListView( + shrinkWrap: true, + physics: const BouncingScrollPhysics(), + children: _filteredItems.map((item) { + return InkWell( + onTap: () { + widget.onChanged?.call(item); + setState(() { + selectedItem = item; + }); + _removeOverlay(); + }, + child: Padding( + padding: widget.contentPadding ?? + const EdgeInsets.symmetric(horizontal: 8, vertical: 4), + child: widget.itemBuilder(item), + ), + ); + }).toList(), + ), + ), + ], + ), + )), + ), + ), + ], + ), + ), + ); + + Overlay.of(context).insert(_overlayEntry!); + _isOpen.value = true; + } + + void _removeOverlay() { + _overlayEntry?.remove(); + _overlayEntry = null; + _isOpen.value = false; + } + + @override + void dispose() { + _removeOverlay(); + _searchController.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return IgnorePointer( + ignoring: widget.items.isEmpty, + child: GestureDetector( + key: _key, + onTap: () { + _isOpen.value ? _removeOverlay() : _showOverlay(); + }, + child: Container( + height: 40, + width: Get.width, + padding: const EdgeInsets.symmetric(horizontal: 12), + decoration: BoxDecoration( + color: widget.items.isEmpty ? Colors.grey.shade200 : AppColor.bgLight, + border: Border.all(color: AppColor.darkGreyLight), + borderRadius: BorderRadius.circular(8), + ), + child: Obx(() => Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + widget.labelBuilder(selectedItem), + Icon(_isOpen.value ? CupertinoIcons.chevron_up : CupertinoIcons.chevron_down, size: 14), + ], + )), + ), + ), + ); + } +}