feat : new UI

This commit is contained in:
2025-06-30 16:18:12 +03:30
parent d76a2ab579
commit e8df5721cb
22 changed files with 480 additions and 235 deletions

View File

@@ -1,6 +1,17 @@
import 'package:get/get.dart';
import 'package:rasadyar_chicken/chicken.dart';
import 'package:rasadyar_core/core.dart';
class BuyLogic extends GetxController {
RootLogic rootLogic = Get.find<RootLogic>();
late List<String> routesName;
@override
void onInit() {
super.onInit();
routesName = [...rootLogic.routesName, 'خرید'].toList();
}
@override
void onReady() {
// TODO: implement onReady

View File

@@ -1,6 +1,7 @@
import 'package:flutter/material.dart';
import 'package:rasadyar_chicken/presentation/routes/routes.dart';
import 'package:rasadyar_chicken/presentation/widget/app_bar.dart';
import 'package:rasadyar_chicken/presentation/widget/base_page.dart';
import 'package:rasadyar_chicken/presentation/widget/base_page/view.dart';
import 'package:rasadyar_chicken/presentation/widget/sale_buy_card_item.dart';
import 'package:rasadyar_core/core.dart';
@@ -12,8 +13,8 @@ class BuyPage extends GetView<BuyLogic> {
@override
Widget build(BuildContext context) {
return BasePage(
routes: ['رصدطیور', 'خرید'],
appBar: chickenAppBar(isBase: true),
routes: controller.routesName,
isBase: true,
widgets: [
Row(
mainAxisAlignment: MainAxisAlignment.center,
@@ -22,8 +23,20 @@ class BuyPage extends GetView<BuyLogic> {
alignment: WrapAlignment.center,
spacing: 14.w,
children: [
saleOrBuyItemCard(title: 'داخل استان', iconPath: Assets.vec.cubeSvg.path, onTap: () {}),
saleOrBuyItemCard(title: 'خارج استان', iconPath: Assets.vec.truckFastSvg.path, onTap: () {}),
saleOrBuyItemCard(
title: 'داخل استان',
iconPath: Assets.vec.cubeSvg.path,
onTap: () {
Get.toNamed(ChickenRoutes.buysInProvince, id: 0);
},
),
saleOrBuyItemCard(
title: 'خارج استان',
iconPath: Assets.vec.truckFastSvg.path,
onTap: () {
Get.toNamed(ChickenRoutes.buysOutOfProvince, id: 0);
},
),
],
),
],

View File

@@ -4,20 +4,23 @@ import 'package:rasadyar_chicken/data/models/request/create_steward_free_bar/cre
import 'package:rasadyar_chicken/data/models/response/iran_province_city/iran_province_city_model.dart';
import 'package:rasadyar_chicken/data/models/response/roles_products/roles_products.dart';
import 'package:rasadyar_chicken/data/models/response/steward_free_bar/steward_free_bar.dart';
import 'package:rasadyar_chicken/presentation/pages/out_of_province/logic.dart';
import 'package:rasadyar_chicken/presentation/pages/buy/logic.dart';
import 'package:rasadyar_chicken/presentation/pages/root/logic.dart';
import 'package:rasadyar_chicken/presentation/pages/sale/logic.dart';
import 'package:rasadyar_core/core.dart';
class BuysOutOfProvinceLogic extends GetxController {
class BuyOutOfProvinceLogic extends GetxController {
RxBool isExpanded = false.obs;
RxBool isSubmitButtonEnabled = false.obs;
RxList<int> isExpandedList = <int>[].obs;
RxBool searchIsSelected = false.obs;
late List<String> routesName;
//TODO add this to Di
ImagePicker imagePicker = ImagePicker();
Rx<Resource<List<StewardFreeBar>>> purchaseOutOfProvinceList = Resource<List<StewardFreeBar>>.loading().obs;
Rx<Resource<List<StewardFreeBar>>> purchaseOutOfProvinceList =
Resource<List<StewardFreeBar>>.loading().obs;
Rxn<ProductModel> selectedProduct = Rxn();
RxList<IranProvinceCityModel> cites = <IranProvinceCityModel>[].obs;
@@ -29,7 +32,9 @@ class BuysOutOfProvinceLogic extends GetxController {
RootLogic get rootLogic => Get.find<RootLogic>();
OutOfProvinceLogic get outOfTheProvinceLogic => Get.find<OutOfProvinceLogic>();
BuyLogic get buyLogic => Get.find<BuyLogic>();
SaleLogic get outOfTheProvinceLogic => Get.find<SaleLogic>();
GlobalKey<FormState> formKey = GlobalKey<FormState>();
TextEditingController sellerNameController = TextEditingController();
@@ -40,23 +45,22 @@ class BuysOutOfProvinceLogic extends GetxController {
Rx<Jalali> toDateFilter = Jalali.now().obs;
RxnString searchedValue = RxnString();
@override
void onInit() {
super.onInit();
routesName = [...buyLogic.routesName, 'خارج استان'].toList();
}
@override
void onReady() {
super.onReady();
getStewardPurchaseOutOfProvince();
selectedProvince.listen((p0) => getCites());
tLog(selectedProduct.value);
outOfTheProvinceLogic.rolesProductsModel.listen((lists) {
selectedProduct.value = lists.first;
},);
tLog(selectedProduct.value);
setupListeners();
debounce(searchedValue, (callback) => getStewardPurchaseOutOfProvince(), time: Duration(milliseconds: 2000));
ever(searchIsSelected, (data) {
if (data == false) {
searchedValue.value = null;
}
});
setupListeners();
}
@override
@@ -69,7 +73,13 @@ class BuysOutOfProvinceLogic extends GetxController {
super.onClose();
}
void setSearchValue(String? data) {
searchedValue.value = data?.trim();
getStewardPurchaseOutOfProvince();
}
Future<void> getStewardPurchaseOutOfProvince() async {
purchaseOutOfProvinceList.value = Resource<List<StewardFreeBar>>.loading();
await safeCall(
call: () => rootLogic.chickenRepository.getStewardPurchasesOutSideOfTheProvince(
token: rootLogic.tokenService.accessToken.value!,
@@ -83,7 +93,8 @@ class BuysOutOfProvinceLogic extends GetxController {
toDate: toDateFilter.value.toDateTime(),
),
),
onSuccess: (res) {
onSuccess: (res) async {
await Future.delayed(Duration(milliseconds: 500));
if ((res?.count ?? 0) == 0) {
purchaseOutOfProvinceList.value = Resource<List<StewardFreeBar>>.empty();
} else {
@@ -95,7 +106,8 @@ class BuysOutOfProvinceLogic extends GetxController {
Future<void> getCites() async {
await safeCall(
call: () => rootLogic.chickenRepository.getCity(provinceName: selectedProvince.value?.name ?? ''),
call: () =>
rootLogic.chickenRepository.getCity(provinceName: selectedProvince.value?.name ?? ''),
onSuccess: (result) {
if (result != null && result.isNotEmpty) {
cites.value = result;
@@ -123,12 +135,12 @@ class BuysOutOfProvinceLogic extends GetxController {
void checkFormValid() {
isSubmitButtonEnabled.value =
sellerNameController.text.isNotEmpty &&
sellerPhoneController.text.isNotEmpty &&
carcassWeightController.text.isNotEmpty &&
selectedProvince.value != null &&
selectedCity.value != null &&
selectedProduct.value != null &&
selectedImage.value != null;
sellerPhoneController.text.isNotEmpty &&
carcassWeightController.text.isNotEmpty &&
selectedProvince.value != null &&
selectedCity.value != null &&
selectedProduct.value != null &&
selectedImage.value != null;
}
Future<bool> createStewardPurchaseOutOfProvince() async {
@@ -184,7 +196,7 @@ class BuysOutOfProvinceLogic extends GetxController {
selectedProvince.value = IranProvinceCityModel(name: item.province);
selectedCity.value = IranProvinceCityModel(name: item.city);
selectedProduct.value = outOfTheProvinceLogic.rolesProductsModel.firstWhere(
(element) => element.key == item.product!.key,
(element) => element.key == item.product!.key,
);
isSubmitButtonEnabled.value = true;
}

View File

@@ -1,4 +1,3 @@
import 'dart:io';
import 'package:flutter/cupertino.dart';
@@ -7,70 +6,38 @@ import 'package:flutter/services.dart';
import 'package:rasadyar_chicken/data/models/response/iran_province_city/iran_province_city_model.dart';
import 'package:rasadyar_chicken/data/models/response/roles_products/roles_products.dart';
import 'package:rasadyar_chicken/data/models/response/steward_free_bar/steward_free_bar.dart';
import 'package:rasadyar_chicken/presentation/widget/base_page/view.dart';
import 'package:rasadyar_core/core.dart';
import 'logic.dart';
class BuysOutOfProvincePage extends GetView<BuysOutOfProvinceLogic> {
const BuysOutOfProvincePage({super.key});
class BuyOutOfProvincePage extends GetView<BuyOutOfProvinceLogic> {
const BuyOutOfProvincePage({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: RAppBar(
titleTextStyle: AppFonts.yekan16Bold.copyWith(color: Colors.white),
centerTitle: true,
hasBack: true,
onBackPressed: () {
Get.back(id: 1);
},
leadingWidth: 155,
leading: Row(
mainAxisSize: MainAxisSize.min,
spacing: 6,
children: [
Assets.vec.chickenSvg.svg(
width: 24,
height: 24,
colorFilter: const ColorFilter.mode(Colors.white, BlendMode.srcIn),
return BasePage(
routes: controller.routesName,
onBackPressed: () => Get.back(id: 0),
onSearchChanged: (data) => controller.setSearchValue(data),
filteringWidget: filterBottomSheet(),
widgets: [
ObxValue((data) {
return RPaginatedListView(
listType: ListType.separated,
resource: data.value,
padding: EdgeInsets.fromLTRB(8, 8, 18, 80),
itemBuilder: (context, index) => saleListItem(
expandList: controller.isExpandedList,
index: index,
item: data.value.data![index],
),
Text('رصدطیور', style: AppFonts.yekan16Bold.copyWith(color: Colors.white)),
],
),
additionalActions: [
GestureDetector(
onTap: () {
controller.searchIsSelected.value = !controller.searchIsSelected.value;
},
child: Assets.vec.searchSvg.svg(
width: 24,
height: 24,
colorFilter: const ColorFilter.mode(Colors.white, BlendMode.srcIn),
),
),
SizedBox(width: 8),
GestureDetector(
onTap: () {
Get.bottomSheet(filterBottomSheet());
},
child: Assets.vec.filterOutlineSvg.svg(
width: 20,
height: 20,
colorFilter: const ColorFilter.mode(Colors.white, BlendMode.srcIn),
),
),
SizedBox(width: 8),
],
),
body: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
routePageWidget(),
_buildSearchWidget(),
Expanded(child: saleListWidget()),
],
),
itemCount: data.value.data?.length ?? 0,
separatorBuilder: (context, index) => SizedBox(height: 8.h),
onLoadMore: () async {},
);
}, controller.purchaseOutOfProvinceList),
],
floatingActionButton: RFab.add(
onPressed: () {
Get.bottomSheet(addPurchasedInformationBottomSheet(), isScrollControlled: true);
@@ -93,7 +60,11 @@ class BuysOutOfProvincePage extends GetView<BuysOutOfProvinceLogic> {
padding: EdgeInsets.fromLTRB(8, 8, 18, 80),
itemBuilder: (context, index) {
return ObxValue(
(expandList) => saleListItem(expandList: expandList, index: index, item: data.value.data![index]),
(expandList) => saleListItem(
expandList: expandList,
index: index,
item: data.value.data![index],
),
controller.isExpandedList,
);
},
@@ -115,11 +86,18 @@ class BuysOutOfProvincePage extends GetView<BuysOutOfProvinceLogic> {
Widget emptyWidget() {
return Center(
child: Text('داده ای دریافت نشد!', style: AppFonts.yekan16.copyWith(color: AppColor.darkGreyDarkHover)),
child: Text(
'داده ای دریافت نشد!',
style: AppFonts.yekan16.copyWith(color: AppColor.darkGreyDarkHover),
),
);
}
GestureDetector saleListItem({required RxList<int> expandList, required int index, required StewardFreeBar item}) {
GestureDetector saleListItem({
required RxList<int> expandList,
required int index,
required StewardFreeBar item,
}) {
return GestureDetector(
onTap: () {
if (expandList.contains(index)) {
@@ -169,7 +147,7 @@ class BuysOutOfProvincePage extends GetView<BuysOutOfProvinceLogic> {
style: AppFonts.yekan12.copyWith(color: AppColor.blueNormal),
),
),
SizedBox(width: 8,),
SizedBox(width: 8),
Expanded(
flex: 2,
child: Column(
@@ -180,11 +158,18 @@ class BuysOutOfProvincePage extends GetView<BuysOutOfProvinceLogic> {
style: AppFonts.yekan12.copyWith(color: AppColor.blueNormal),
),
SizedBox(height: 2,),
SizedBox(height: 2),
Visibility(
visible: item.product?.name?.contains('مرغ گرم') ?? false,
child: Assets.vec.hotChickenSvg.svg(width: 24,height: 24, colorFilter: ColorFilter.mode(AppColor.blueNormal, BlendMode.srcIn))),
visible: item.product?.name?.contains('مرغ گرم') ?? false,
child: Assets.vec.hotChickenSvg.svg(
width: 24,
height: 24,
colorFilter: ColorFilter.mode(
AppColor.blueNormal,
BlendMode.srcIn,
),
),
),
],
),
),
@@ -204,7 +189,10 @@ class BuysOutOfProvincePage extends GetView<BuysOutOfProvinceLogic> {
secondChild: Container(
padding: EdgeInsets.fromLTRB(8, 12, 14, 12),
decoration: BoxDecoration(color: Colors.white, borderRadius: BorderRadius.circular(8)),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(8),
),
child: Column(
spacing: 8,
children: [
@@ -237,7 +225,8 @@ class BuysOutOfProvincePage extends GetView<BuysOutOfProvinceLogic> {
GestureDetector(
onTap: () {
buildDeleteDialog(
onConfirm: () => controller.deleteStewardPurchaseOutOfProvince(item.key!),
onConfirm: () =>
controller.deleteStewardPurchaseOutOfProvince(item.key!),
);
},
child: Assets.vec.trashSvg.svg(
@@ -261,9 +250,15 @@ class BuysOutOfProvincePage extends GetView<BuysOutOfProvinceLogic> {
child: buildRow('تاریخ', item.date?.formattedJalaliDateYHMS ?? 'N/A'),
),
buildRow('مشخصات فروشنده', '${item.killHouseName} - ${item.killHouseMobile ?? 'N/A'}'),
buildRow('محصول', item.product?.name ??'N/A'),
buildRow('وزن خریداری شده', '${item.weightOfCarcasses?.separatedByComma} کیلوگرم'),
buildRow(
'مشخصات فروشنده',
'${item.killHouseName} - ${item.killHouseMobile ?? 'N/A'}',
),
buildRow('محصول', item.product?.name ?? 'N/A'),
buildRow(
'وزن خریداری شده',
'${item.weightOfCarcasses?.separatedByComma} کیلوگرم',
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
@@ -277,7 +272,9 @@ class BuysOutOfProvincePage extends GetView<BuysOutOfProvinceLogic> {
children: [
Text(
'بارنامه',
style: AppFonts.yekan16Bold.copyWith(color: AppColor.darkGreyDarkHover),
style: AppFonts.yekan16Bold.copyWith(
color: AppColor.darkGreyDarkHover,
),
),
Image.network(
@@ -299,7 +296,10 @@ class BuysOutOfProvincePage extends GetView<BuysOutOfProvinceLogic> {
),
);
},
child: Text('مشاهده بارنامه', style: AppFonts.yekan14.copyWith(color: AppColor.blueNormal)),
child: Text(
'مشاهده بارنامه',
style: AppFonts.yekan14.copyWith(color: AppColor.blueNormal),
),
),
Icon(CupertinoIcons.chevron_up, size: 12),
],
@@ -307,7 +307,9 @@ class BuysOutOfProvincePage extends GetView<BuysOutOfProvinceLogic> {
],
),
),
crossFadeState: expandList.contains(index) ? CrossFadeState.showSecond : CrossFadeState.showFirst,
crossFadeState: expandList.contains(index)
? CrossFadeState.showSecond
: CrossFadeState.showFirst,
duration: Duration(milliseconds: 300),
),
),
@@ -324,7 +326,10 @@ class BuysOutOfProvincePage extends GetView<BuysOutOfProvinceLogic> {
border: Border.all(width: 0.50, color: AppColor.greenDarkActive),
),
alignment: Alignment.center,
child: Text((index + 1).toString(), style: AppFonts.yekan12.copyWith(color: Colors.black)),
child: Text(
(index + 1).toString(),
style: AppFonts.yekan12.copyWith(color: Colors.black),
),
),
),
],
@@ -333,37 +338,6 @@ class BuysOutOfProvincePage extends GetView<BuysOutOfProvinceLogic> {
);
}
Row routePageWidget() {
return Row(
children: [
SizedBox(width: 8),
RichText(
text: TextSpan(
style: AppFonts.yekan14.copyWith(color: AppColor.blueNormal),
children: [
WidgetSpan(
child: Row(
children: [
Assets.vec.cubeSearchSvg.svg(
width: 24,
height: 24,
colorFilter: const ColorFilter.mode(AppColor.blueNormal, BlendMode.srcIn),
),
SizedBox(width: 6),
],
),
),
TextSpan(text: 'خارج استان'),
TextSpan(text: '/'),
TextSpan(text: 'خرید'),
],
),
),
],
);
}
Widget buildRow(String title, String value) {
return Padding(
padding: const EdgeInsets.symmetric(vertical: 4.0),
@@ -438,7 +412,10 @@ class BuysOutOfProvincePage extends GetView<BuysOutOfProvinceLogic> {
label: 'وزن لاشه',
keyboardType: TextInputType.number,
borderColor: AppColor.darkGreyLight,
inputFormatters: [FilteringTextInputFormatter.digitsOnly, SeparatorInputFormatter()],
inputFormatters: [
FilteringTextInputFormatter.digitsOnly,
SeparatorInputFormatter(),
],
),
_imageCarcasesWidget(isOnEdit),
submitButtonWidget(isOnEdit),
@@ -456,11 +433,11 @@ class BuysOutOfProvincePage extends GetView<BuysOutOfProvinceLogic> {
text: isOnEdit ? 'ویرایش' : 'ثبت خرید',
onPressed: data.value
? () async {
var res = await controller.createStewardPurchaseOutOfProvince();
if (res) {
Get.back();
}
}
var res = await controller.createStewardPurchaseOutOfProvince();
if (res) {
Get.back();
}
}
: null,
height: 40,
);
@@ -526,7 +503,10 @@ class BuysOutOfProvincePage extends GetView<BuysOutOfProvinceLogic> {
child: ObxValue((data) {
return Container(
width: Get.width,
decoration: BoxDecoration(color: AppColor.lightGreyNormal, borderRadius: BorderRadius.circular(8)),
decoration: BoxDecoration(
color: AppColor.lightGreyNormal,
borderRadius: BorderRadius.circular(8),
),
child: Center(
child: isOnEdit
? Image.network(controller.editImageUrl.value ?? '')
@@ -544,7 +524,10 @@ class BuysOutOfProvincePage extends GetView<BuysOutOfProvinceLogic> {
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Text('تصویر بار', style: AppFonts.yekan16Bold.copyWith(color: AppColor.blueNormal)),
Text(
'تصویر بار',
style: AppFonts.yekan16Bold.copyWith(color: AppColor.blueNormal),
),
Spacer(),
GestureDetector(
onTap: () async {
@@ -612,7 +595,10 @@ class BuysOutOfProvincePage extends GetView<BuysOutOfProvinceLogic> {
title: 'حذف خرید',
middleText: 'آیا از حذف این خرید مطمئن هستید؟',
confirm: ElevatedButton(
style: ElevatedButton.styleFrom(backgroundColor: AppColor.error, foregroundColor: Colors.white),
style: ElevatedButton.styleFrom(
backgroundColor: AppColor.error,
foregroundColor: Colors.white,
),
onPressed: () async {
await onConfirm();
Get.back();
@@ -692,7 +678,10 @@ class BuysOutOfProvincePage extends GetView<BuysOutOfProvinceLogic> {
height: 24,
colorFilter: const ColorFilter.mode(AppColor.blueNormal, BlendMode.srcIn),
),
Text(isFrom ? 'از' : 'تا', style: AppFonts.yekan16.copyWith(color: AppColor.blueNormal)),
Text(
isFrom ? 'از' : 'تا',
style: AppFonts.yekan16.copyWith(color: AppColor.blueNormal),
),
Expanded(
child: ObxValue((data) {
return Text(
@@ -763,7 +752,7 @@ class BuysOutOfProvincePage extends GetView<BuysOutOfProvinceLogic> {
);
}
ObxValue<RxBool> _buildSearchWidget() {
/*ObxValue<RxBool> _buildSearchWidget() {
return ObxValue((data) {
return AnimatedContainer(
duration: Duration(milliseconds: 300),
@@ -793,5 +782,5 @@ class BuysOutOfProvincePage extends GetView<BuysOutOfProvinceLogic> {
),
);
}, controller.searchIsSelected);
}
}*/
}

View File

@@ -121,6 +121,8 @@ class HomePage extends GetView<HomeLogic> {
Icon(CupertinoIcons.chevron_down, size: 18),
],
),
_todayShipmentWidget(),
_inventoryWidget(),
],
),
),

View File

@@ -8,8 +8,8 @@ import 'package:rasadyar_chicken/data/repositories/chicken_repository.dart';
import 'package:rasadyar_chicken/data/repositories/chicken_repository_imp.dart';
import 'package:rasadyar_chicken/presentation/pages/buy/view.dart';
import 'package:rasadyar_chicken/presentation/pages/home/view.dart';
import 'package:rasadyar_chicken/presentation/pages/out_of_province/view.dart';
import 'package:rasadyar_chicken/presentation/pages/sales_in_province/view.dart';
import 'package:rasadyar_chicken/presentation/pages/sale/view.dart';
import 'package:rasadyar_chicken/presentation/routes/routes.dart';
import 'package:rasadyar_chicken/presentation/utils/utils.dart';
import 'package:rasadyar_core/core.dart';
@@ -19,12 +19,20 @@ class RootLogic extends GetxController {
RxInt currentPage = 2.obs;
List<Widget> pages = [
BuyPage(),
OutOfProvincePage(),
SalePage(),
HomePage(),
Container(color: Colors.blue),
Container(color: Colors.amber),
];
final defaultRoutes = <int, String>{
0: ChickenRoutes.buy,
1: ChickenRoutes.sale,
};
List<String> routesName = ['رصدطیور'];
late DioRemote dioRemote;
var tokenService = Get.find<TokenStorageService>();
late ChickenRepository chickenRepository;

View File

@@ -15,14 +15,21 @@ class RootPage extends GetView<RootLogic> {
children: [
Navigator(
key: Get.nestedKey(0),
onGenerateRoute: (settings) => GetPageRoute(page: () => controller.pages[0]),
onGenerateRoute: (settings) {
final page = ChickenPages.pages.firstWhere(
(e) => e.name == settings.name,
orElse: () => ChickenPages.pages.firstWhere((e) => e.name == ChickenRoutes.buy),
);
return buildRouteFromGetPage(page);
},
),
Navigator(
key: Get.nestedKey(1),
onGenerateRoute: (settings) {
final page = ChickenPages.pages.firstWhere(
(e) => e.name == settings.name,
orElse: () => ChickenPages.pages.firstWhere((e) => e.name == ChickenRoutes.outOfProvince),
orElse: () => ChickenPages.pages.firstWhere((e) => e.name == ChickenRoutes.sale),
);
return buildRouteFromGetPage(page);

View File

@@ -8,7 +8,7 @@ import 'package:rasadyar_chicken/data/models/response/steward_free_bar_dashboard
import 'package:rasadyar_chicken/presentation/pages/root/logic.dart';
import 'package:rasadyar_core/core.dart';
class OutOfProvinceLogic extends GetxController {
class SaleLogic extends GetxController {
var rootLogic = Get.find<RootLogic>();
Rxn<List<AllocatedMadeModel>?> allocatedMadeModel =
Rxn<List<AllocatedMadeModel>?>();

View File

@@ -5,8 +5,8 @@ import 'package:rasadyar_core/core.dart';
import 'logic.dart';
class OutOfProvincePage extends GetView<OutOfProvinceLogic> {
OutOfProvincePage({super.key});
class SalePage extends GetView<SaleLogic> {
SalePage({super.key});
@override
Widget build(BuildContext context) {

View File

@@ -6,8 +6,8 @@ import 'package:rasadyar_chicken/data/models/response/iran_province_city/iran_pr
import 'package:rasadyar_chicken/data/models/response/out_province_carcasses_buyer/out_province_carcasses_buyer.dart';
import 'package:rasadyar_chicken/data/models/response/roles_products/roles_products.dart';
import 'package:rasadyar_chicken/data/models/response/steward_free_sale_bar/steward_free_sale_bar.dart';
import 'package:rasadyar_chicken/presentation/pages/out_of_province/logic.dart';
import 'package:rasadyar_chicken/presentation/pages/root/logic.dart';
import 'package:rasadyar_chicken/presentation/pages/sale/logic.dart';
import 'package:rasadyar_core/core.dart';
class SalesOutOfProvinceLogic extends GetxController {
@@ -36,8 +36,8 @@ class SalesOutOfProvinceLogic extends GetxController {
RootLogic get rootLogic => Get.find<RootLogic>();
OutOfProvinceLogic get outOfTheProvinceLogic =>
Get.find<OutOfProvinceLogic>();
SaleLogic get outOfTheProvinceLogic =>
Get.find<SaleLogic>();
GlobalKey<FormState> formKey = GlobalKey<FormState>();
TextEditingController buyerNameController = TextEditingController();

View File

@@ -16,10 +16,7 @@ class BuyersPage extends GetView<SalesOutOfProvinceLogic> {
return Scaffold(
body: Column(
children: [
searchWidget(controller.searchIsSelected, (data) {
controller.searchedValue.value = data;
controller.getOutProvinceCarcassesBuyer();
}),
buyerListWidget(),
],

View File

@@ -1,21 +1,23 @@
import 'package:rasadyar_auth/auth.dart';
import 'package:rasadyar_chicken/presentation/pages/buy/logic.dart';
import 'package:rasadyar_chicken/presentation/pages/buy/view.dart';
import 'package:rasadyar_chicken/presentation/pages/buys_out_of_province/logic.dart';
import 'package:rasadyar_chicken/presentation/pages/buys_out_of_province/view.dart';
import 'package:rasadyar_chicken/presentation/pages/entering_the_warehouse/logic.dart';
import 'package:rasadyar_chicken/presentation/pages/entering_the_warehouse/view.dart';
import 'package:rasadyar_chicken/presentation/pages/buy_in_province/logic.dart';
import 'package:rasadyar_chicken/presentation/pages/buy_in_province/view.dart';
import 'package:rasadyar_chicken/presentation/pages/buy_out_of_province/logic.dart';
import 'package:rasadyar_chicken/presentation/pages/buy_out_of_province/view.dart';
import 'package:rasadyar_chicken/presentation/pages/home/logic.dart';
import 'package:rasadyar_chicken/presentation/pages/home/view.dart';
import 'package:rasadyar_chicken/presentation/pages/out_of_province/logic.dart';
import 'package:rasadyar_chicken/presentation/pages/out_of_province/view.dart';
import 'package:rasadyar_chicken/presentation/pages/root/logic.dart';
import 'package:rasadyar_chicken/presentation/pages/root/view.dart';
import 'package:rasadyar_chicken/presentation/pages/sale/logic.dart';
import 'package:rasadyar_chicken/presentation/pages/sale/view.dart';
import 'package:rasadyar_chicken/presentation/pages/sales_in_province/logic.dart';
import 'package:rasadyar_chicken/presentation/pages/sales_in_province/view.dart';
import 'package:rasadyar_chicken/presentation/pages/sales_out_of_province/logic.dart';
import 'package:rasadyar_chicken/presentation/pages/sales_out_of_province/view.dart';
import 'package:rasadyar_chicken/presentation/routes/routes.dart';
import 'package:rasadyar_chicken/presentation/widget/base_page/logic.dart';
import 'package:rasadyar_chicken/presentation/widget/search/logic.dart';
import 'package:rasadyar_core/core.dart';
sealed class ChickenPages {
@@ -30,9 +32,11 @@ sealed class ChickenPages {
Get.put(RootLogic());
Get.lazyPut(() => HomeLogic());
Get.lazyPut(() => BuyLogic());
Get.lazyPut(() => SalesInProvinceLogic());
Get.lazyPut(() => OutOfProvinceLogic());
Get.lazyPut(() => SalesOutOfProvinceLogic());
Get.lazyPut(() => SaleLogic());
Get.lazyPut(() => BaseLogic());
/*Get.lazyPut(() => SalesInProvinceLogic());
Get.lazyPut(() => SalesOutOfProvinceLogic());*/
}),
),
@@ -43,10 +47,11 @@ sealed class ChickenPages {
binding: BindingsBuilder(() {
Get.put(HomeLogic());
Get.put(RootLogic());
Get.lazyPut(() => BaseLogic());
}),
),
GetPage(
/* GetPage(
name: ChickenRoutes.enteringTheWarehouse,
page: () => EnteringTheWarehousePage(),
middlewares: [AuthMiddleware()],
@@ -54,29 +59,20 @@ sealed class ChickenPages {
Get.lazyPut(() => EnteringTheWarehouseLogic());
Get.lazyPut(() => RootLogic());
}),
),
),*/
//sales
GetPage(
name: ChickenRoutes.salesInProvince,
page: () => SalesInProvincePage(),
name: ChickenRoutes.sale,
page: () => SalePage(),
middlewares: [AuthMiddleware()],
binding: BindingsBuilder(() {
Get.lazyPut(() => SalesInProvinceLogic());
Get.lazyPut(() => RootLogic());
}),
),
GetPage(
name: ChickenRoutes.outOfProvince,
page: () => OutOfProvincePage(),
middlewares: [AuthMiddleware()],
binding: BindingsBuilder(() {
Get.lazyPut(() => OutOfProvinceLogic());
Get.lazyPut(() => SaleLogic());
Get.lazyPut(() => BaseLogic());
Get.lazyPut(() => SalesOutOfProvinceLogic());
Get.lazyPut(() => RootLogic());
}),
),
GetPage(
name: ChickenRoutes.salesOutOfProvince,
page: () => SalesOutOfProvincePage(),
@@ -84,19 +80,53 @@ sealed class ChickenPages {
binding: BindingsBuilder(() {
Get.lazyPut(() => SalesOutOfProvinceLogic());
Get.lazyPut(() => RootLogic());
Get.lazyPut(() => BaseLogic());
}),
),
GetPage(
name: ChickenRoutes.salesInProvince,
page: () => SalesInProvincePage(),
middlewares: [AuthMiddleware()],
binding: BindingsBuilder(() {
Get.lazyPut(() => BaseLogic());
Get.lazyPut(() => SalesInProvinceLogic());
Get.lazyPut(() => RootLogic());
}),
),
//buy
GetPage(
name: ChickenRoutes.buy,
page: () => BuyPage(),
middlewares: [AuthMiddleware()],
binding: BindingsBuilder(() {
Get.lazyPut(() => BaseLogic());
Get.lazyPut(() => BuyLogic());
Get.lazyPut(() => RootLogic());
}),
),
GetPage(
name: ChickenRoutes.buysOutOfProvince,
page: () => BuysOutOfProvincePage(),
page: () => BuyOutOfProvincePage(),
middlewares: [AuthMiddleware()],
binding: BindingsBuilder(() {
Get.lazyPut(() => BuysOutOfProvinceLogic());
Get.lazyPut(() => BaseLogic());
Get.lazyPut(() => SearchLogic());
Get.lazyPut(() => BuyOutOfProvinceLogic());
Get.lazyPut(() => RootLogic());
}),
),
GetPage(
name: ChickenRoutes.buysInProvince,
page: () => BuyInProvincePage(),
middlewares: [AuthMiddleware()],
binding: BindingsBuilder(() {
Get.lazyPut(() => BaseLogic());
Get.lazyPut(() => BuyInProvinceLogic());
Get.lazyPut(() => RootLogic());
}),
),
];
}

View File

@@ -5,11 +5,13 @@ sealed class ChickenRoutes {
static const init = '$_base/root';
static const home = '$_base/home';
static const buy = '$_base/buy';
static const sale = '$_base/sale';
static const enteringTheWarehouse = '$_base/enteringTheWarehouse';
static const salesInProvince = '$_base/SalesInProvincePage';
static const outOfProvince = '$_base/OutOfProvincePage';
//buys
static const buysOutOfProvince = '$buy/buyOutOfProvince';
static const buysInProvince = '$buy/buyInProvince';
static const salesOutOfProvince = '$outOfProvince/saleOutOfProvince';
static const buysOutOfProvince = '$outOfProvince/buyOutOfProvince';
//sales
static const salesInProvince = '$sale/SalesInProvince';
static const salesOutOfProvince = '$sale/saleOutOfProvince';
}

View File

@@ -27,15 +27,15 @@ RAppBar chickenAppBar({
],
),
additionalActions: [
if (!isBase && hasFilter) filterWidget(onFilterTap),
SizedBox(width: 8),
if (!isBase && hasSearch) searchWidget(onSearchTap),
SizedBox(width: 8),
if (!isBase && hasFilter) filterWidget(onFilterTap),
SizedBox(width: 8),
],
);
}
GestureDetector searchWidget(GestureTapCallback? onSearchTap) {
GestureDetector filterWidget(GestureTapCallback? onSearchTap) {
return GestureDetector(
onTap: onSearchTap,
child: Assets.vec.filterOutlineSvg.svg(
@@ -46,7 +46,7 @@ GestureDetector searchWidget(GestureTapCallback? onSearchTap) {
);
}
GestureDetector filterWidget(GestureTapCallback? onFilterTap) {
GestureDetector searchWidget(GestureTapCallback? onFilterTap) {
return GestureDetector(
onTap: onFilterTap,
child: Assets.vec.searchSvg.svg(

View File

@@ -1,20 +0,0 @@
import 'package:flutter/material.dart';
import 'package:rasadyar_chicken/presentation/widget/page_route.dart';
import 'package:rasadyar_core/core.dart';
class BasePage extends StatelessWidget {
const BasePage({super.key, required this.routes, required this.appBar, required this.widgets});
final List<String> routes;
final RAppBar appBar;
final List<Widget> widgets;
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: AppColor.bgLight,
appBar: appBar,
body: Column(crossAxisAlignment: CrossAxisAlignment.start, children: [buildPageRoute(routes), ...widgets]),
);
}
}

View File

@@ -0,0 +1,9 @@
import 'package:rasadyar_core/core.dart';
class BaseLogic extends GetxController {
final RxBool isFilterSelected = false.obs;
void toggleFilter() {
isFilterSelected.value = !isFilterSelected.value;
}
}

View File

@@ -0,0 +1,100 @@
import 'package:flutter/material.dart';
import 'package:rasadyar_chicken/presentation/widget/app_bar.dart';
import 'package:rasadyar_chicken/presentation/widget/base_page/logic.dart';
import 'package:rasadyar_chicken/presentation/widget/page_route.dart';
import 'package:rasadyar_chicken/presentation/widget/search/logic.dart';
import 'package:rasadyar_chicken/presentation/widget/search/view.dart';
import 'package:rasadyar_core/core.dart';
class BasePage extends StatefulWidget {
const BasePage({
super.key,
required this.routes,
required this.widgets,
this.floatingActionButtonLocation,
this.floatingActionButton,
this.onSearchChanged,
this.hasBack = true,
this.hasFilter = true,
this.hasSearch = true,
this.isBase = false,
this.onBackPressed,
this.onFilterTap,
this.onSearchTap,
this.filteringWidget,
});
final List<String> routes;
final List<Widget> widgets;
final FloatingActionButtonLocation? floatingActionButtonLocation;
final Widget? floatingActionButton;
final Widget? filteringWidget;
final void Function(String)? onSearchChanged;
final bool hasBack;
final bool hasFilter;
final bool hasSearch;
final bool isBase;
final VoidCallback? onBackPressed;
final GestureTapCallback? onFilterTap;
final GestureTapCallback? onSearchTap;
@override
State<BasePage> createState() => _BasePageState();
}
class _BasePageState extends State<BasePage> {
BaseLogic get controller => Get.find<BaseLogic>();
Worker? filterWorker;
@override
void initState() {
super.initState();
filterWorker = ever(controller.isFilterSelected, (bool isSelected) {
if (isSelected && widget.filteringWidget != null) {
Get.bottomSheet(
widget.filteringWidget!,
isScrollControlled: true,
isDismissible: true,
enableDrag: true,
).then((_) {
controller.isFilterSelected.value = false;
});
}
});
}
@override
void dispose() {
filterWorker?.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: AppColor.bgLight,
appBar: chickenAppBar(
hasBack: widget.isBase ? false : widget.hasBack,
onBackPressed: widget.onBackPressed,
hasFilter: widget.hasFilter,
hasSearch: widget.hasSearch,
isBase: widget.isBase,
onFilterTap: widget.hasFilter ? () => controller.toggleFilter() : null,
onSearchTap: widget.hasSearch ? () => Get.find<SearchLogic>().toggleSearch() : null,
),
body: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
buildPageRoute(widget.routes),
const SizedBox(height: 8),
if (!widget.isBase && widget.hasSearch) ...{
SearchWidget(onSearchChanged: widget.onSearchChanged),
},
...widget.widgets,
],
),
floatingActionButtonLocation: widget.floatingActionButtonLocation,
floatingActionButton: widget.floatingActionButton,
);
}
}

View File

@@ -3,6 +3,7 @@ import 'package:rasadyar_core/core.dart';
Widget saleOrBuyItemCard({String? title, String? iconPath, required VoidCallback onTap}) {
return InkWell(
borderRadius: BorderRadius.circular(8.r),
onTap: onTap,
child: Card(
color: Colors.white,

View File

@@ -10,16 +10,17 @@
import 'package:flutter/services.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter_svg/flutter_svg.dart' as _svg;
import 'package:lottie/lottie.dart' as _lottie;
import 'package:vector_graphics/vector_graphics.dart' as _vg;
class $AssetsAnimGen {
const $AssetsAnimGen();
/// File path: assets/anim/loading.json
String get loading => 'assets/anim/loading.json';
LottieGenImage get loading => const LottieGenImage('assets/anim/loading.json');
/// List of all assets
List<String> get values => [loading];
List<LottieGenImage> get values => [loading];
}
class $AssetsIconsGen {
@@ -733,3 +734,69 @@ class SvgGenImage {
String get keyName => _assetName;
}
class LottieGenImage {
const LottieGenImage(this._assetName, {this.flavors = const {}});
final String _assetName;
final Set<String> flavors;
_lottie.LottieBuilder lottie({
Animation<double>? controller,
bool? animate,
_lottie.FrameRate? frameRate,
bool? repeat,
bool? reverse,
_lottie.LottieDelegates? delegates,
_lottie.LottieOptions? options,
void Function(_lottie.LottieComposition)? onLoaded,
_lottie.LottieImageProviderFactory? imageProviderFactory,
Key? key,
AssetBundle? bundle,
Widget Function(BuildContext, Widget, _lottie.LottieComposition?)? frameBuilder,
ImageErrorWidgetBuilder? errorBuilder,
double? width,
double? height,
BoxFit? fit,
AlignmentGeometry? alignment,
String? package,
bool? addRepaintBoundary,
FilterQuality? filterQuality,
void Function(String)? onWarning,
_lottie.LottieDecoder? decoder,
_lottie.RenderCache? renderCache,
bool? backgroundLoading,
}) {
return _lottie.Lottie.asset(
_assetName,
controller: controller,
animate: animate,
frameRate: frameRate,
repeat: repeat,
reverse: reverse,
delegates: delegates,
options: options,
onLoaded: onLoaded,
imageProviderFactory: imageProviderFactory,
key: key,
bundle: bundle,
frameBuilder: frameBuilder,
errorBuilder: errorBuilder,
width: width,
height: height,
fit: fit,
alignment: alignment,
package: package,
addRepaintBoundary: addRepaintBoundary,
filterQuality: filterQuality,
onWarning: onWarning,
decoder: decoder,
renderCache: renderCache,
backgroundLoading: backgroundLoading,
);
}
String get path => _assetName;
String get keyName => _assetName;
}

View File

@@ -1,8 +1,6 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:rasadyar_core/utils/network/resource.dart';
import 'r_shimmer_list.dart';
import 'package:rasadyar_core/core.dart';
enum ListType { builder, separated }
@@ -21,7 +19,9 @@ class RPaginatedListView<T> extends StatelessWidget {
this.emptyWidget,
this.errorWidget,
this.scrollController,
this.padding = const EdgeInsets.all(8.0),
this.listType = ListType.builder,
this.physics = const BouncingScrollPhysics(),
});
final Resource<List<T>> resource;
@@ -37,11 +37,17 @@ class RPaginatedListView<T> extends StatelessWidget {
final Widget? errorWidget;
final ScrollController? scrollController;
final ListType listType;
final EdgeInsets padding;
final ScrollPhysics physics;
@override
Widget build(BuildContext context) {
if (resource.isLoading) {
/* if (resource.isLoading) {
return loadingWidget ?? RShimmerList(isSeparated: listType == ListType.separated);
}*/
if (resource.isLoading) {
return loadingWidget ?? const LoadingWidget();
}
if (resource.isError) {
@@ -49,23 +55,28 @@ class RPaginatedListView<T> extends StatelessWidget {
}
if (resource.isEmpty || resource.data?.isEmpty == true) {
return emptyWidget ?? const Center(child: Text('آیتمی یافت نشد'));
return emptyWidget ?? const EmptyWidget();
}
final controller = scrollController ?? ScrollController();
return NotificationListener<ScrollNotification>(
onNotification: (ScrollNotification scrollInfo) {
if (!isPaginating && hasMore && scrollInfo.metrics.pixels >= scrollInfo.metrics.maxScrollExtent - 100) {
if (!isPaginating &&
hasMore &&
scrollInfo.metrics.pixels >= scrollInfo.metrics.maxScrollExtent - 100) {
onLoadMore();
}
return false;
},
child: RefreshIndicator(
color: AppColor.blueNormal,
onRefresh: onRefresh ?? () async {},
child: listType == ListType.separated
? ListView.separated(
padding: padding,
controller: controller,
shrinkWrap: true,
itemCount: itemCount + (isPaginating ? 1 : 0),
itemBuilder: (context, index) {
if (isPaginating && index == itemCount) {
@@ -79,7 +90,9 @@ class RPaginatedListView<T> extends StatelessWidget {
separatorBuilder: separatorBuilder ?? (_, __) => const SizedBox(height: 8),
)
: ListView.builder(
padding: padding,
controller: controller,
shrinkWrap: true,
itemCount: itemCount + (isPaginating ? 1 : 0),
itemBuilder: (context, index) {
if (isPaginating && index == itemCount) {

View File

@@ -1,23 +1,27 @@
export 'app_bar/r_app_bar.dart';
export 'bottom_navigation/r_bottom_navigation.dart';
export 'bottom_navigation/wave_bottom_navigation.dart';
export 'bottom_sheet/base_bottom_sheet.dart';
export 'buttons/elevated.dart';
export 'buttons/fab.dart';
export 'buttons/outline_elevated.dart';
export 'buttons/outline_elevated_icon.dart';
export 'buttons/text_button.dart';
export 'card/card_with_icon_with_border.dart';
export 'chips/r_chips.dart';
export 'draggable_bottom_sheet/bottom_sheet_manger.dart';
export 'draggable_bottom_sheet/draggable_bottom_sheet.dart';
export 'draggable_bottom_sheet/draggable_bottom_sheet2.dart';
export 'draggable_bottom_sheet/draggable_bottom_sheet_controller.dart';
export 'draggable_bottom_sheet/bottom_sheet_manger.dart';
export 'inputs/input_fixed_hint.dart';
export 'inputs/r_input.dart';
export 'list_view/list_view.dart';
export 'overlay_dropdown_widget/view.dart';
export 'pagination/pagination_from_until.dart';
export 'pagination/show_more.dart';
export 'tabs/new_tab.dart';
export 'tabs/tab.dart';
export 'vec_widget.dart';
export 'card/card_with_icon_with_border.dart';
export 'chips/r_chips.dart';
export 'overlay_dropdown_widget/view.dart';
export 'inputs/input_fixed_hint.dart';
export 'bottom_sheet/base_bottom_sheet.dart';
export 'buttons/fab.dart';
export 'empty_widget.dart';
export 'loading_widget.dart';

View File

@@ -80,5 +80,5 @@ flutter_gen:
integrations:
image: true
flutter_svg: true
lottie: true
rive: false
lottie: false