fix : ui fix after release 1.3.3

This commit is contained in:
2025-07-17 15:44:40 +03:30
parent c28a0e6630
commit 7790a4017e
18 changed files with 898 additions and 207 deletions

View File

@@ -27,19 +27,19 @@
<path fill="#E0E0E0" d="M373.4,193.2c-0.1,0.2-17.3-8.9-38.5-20.3s-38.3-20.7-38.3-20.8 17.3,8.9,38.5,20.3 38.3,20.7,38.3,20.8z"/>
<!-- Lamp -->
<path fill="#2D5FFF" d="M314.8,97.2h120.5c0,0-11.1-53.2-61.1-53.2s-59.4,53.2-59.4,53.2z"/>
<rect x="373.7" width="2.6" height="44" fill="#2D5FFF"/>
<path fill="#778dd4" d="M314.8,97.2h120.5c0,0-11.1-53.2-61.1-53.2s-59.4,53.2-59.4,53.2z"/>
<rect x="373.7" width="2.6" height="44" fill="#778dd4"/>
<!-- Floor -->
<path fill="#263238" d="M663.7,439.8c0,0.1-129.3,0.3-288.7,0.3s-288.7-0.1-288.7-0.3c0-0.1,129.2-0.3,288.7-0.3s288.7,0.3,288.7,0.3z"/>
<!-- Plant -->
<path fill="#2D5FFF" d="M118.3,377.2c3.4,0.1,6.6,2,8.8,4.5s3.6,5.7,4.5,9c1.7,6.3,0.7,13.8-1.2,20.1-6.8-2.4-11.1-9.7-13-13.6-2.9-6.1-4.7-18.9,1-19.9"/>
<path fill="#2D5FFF" d="M140.2,418.5c-2.2-3.1-2.2-7.4-0.5-10.8s5-5.8,8.6-6.9c1.7-0.5,3.6-0.7,5.1,0.2s1.9,2.7,1.8,4.3-1,3.1-2,4.4c-3.3,4.5-7.4,8.3-13,8.8"/>
<path fill="#2D5FFF" d="M141,439.6s-0.1-0.5-0.3-1.3c-0.2-0.9-0.4-2.1-0.7-3.6-0.5-3-1.4-7.3-0.7-12.1s2.5-8.8,4.5-11.2c1-1.2,1.9-2.1,2.6-2.6 0.3-0.3,0.6-0.5,0.8-0.6s0.3-0.2,0.3-0.2c0.1,0.1-1.6,1.1-3.5,3.6-1.9,2.4-3.7,6.4-4.3,11.1s0.2,8.9,0.6,12c0.2,1.5,0.4,2.8,0.6,3.6 0.2,0.8,0.3,1.3,0.3,1.3z"/>
<path fill="#2D5FFF" d="M120.5,386.8s0.1,0.2,0.3,0.5c0.2,0.4,0.4,0.9,0.7,1.5 0.6,1.3,1.5,3.3,2.5,5.7 2.1,4.8,4.8,11.4,7.7,18.9s5.3,14.2,7,19.1c0.9,2.5,1.5,4.5,2,5.9 0.2,0.7,0.4,1.2,0.5,1.6s0.2,0.6,0.1,0.6-0.1-0.2-0.2-0.5c-0.2-0.4-0.3-0.9-0.6-1.6-0.5-1.4-1.2-3.4-2.1-5.8-1.8-4.9-4.3-11.6-7.2-19.1-2.9-7.4-5.6-14.1-7.6-18.9-1-2.4-1.8-4.3-2.3-5.7-0.3-0.6-0.5-1.2-0.6-1.6-0.1-0.4-0.1-0.6-0.1-0.6z"/>
<path fill="#2D5FFF" d="M132.9,425.6c-4-6.9-11.6-11.6-19.5-12.1-2-0.1-4.5,0.2-5.4,2s0.3,4,1.7,5.5c5.7,6.2,15.4,8.4,23.3,5.2"/>
<path fill="#2D5FFF" d="M116.4,418.9s0.5,0,1.3,0c0.4,0,0.9,0.1,1.5,0.2s1.2,0.2,1.9,0.4c0.7,0.2,1.5,0.3,2.3,0.6 0.8,0.2,1.7,0.6,2.6,1 1.8,0.8,3.6,1.8,5.4,3.2 1.8,1.4,3.3,2.9,4.5,4.4 0.6,0.8,1.1,1.5,1.6,2.3 0.5,0.7,0.8,1.4,1.2,2.1 0.4,0.6,0.6,1.3,0.8,1.8s0.4,1,0.5,1.4c0.2,0.8,0.4,1.2,0.3,1.2-0.1,0-0.6-1.7-1.9-4.3-0.4-0.6-0.7-1.3-1.2-2-0.4-0.7-1-1.4-1.6-2.2-1.2-1.5-2.7-3-4.4-4.3-1.8-1.3-3.6-2.4-5.3-3.2-0.9-0.4-1.7-0.7-2.5-1s-1.6-0.5-2.3-0.7-1.5-0.4-1.9-0.4z"/>
<path fill="#778dd4" d="M118.3,377.2c3.4,0.1,6.6,2,8.8,4.5s3.6,5.7,4.5,9c1.7,6.3,0.7,13.8-1.2,20.1-6.8-2.4-11.1-9.7-13-13.6-2.9-6.1-4.7-18.9,1-19.9"/>
<path fill="#778dd4" d="M140.2,418.5c-2.2-3.1-2.2-7.4-0.5-10.8s5-5.8,8.6-6.9c1.7-0.5,3.6-0.7,5.1,0.2s1.9,2.7,1.8,4.3-1,3.1-2,4.4c-3.3,4.5-7.4,8.3-13,8.8"/>
<path fill="#778dd4" d="M141,439.6s-0.1-0.5-0.3-1.3c-0.2-0.9-0.4-2.1-0.7-3.6-0.5-3-1.4-7.3-0.7-12.1s2.5-8.8,4.5-11.2c1-1.2,1.9-2.1,2.6-2.6 0.3-0.3,0.6-0.5,0.8-0.6s0.3-0.2,0.3-0.2c0.1,0.1-1.6,1.1-3.5,3.6-1.9,2.4-3.7,6.4-4.3,11.1s0.2,8.9,0.6,12c0.2,1.5,0.4,2.8,0.6,3.6 0.2,0.8,0.3,1.3,0.3,1.3z"/>
<path fill="#778dd4" d="M120.5,386.8s0.1,0.2,0.3,0.5c0.2,0.4,0.4,0.9,0.7,1.5 0.6,1.3,1.5,3.3,2.5,5.7 2.1,4.8,4.8,11.4,7.7,18.9s5.3,14.2,7,19.1c0.9,2.5,1.5,4.5,2,5.9 0.2,0.7,0.4,1.2,0.5,1.6s0.2,0.6,0.1,0.6-0.1-0.2-0.2-0.5c-0.2-0.4-0.3-0.9-0.6-1.6-0.5-1.4-1.2-3.4-2.1-5.8-1.8-4.9-4.3-11.6-7.2-19.1-2.9-7.4-5.6-14.1-7.6-18.9-1-2.4-1.8-4.3-2.3-5.7-0.3-0.6-0.5-1.2-0.6-1.6-0.1-0.4-0.1-0.6-0.1-0.6z"/>
<path fill="#778dd4" d="M132.9,425.6c-4-6.9-11.6-11.6-19.5-12.1-2-0.1-4.5,0.2-5.4,2s0.3,4,1.7,5.5c5.7,6.2,15.4,8.4,23.3,5.2"/>
<path fill="#778dd4" d="M116.4,418.9s0.5,0,1.3,0c0.4,0,0.9,0.1,1.5,0.2s1.2,0.2,1.9,0.4c0.7,0.2,1.5,0.3,2.3,0.6 0.8,0.2,1.7,0.6,2.6,1 1.8,0.8,3.6,1.8,5.4,3.2 1.8,1.4,3.3,2.9,4.5,4.4 0.6,0.8,1.1,1.5,1.6,2.3 0.5,0.7,0.8,1.4,1.2,2.1 0.4,0.6,0.6,1.3,0.8,1.8s0.4,1,0.5,1.4c0.2,0.8,0.4,1.2,0.3,1.2-0.1,0-0.6-1.7-1.9-4.3-0.4-0.6-0.7-1.3-1.2-2-0.4-0.7-1-1.4-1.6-2.2-1.2-1.5-2.7-3-4.4-4.3-1.8-1.3-3.6-2.4-5.3-3.2-0.9-0.4-1.7-0.7-2.5-1s-1.6-0.5-2.3-0.7-1.5-0.4-1.9-0.4z"/>
<!-- Character -->
<path fill="#263238" d="M598.9,92c-0.1,0-0.7-5.3-1.3-12s-0.9-12-0.8-12c0.1,0,0.7,5.3,1.3,12s0.9,12,0.8,12z"/>
@@ -47,9 +47,9 @@
<path fill="#263238" d="M639.1,97.2c0,0.1-5.1,1.3-11.4,2.6s-11.5,2.2-11.5,2.1 5.1-1.3,11.4-2.6 11.5-2.2,11.5-2.1z"/>
<!-- Folder -->
<path fill="#2D5FFF" d="M307.2,234.5l-35.4,181.8-4.6,23.8 236.1-1.2c10.6-0.1,20-9.5,23.4-23.4l41.9-171.6c2.6-10.6-3.1-21.6-11.1-21.6l-238.9,0.3c-6.4-1.1-11,3.8-12.4,10.9z"/>
<path fill="#00237C" fill-opacity="0.5" d="M307.2,234.5l-35.4,181.8-4.6,23.8 236.1-1.2c10.6-0.1,20-9.5,23.4-23.4l41.9-171.6c2.6-10.6-3.1-21.6-11.1-21.6l-238.9,0.3c-6.4-1.1-11,3.8-12.4,10.9z"/>
<path fill="#2D5FFF" d="M480.6,404l-25-201.4c-1-8.3-7.6-14.4-15.4-14.4l-54.8,0.2c-4.1,0-7.9,1.7-10.8,4.8l-26,27.7-152.4,0.8c-9.3,0-16.5,8.9-15.2,18.8l23.2,186.2c1,8.2,7.6,14.4,15.3,14.4l265.6-0.5c29.6,0.6,32.4-8.1,32.4-8.1s-3.1-35.8-3.1-35.8z"/>
<path fill="#778dd4" d="M307.2,234.5l-35.4,181.8-4.6,23.8 236.1-1.2c10.6-0.1,20-9.5,23.4-23.4l41.9-171.6c2.6-10.6-3.1-21.6-11.1-21.6l-238.9,0.3c-6.4-1.1-11,3.8-12.4,10.9z"/>
<path fill="#41527d" fill-opacity="0.5" d="M307.2,234.5l-35.4,181.8-4.6,23.8 236.1-1.2c10.6-0.1,20-9.5,23.4-23.4l41.9-171.6c2.6-10.6-3.1-21.6-11.1-21.6l-238.9,0.3c-6.4-1.1-11,3.8-12.4,10.9z"/>
<path fill="#778dd4" d="M480.6,404l-25-201.4c-1-8.3-7.6-14.4-15.4-14.4l-54.8,0.2c-4.1,0-7.9,1.7-10.8,4.8l-26,27.7-152.4,0.8c-9.3,0-16.5,8.9-15.2,18.8l23.2,186.2c1,8.2,7.6,14.4,15.3,14.4l265.6-0.5c29.6,0.6,32.4-8.1,32.4-8.1s-3.1-35.8-3.1-35.8z"/>
<polygon fill="#06FFB8" points="361.1,325.7 352.1,335.3 283.1,273.3 292.1,263.6"/>
<polygon fill="#06FFB8" points="348.4,261.5 358.3,270.4 295.9,337.5 285.9,328.6"/>

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 11 KiB

View File

@@ -1,4 +1,4 @@
<svg width="109" height="92" viewBox="0 0 109 92" fill="none" xmlns="http://www.w3.org/2000/svg">
ث<svg width="109" height="92" viewBox="0 0 109 92" fill="none" xmlns="http://www.w3.org/2000/svg">
<g opacity="0.29">
<path d="M35.6146 47.3662C36.0267 43.5287 38.0099 41.6228 40.8944 40.7986C47.2301 39.2791 52.1236 43.1938 53.231 49.6841C53.6174 58.312 49.0072 63.1282 41.0232 65.3689C42.9548 61.7117 44.6289 58.003 39.5551 52.8005C36.0525 52.1051 33.4512 52.2854 31.5711 53.1868C30.9272 51.0234 32.1634 49.0917 35.5889 47.3662H35.6146Z" fill="#231F20"/>
<path d="M50.0125 41.4407C50.1671 42.2133 44.8615 36.1866 37.3668 39.097C35.0231 40.8225 31.9325 40.7453 30.7736 38.8652C30.1554 37.8607 30.6705 35.8518 31.8295 34.9246C35.3837 31.3447 49.7807 40.2302 50.0125 41.4149V41.4407Z" fill="#231F20"/>

Before

Width:  |  Height:  |  Size: 19 KiB

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

View File

@@ -63,7 +63,7 @@ class ChickenRemoteDatasourceImp implements ChickenRemoteDatasource {
Map<String, dynamic>? queryParameters,
}) async {
var res = await _httpClient.get(
'/bars_for_kill_house_dashboard/?role=Steward',
'/bars_for_kill_house_dashboard/',
queryParameters: queryParameters,
headers: {'Authorization': 'Bearer $token'},
fromJson: BarInformation.fromJson,

View File

@@ -6,8 +6,14 @@ part 'segmentation_model.g.dart';
@freezed
abstract class SegmentationModel with _$SegmentationModel {
const factory SegmentationModel({String? key, Buyer? buyer, DateTime? date, int? weight,String? result}) =
_SegmentationModel;
const factory SegmentationModel({
String? key,
String? productKey,
Buyer? buyer,
DateTime? date,
int? weight,
String? result,
}) = _SegmentationModel;
factory SegmentationModel.fromJson(Map<String, dynamic> json) =>
_$SegmentationModelFromJson(json);

View File

@@ -16,7 +16,7 @@ T _$identity<T>(T value) => value;
/// @nodoc
mixin _$SegmentationModel {
String? get key; Buyer? get buyer; DateTime? get date; int? get weight; String? get result;
String? get key; String? get productKey; Buyer? get buyer; DateTime? get date; int? get weight; String? get result;
/// Create a copy of SegmentationModel
/// with the given fields replaced by the non-null parameter values.
@JsonKey(includeFromJson: false, includeToJson: false)
@@ -29,16 +29,16 @@ $SegmentationModelCopyWith<SegmentationModel> get copyWith => _$SegmentationMode
@override
bool operator ==(Object other) {
return identical(this, other) || (other.runtimeType == runtimeType&&other is SegmentationModel&&(identical(other.key, key) || other.key == key)&&(identical(other.buyer, buyer) || other.buyer == buyer)&&(identical(other.date, date) || other.date == date)&&(identical(other.weight, weight) || other.weight == weight)&&(identical(other.result, result) || other.result == result));
return identical(this, other) || (other.runtimeType == runtimeType&&other is SegmentationModel&&(identical(other.key, key) || other.key == key)&&(identical(other.productKey, productKey) || other.productKey == productKey)&&(identical(other.buyer, buyer) || other.buyer == buyer)&&(identical(other.date, date) || other.date == date)&&(identical(other.weight, weight) || other.weight == weight)&&(identical(other.result, result) || other.result == result));
}
@JsonKey(includeFromJson: false, includeToJson: false)
@override
int get hashCode => Object.hash(runtimeType,key,buyer,date,weight,result);
int get hashCode => Object.hash(runtimeType,key,productKey,buyer,date,weight,result);
@override
String toString() {
return 'SegmentationModel(key: $key, buyer: $buyer, date: $date, weight: $weight, result: $result)';
return 'SegmentationModel(key: $key, productKey: $productKey, buyer: $buyer, date: $date, weight: $weight, result: $result)';
}
@@ -49,7 +49,7 @@ abstract mixin class $SegmentationModelCopyWith<$Res> {
factory $SegmentationModelCopyWith(SegmentationModel value, $Res Function(SegmentationModel) _then) = _$SegmentationModelCopyWithImpl;
@useResult
$Res call({
String? key, Buyer? buyer, DateTime? date, int? weight, String? result
String? key, String? productKey, Buyer? buyer, DateTime? date, int? weight, String? result
});
@@ -66,9 +66,10 @@ class _$SegmentationModelCopyWithImpl<$Res>
/// Create a copy of SegmentationModel
/// with the given fields replaced by the non-null parameter values.
@pragma('vm:prefer-inline') @override $Res call({Object? key = freezed,Object? buyer = freezed,Object? date = freezed,Object? weight = freezed,Object? result = freezed,}) {
@pragma('vm:prefer-inline') @override $Res call({Object? key = freezed,Object? productKey = freezed,Object? buyer = freezed,Object? date = freezed,Object? weight = freezed,Object? result = freezed,}) {
return _then(_self.copyWith(
key: freezed == key ? _self.key : key // ignore: cast_nullable_to_non_nullable
as String?,productKey: freezed == productKey ? _self.productKey : productKey // ignore: cast_nullable_to_non_nullable
as String?,buyer: freezed == buyer ? _self.buyer : buyer // ignore: cast_nullable_to_non_nullable
as Buyer?,date: freezed == date ? _self.date : date // ignore: cast_nullable_to_non_nullable
as DateTime?,weight: freezed == weight ? _self.weight : weight // ignore: cast_nullable_to_non_nullable
@@ -96,10 +97,11 @@ $BuyerCopyWith<$Res>? get buyer {
@JsonSerializable()
class _SegmentationModel implements SegmentationModel {
const _SegmentationModel({this.key, this.buyer, this.date, this.weight, this.result});
const _SegmentationModel({this.key, this.productKey, this.buyer, this.date, this.weight, this.result});
factory _SegmentationModel.fromJson(Map<String, dynamic> json) => _$SegmentationModelFromJson(json);
@override final String? key;
@override final String? productKey;
@override final Buyer? buyer;
@override final DateTime? date;
@override final int? weight;
@@ -118,16 +120,16 @@ Map<String, dynamic> toJson() {
@override
bool operator ==(Object other) {
return identical(this, other) || (other.runtimeType == runtimeType&&other is _SegmentationModel&&(identical(other.key, key) || other.key == key)&&(identical(other.buyer, buyer) || other.buyer == buyer)&&(identical(other.date, date) || other.date == date)&&(identical(other.weight, weight) || other.weight == weight)&&(identical(other.result, result) || other.result == result));
return identical(this, other) || (other.runtimeType == runtimeType&&other is _SegmentationModel&&(identical(other.key, key) || other.key == key)&&(identical(other.productKey, productKey) || other.productKey == productKey)&&(identical(other.buyer, buyer) || other.buyer == buyer)&&(identical(other.date, date) || other.date == date)&&(identical(other.weight, weight) || other.weight == weight)&&(identical(other.result, result) || other.result == result));
}
@JsonKey(includeFromJson: false, includeToJson: false)
@override
int get hashCode => Object.hash(runtimeType,key,buyer,date,weight,result);
int get hashCode => Object.hash(runtimeType,key,productKey,buyer,date,weight,result);
@override
String toString() {
return 'SegmentationModel(key: $key, buyer: $buyer, date: $date, weight: $weight, result: $result)';
return 'SegmentationModel(key: $key, productKey: $productKey, buyer: $buyer, date: $date, weight: $weight, result: $result)';
}
@@ -138,7 +140,7 @@ abstract mixin class _$SegmentationModelCopyWith<$Res> implements $SegmentationM
factory _$SegmentationModelCopyWith(_SegmentationModel value, $Res Function(_SegmentationModel) _then) = __$SegmentationModelCopyWithImpl;
@override @useResult
$Res call({
String? key, Buyer? buyer, DateTime? date, int? weight, String? result
String? key, String? productKey, Buyer? buyer, DateTime? date, int? weight, String? result
});
@@ -155,9 +157,10 @@ class __$SegmentationModelCopyWithImpl<$Res>
/// Create a copy of SegmentationModel
/// with the given fields replaced by the non-null parameter values.
@override @pragma('vm:prefer-inline') $Res call({Object? key = freezed,Object? buyer = freezed,Object? date = freezed,Object? weight = freezed,Object? result = freezed,}) {
@override @pragma('vm:prefer-inline') $Res call({Object? key = freezed,Object? productKey = freezed,Object? buyer = freezed,Object? date = freezed,Object? weight = freezed,Object? result = freezed,}) {
return _then(_SegmentationModel(
key: freezed == key ? _self.key : key // ignore: cast_nullable_to_non_nullable
as String?,productKey: freezed == productKey ? _self.productKey : productKey // ignore: cast_nullable_to_non_nullable
as String?,buyer: freezed == buyer ? _self.buyer : buyer // ignore: cast_nullable_to_non_nullable
as Buyer?,date: freezed == date ? _self.date : date // ignore: cast_nullable_to_non_nullable
as DateTime?,weight: freezed == weight ? _self.weight : weight // ignore: cast_nullable_to_non_nullable

View File

@@ -9,6 +9,7 @@ part of 'segmentation_model.dart';
_SegmentationModel _$SegmentationModelFromJson(Map<String, dynamic> json) =>
_SegmentationModel(
key: json['key'] as String?,
productKey: json['product_key'] as String?,
buyer: json['buyer'] == null
? null
: Buyer.fromJson(json['buyer'] as Map<String, dynamic>),
@@ -22,6 +23,7 @@ _SegmentationModel _$SegmentationModelFromJson(Map<String, dynamic> json) =>
Map<String, dynamic> _$SegmentationModelToJson(_SegmentationModel instance) =>
<String, dynamic>{
'key': instance.key,
'product_key': instance.productKey,
'buyer': instance.buyer,
'date': instance.date?.toIso8601String(),
'weight': instance.weight,

View File

@@ -1,41 +1,56 @@
import 'package:rasadyar_auth/data/utils/safe_call.dart';
import 'package:rasadyar_chicken/chicken.dart';
import 'package:rasadyar_chicken/data/models/response/bar_information/bar_information.dart';
import 'package:rasadyar_chicken/data/models/response/inventory/inventory_model.dart';
import 'package:rasadyar_chicken/data/models/response/kill_house_distribution_info/kill_house_distribution_info.dart';
import 'package:rasadyar_chicken/presentation/utils/utils.dart';
import 'package:rasadyar_core/core.dart';
class HomeLogic extends GetxController {
RootLogic rootLogic = Get.find<RootLogic>();
RxnInt totalWeightTodayBars = RxnInt();
Rxn<KillHouseDistributionInfo> killHouseDistributionInfo = Rxn<KillHouseDistributionInfo>();
Rxn<BarInformation> barInformation = Rxn();
RxBool isExpanded = false.obs;
@override
void onReady() {
super.onReady();
getGeneralBarsInformation();
getTodayBars();
getDistributionInformation();
}
Future<void> getGeneralBarsInformation() async {
await safeCall<BarInformation?>(
call: () async => await rootLogic.chickenRepository.getGeneralBarInformation(
token: rootLogic.tokenService.accessToken.value!,
queryParameters: buildQueryParams(role: 'Steward'),
),
onSuccess: (result) {
if (result != null) {
barInformation.value = result;
}
},
onError: (error, stackTrace) {},
);
}
Future<void> getTodayBars() async {
await safeCall<BarInformation?>(
call: () async => await rootLogic.chickenRepository.getGeneralBarInformation(
token: rootLogic.tokenService.accessToken.value!,
queryParameters: buildQueryParams(fromDate: DateTime.now(), toDate: DateTime.now()),
queryParameters: buildQueryParams(
fromDate: DateTime.now(),
toDate: DateTime.now(),
role: 'Steward',
),
),
onSuccess: (result) {
if (result != null) {
totalWeightTodayBars.value = result.totalBarsWeight?.toInt();
}
},
onError: (error, stackTrace) {
},
onError: (error, stackTrace) {},
);
}
@@ -52,7 +67,4 @@ class HomeLogic extends GetxController {
onError: (error, stackTrace) {},
);
}
}

View File

@@ -280,61 +280,44 @@ class HomePage extends GetView<HomeLogic> {
}
Widget _todayShipmentWidget() {
return ObxValue((data) {
return Container(
height: 70,
width: Get.width / 2,
decoration: BoxDecoration(color: Colors.white, borderRadius: BorderRadius.circular(8)),
clipBehavior: Clip.hardEdge,
child: Row(
children: [
Expanded(
child: Container(
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
colors: [const Color(0xFFEAEFFF), Colors.white],
),
),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
spacing: 4,
children: [
Assets.icons.cubeScan.svg(width: 30, height: 30),
Text(
'بارهای امروز',
textAlign: TextAlign.right,
style: AppFonts.yekan14.copyWith(color: AppColor.blueNormal),
),
],
),
return Padding(
padding: const EdgeInsets.fromLTRB(0, 10, 0, 13),
child: Row(
spacing: 8,
children: [
Expanded(
child: ObxValue(
(data) => _informationLabelCard(
title: 'بارهای امروز',
isLoading: data.value == null,
description: data.value?.separatedByComma ?? '0',
iconPath: Assets.vec.cubeSearchSvg.path,
iconColor: AppColor.blueNormal,
bgDescriptionColor: Colors.white,
bgLabelColor: Color(0xFFEAEFFF),
),
controller.totalWeightTodayBars,
),
Expanded(
child: data.value == null
? CupertinoActivityIndicator()
: Column(
mainAxisAlignment: MainAxisAlignment.center,
spacing: 4,
children: [
Text(
data.value.separatedByComma,
textAlign: TextAlign.right,
style: AppFonts.yekan16.copyWith(color: AppColor.textColor),
),
Text(
'کیلوگرم',
textAlign: TextAlign.center,
style: AppFonts.yekan12.copyWith(color: AppColor.textColor),
),
],
),
),
],
),
);
}, controller.totalWeightTodayBars);
),
Expanded(
child: ObxValue((data) {
return _informationLabelCard(
title: 'درانتظار تایید',
isLoading: data.value == null,
description: '(${data.value?.totalNotEnteredBars.separatedByComma ?? '0'})',
unit: '(${data.value?.totalNotEnteredKillHouseRequestsWeight.separatedByComma})کیلوگرم',
iconPath: Assets.vec.cubeRotateSvg.path,
iconColor: Color(0xFF8F4124),
bgLabelColor: Color(0xFFF59770),
bgDescriptionColor: Color(0xFFF6DFD8),
);
}, controller.barInformation),
),
],
),
);
}
Container _informationLabelCard({

View File

@@ -74,6 +74,9 @@ class ProfilePage extends GetView<ProfileLogic> {
cardActionWidget(
title: 'خروج',
selected: true,
color: ColorFilter.mode(Colors.redAccent, BlendMode.srcIn),
cardColor:AppColor.error.withValues(alpha: 0.24),
textColor: Colors.red,
onPressed: () {
Get.bottomSheet(exitBottomSheet(), isScrollControlled: true);
},
@@ -83,7 +86,6 @@ class ProfilePage extends GetView<ProfileLogic> {
),
),
SizedBox(height: 100),
],
),
@@ -214,6 +216,9 @@ class ProfilePage extends GetView<ProfileLogic> {
required VoidCallback onPressed,
required String icon,
bool selected = false,
ColorFilter? color,
Color? cardColor,
Color? textColor,
}) {
return GestureDetector(
onTap: onPressed,
@@ -225,23 +230,25 @@ class ProfilePage extends GetView<ProfileLogic> {
height: 52,
padding: EdgeInsets.all(8),
decoration: ShapeDecoration(
color: AppColor.blueLight,
color: cardColor??AppColor.blueLight,
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)),
),
child: SvgGenImage.vec(icon).svg(
width: 40,
height: 40,
colorFilter: ColorFilter.mode(
selected ? AppColor.blueNormal : AppColor.whiteLight,
BlendMode.srcIn,
),
colorFilter:
color ??
ColorFilter.mode(
selected ? AppColor.blueNormal : AppColor.whiteLight,
BlendMode.srcIn,
),
),
),
SizedBox(height: 2),
Text(
title,
style: AppFonts.yekan10.copyWith(
color: selected ? AppColor.blueNormal : AppColor.blueLightActive,
color: textColor ?? (selected ? AppColor.blueNormal : AppColor.blueLightActive),
),
textAlign: TextAlign.center,
),

View File

@@ -1,7 +1,15 @@
import 'package:flutter/material.dart';
import 'package:rasadyar_auth/data/utils/safe_call.dart';
import 'package:rasadyar_chicken/data/models/request/steward_free_sale_bar/steward_free_sale_bar_request.dart';
import 'package:rasadyar_chicken/data/models/response/iran_province_city/iran_province_city_model.dart';
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/root/logic.dart';
import 'package:rasadyar_chicken/presentation/pages/sale/logic.dart';
import 'package:rasadyar_chicken/presentation/pages/sales_out_of_province_buyers/logic.dart';
import 'package:rasadyar_chicken/presentation/pages/sales_out_of_province_sales_list/logic.dart';
import 'package:rasadyar_chicken/presentation/utils/utils.dart';
import 'package:rasadyar_core/core.dart';
class SalesOutOfProvinceLogic extends GetxController {
@@ -9,58 +17,199 @@ class SalesOutOfProvinceLogic extends GetxController {
SaleLogic get saleLogic => Get.find<SaleLogic>();
SalesOutOfProvinceBuyersLogic get buyersLogic =>
Get.find<SalesOutOfProvinceBuyersLogic>();
SalesOutOfProvinceBuyersLogic get buyersLogic => Get.find<SalesOutOfProvinceBuyersLogic>();
SalesOutOfProvinceSalesListLogic get saleListLogic =>
Get.find<SalesOutOfProvinceSalesListLogic>();
RxInt selectedSegmentIndex = 0.obs;
RxBool isExpanded = false.obs;
SalesOutOfProvinceBuyersLogic get buyerLogic => Get.find<SalesOutOfProvinceBuyersLogic>();
RxBool isExpanded = false.obs;
RxInt currentPage = 1.obs;
RxBool isSaleSubmitButtonEnabled = false.obs;
RxList<int> isExpandedList = <int>[].obs;
Rx<Jalali> fromDateFilter = Jalali.now().obs;
Rx<Jalali> toDateFilter = Jalali.now().obs;
RxnString searchedValue = RxnString();
RxList<String> routesName = RxList();
RxBool isLoadingMoreAllocationsMade = false.obs;
Rxn<IranProvinceCityModel> selectedCity = Rxn();
//TODO add this to Di
ImagePicker imagePicker = ImagePicker();
GlobalKey<FormState> formKey = GlobalKey<FormState>();
TextEditingController quarantineCodeController = TextEditingController();
TextEditingController saleWeightController = TextEditingController();
Rx<Jalali> saleDate = Jalali.now().obs;
String? key;
Rx<Resource<PaginationModel<StewardFreeSaleBar>>> salesList =
Resource<PaginationModel<StewardFreeSaleBar>>.loading().obs;
Rxn<ProductModel> selectedProduct = Rxn();
Rxn<OutProvinceCarcassesBuyer> selectedBuyer = Rxn();
@override
void onInit() {
super.onInit();
routesName.value = [...saleLogic.routesName, 'خارج استان'].toList();
routesName.add(selectedSegmentIndex.value == 0 ? 'فروش' : 'خریداران');
ever(selectedSegmentIndex, (callback) {
routesName.removeLast();
routesName.add(callback == 0 ? 'فروش' : 'خریداران');
});
}
@override
void onReady() {
super.onReady();
getOutProvinceSales();
selectedProduct.value = rootLogic.rolesProductsModel.first;
debounce(
searchedValue,
(callback) => getOutProvinceSales(),
time: Duration(milliseconds: timeDebounce),
);
}
void setSearchValue(String? value) {
searchedValue.value = value?.trim();
if (selectedSegmentIndex.value == 0) {
saleListLogic.searchedValue.value = value?.trim();
} else {
buyersLogic.searchedValue.value = value?.trim();
}
}
void submitFilter() {
if (selectedSegmentIndex.value == 0) {
saleListLogic.fromDateFilter.value = fromDateFilter.value;
saleListLogic.toDateFilter.value = toDateFilter.value;
saleListLogic.getOutProvinceSales();
fromDateFilter.value = fromDateFilter.value;
toDateFilter.value = toDateFilter.value;
getOutProvinceSales();
}
Future<void> getOutProvinceSales([bool isLoadingMore = false]) async {
if (isLoadingMore) {
isLoadingMoreAllocationsMade.value = true;
} else {
buyersLogic.fromDateFilter.value = fromDateFilter.value;
buyersLogic.toDateFilter.value = toDateFilter.value;
buyersLogic.getOutProvinceCarcassesBuyer();
salesList.value = Resource<PaginationModel<StewardFreeSaleBar>>.loading();
}
await safeCall(
call: () => rootLogic.chickenRepository.getStewardFreeSaleBar(
token: rootLogic.tokenService.accessToken.value!,
queryParameters: buildQueryParams(
pageSize: 20,
page: currentPage.value,
state: 'buyer-list',
search: 'filter',
role: 'Steward',
value: searchedValue.value ?? '',
fromDate: fromDateFilter.value.toDateTime(),
toDate: toDateFilter.value.toDateTime(),
),
),
onSuccess: (res) {
if ((res?.count ?? 0) == 0) {
salesList.value = Resource<PaginationModel<StewardFreeSaleBar>>.empty();
} else {
salesList.value = Resource<PaginationModel<StewardFreeSaleBar>>.success(
PaginationModel<StewardFreeSaleBar>(
count: res?.count ?? 0,
next: res?.next,
previous: res?.previous,
results: [...(salesList.value.data?.results ?? []), ...(res?.results ?? [])],
),
);
isLoadingMoreAllocationsMade.value = false;
}
},
);
}
void setupListeners() {
saleWeightController.addListener(checkSalesFormValid);
quarantineCodeController.addListener(checkSalesFormValid);
ever(selectedBuyer, (_) => checkSalesFormValid);
ever(selectedProduct, (_) => checkSalesFormValid);
ever(saleDate, (_) => checkSalesFormValid());
}
void checkSalesFormValid() {
isSaleSubmitButtonEnabled.value =
saleDate.value.toString().isNotEmpty &&
selectedProduct.value != null &&
selectedBuyer.value != null &&
saleWeightController.text.isNotEmpty &&
quarantineCodeController.text.isNotEmpty;
}
void setEditDataSales(StewardFreeSaleBar item) {
quarantineCodeController.text = item.clearanceCode ?? '';
saleWeightController.text = item.weightOfCarcasses?.toInt().toString() ?? '';
saleDate.value = Jalali.fromDateTime(DateTime.parse(item.date!));
selectedCity.value = IranProvinceCityModel(name: item.city);
selectedBuyer.value = buyerLogic.buyerList.value.data?.results?.firstWhere(
(element) => element.key == item.buyer?.key,
);
selectedProduct.value = rootLogic.rolesProductsModel.first;
key = item.key;
isSaleSubmitButtonEnabled.value = true;
}
Future<void> deleteStewardPurchaseOutOfProvince(String key) async {
await safeCall(
call: () => rootLogic.chickenRepository.deleteStewardPurchasesOutSideOfTheProvince(
token: rootLogic.tokenService.accessToken.value!,
stewardFreeBarKey: key,
),
);
}
Future<bool> createSale() async {
bool res = false;
StewardFreeSaleBarRequest requestBody = StewardFreeSaleBarRequest(
buyerKey: selectedBuyer.value?.key,
numberOfCarcasses: 0,
weightOfCarcasses: int.tryParse(saleWeightController.text.clearComma),
date: saleDate.value.toDateTime().formattedDashedGregorian,
clearanceCode: quarantineCodeController.text,
productKey: selectedProduct.value?.key,
);
await safeCall(
call: () => rootLogic.chickenRepository.createOutProvinceStewardFreeBar(
token: rootLogic.tokenService.accessToken.value!,
body: requestBody,
),
onSuccess: (_) {
res = true;
},
);
return res;
}
void clearSaleForm() {
quarantineCodeController.clear();
saleWeightController.clear();
saleDate.value = Jalali.now();
selectedBuyer.value = null;
selectedProduct.value = null;
}
Future<bool> editSale() async {
bool res = false;
StewardFreeSaleBarRequest requestBody = StewardFreeSaleBarRequest(
numberOfCarcasses: 0,
weightOfCarcasses: int.tryParse(saleWeightController.text.clearComma),
date: saleDate.value.toDateTime().formattedDashedGregorian,
clearanceCode: quarantineCodeController.text,
key: key,
);
await safeCall(
call: () => rootLogic.chickenRepository.updateOutProvinceStewardFreeBar(
token: rootLogic.tokenService.accessToken.value!,
body: requestBody,
),
onSuccess: (_) {
res = true;
},
);
return res;
}
void resetSubmitForm() {
selectedCity.value = null;
selectedProduct.value = null;
key = null;
}
}

View File

@@ -1,8 +1,16 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
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/sales_out_of_province_sales_list/view.dart';
import 'package:rasadyar_chicken/presentation/routes/routes.dart';
import 'package:rasadyar_chicken/presentation/widget/base_page/view.dart';
import 'package:rasadyar_chicken/presentation/widget/filter_bottom_sheet.dart';
import 'package:rasadyar_chicken/presentation/widget/inventory_widget.dart';
import 'package:rasadyar_chicken/presentation/widget/list_item/list_item.dart';
import 'package:rasadyar_chicken/presentation/widget/list_row_item.dart';
import 'package:rasadyar_chicken/presentation/widget/page_route.dart';
import 'package:rasadyar_core/core.dart';
@@ -20,13 +28,61 @@ class SalesOutOfProvincePage extends GetView<SalesOutOfProvinceLogic> {
filteringWidget: filterBottomSheet(),
widgets: [
inventoryWidget(controller.rootLogic),
Expanded(child: SalesOutOfProvinceSalesListPage()),
Expanded(
child: ObxValue((data) {
return RPaginatedListView(
onLoadMore: () async => controller.getOutProvinceSales(true),
onRefresh: () async {
controller.currentPage.value = 1;
await controller.getOutProvinceSales();
},
hasMore: data.value.data?.next != null,
listType: ListType.separated,
resource: data.value,
padding: EdgeInsets.fromLTRB(8, 8, 8, 80),
itemBuilder: (context, index) {
var item = data.value.data!.results![index];
return ObxValue((val) {
return ListItem2(
selected: val.contains(index),
onTap: () => controller.isExpandedList.toggle(index),
index: index,
child: itemListWidget(item),
secondChild: itemListExpandedWidget(item, index),
labelColor: AppColor.blueLight,
labelIcon: Assets.vec.timerSvg.path,
);
}, controller.isExpandedList);
},
itemCount: data.value.data?.results?.length ?? 0,
separatorBuilder: (context, index) => SizedBox(height: 8.h),
);
}, controller.salesList),
),
],
floatingActionButton: Row(
children: [
RFab.add(
onPressed: () {
Get.bottomSheet(addOrEditSaleBottomSheet(), isScrollControlled: true);
},
),
Spacer(),
RFab(
icon: Icon(CupertinoIcons.person_add_solid, color: Colors.white, size: 35.w),
backgroundColor: AppColor.blueNormal,
onPressed: () {
Get.toNamed(ChickenRoutes.salesOutOfProvinceBuyer, id: 1);
},
),
SizedBox(width: 25),
],
),
floatingActionButtonLocation: FloatingActionButtonLocation.startFloat,
);
}
Padding segmentWidget() {
/* Padding segmentWidget() {
return Padding(
padding: const EdgeInsets.fromLTRB(8, 0, 8, 8),
child: Row(
@@ -45,7 +101,7 @@ class SalesOutOfProvincePage extends GetView<SalesOutOfProvinceLogic> {
],
),
);
}
}*/
Widget filterBottomSheet() => filterBottomSheetWidget(
fromDate: controller.fromDateFilter,
@@ -54,4 +110,418 @@ class SalesOutOfProvincePage extends GetView<SalesOutOfProvinceLogic> {
onChangedToDate: (jalali) => controller.toDateFilter.value = jalali,
onSubmit: () => controller.submitFilter(),
);
itemListWidget(StewardFreeSaleBar item) {
return Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
SizedBox(width: 12),
Expanded(
flex: 3,
child: Text(
item.date?.formattedJalaliDate ?? 'N/A',
textAlign: TextAlign.center,
style: AppFonts.yekan12.copyWith(color: AppColor.bgDark),
),
),
SizedBox(width: 4),
Expanded(
flex: 5,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
item.buyer?.fullname ?? 'N/A',
textAlign: TextAlign.center,
style: AppFonts.yekan14.copyWith(color: AppColor.blueNormal),
),
SizedBox(height: 2),
Text(
item.buyer?.mobile ?? 'N/A',
textAlign: TextAlign.center,
style: AppFonts.yekan14.copyWith(color: AppColor.bgDark),
),
],
),
),
SizedBox(width: 4),
Expanded(
flex: 4,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
spacing: 8,
children: [
Text(
item.buyer?.unitName ?? 'N/A',
textAlign: TextAlign.center,
style: AppFonts.yekan12.copyWith(color: AppColor.bgDark),
),
Text(
'${item.weightOfCarcasses?.separatedByComma ?? 0}KG',
textAlign: TextAlign.center,
style: AppFonts.yekan12.copyWith(color: AppColor.bgDark),
),
],
),
),
Expanded(
flex: 2,
child: Text(
'${item.buyer?.province}\n${item.buyer?.city}',
textAlign: TextAlign.center,
style: AppFonts.yekan12.copyWith(color: AppColor.bgDark),
),
),
],
);
}
itemListExpandedWidget(StewardFreeSaleBar item, int index) {
return Container(
padding: EdgeInsets.symmetric(horizontal: 8),
decoration: BoxDecoration(color: Colors.white, borderRadius: BorderRadius.circular(8)),
child: Column(
spacing: 8,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.start,
children: [
Text(
'${item.province}-${item.city}',
textAlign: TextAlign.center,
style: AppFonts.yekan16.copyWith(color: AppColor.greenDark),
),
],
),
Container(
height: 32,
padding: EdgeInsets.symmetric(horizontal: 8),
decoration: ShapeDecoration(
color: AppColor.blueLight,
shape: RoundedRectangleBorder(
side: BorderSide(width: 1, color: AppColor.blueLightHover),
borderRadius: BorderRadius.circular(8),
),
),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Row(
spacing: 3,
children: [
Text(
item.date?.toJalali.formatter.wN ?? 'N/A',
style: AppFonts.yekan14.copyWith(color: AppColor.textColor),
),
Text(
'${item.date?.toJalali.formatter.d} ${item.date?.toJalali.formatter.mN ?? 'N/A'}',
style: AppFonts.yekan14.copyWith(color: AppColor.blueNormal),
),
],
),
Text(
'${item.date?.toJalali.formatter.y}',
style: AppFonts.yekan20.copyWith(color: AppColor.textColor),
),
Text(
'${item.date?.toJalali.formatter.tHH}:${item.date?.toJalali.formatter.tMM ?? 'N/A'}',
style: AppFonts.yekan14.copyWith(color: AppColor.textColor),
),
],
),
),
buildRow(title: 'مشخصات خریدار', value: item.buyer?.fullname ?? 'N/A'),
buildRow(title: 'تلفن خریدار', value: item.buyer?.mobile ?? 'N/A'),
buildRow(title: 'نام واحد', value: item.buyer?.unitName ?? 'N/A'),
buildRow(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,
),
],
),
],
),
);
}
Widget addOrEditSaleBottomSheet([bool isOnEdit = false]) {
return BaseBottomSheet(
height: 500.h,
child: SingleChildScrollView(
child: Form(
key: controller.formKey,
child: Column(
spacing: 16,
children: [
Text(
isOnEdit ? 'ویرایش فروش' : 'افزودن فروش',
style: AppFonts.yekan16Bold.copyWith(color: AppColor.blueNormal),
),
_productDropDown(),
Container(
padding: EdgeInsets.all(8),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(8),
border: Border.all(color: AppColor.darkGreyLight, width: 1),
),
child: Column(
spacing: 12,
children: [
Row(
spacing: 8,
children: [
Expanded(
child: timeFilterWidget(
date: controller.saleDate,
onChanged: (jalali) => controller.saleDate.value = jalali,
),
),
],
),
_buyerWidget(),
RTextField(
controller: controller.saleWeightController,
label: 'وزن لاشه',
keyboardType: TextInputType.number,
borderColor: AppColor.darkGreyLight,
filledColor: AppColor.bgLight,
filled: true,
inputFormatters: [
FilteringTextInputFormatter.digitsOnly,
SeparatorInputFormatter(),
],
validator: (value) {
if (value == null) {
return 'لطفاً وزن لاشه را وارد کنید';
}
return null;
},
),
RTextField(
controller: controller.quarantineCodeController,
label: 'کد قرنطینه',
borderColor: AppColor.darkGreyLight,
filledColor: AppColor.bgLight,
filled: true,
validator: (value) {
if (value == null) {
return 'لطفاً کد قرنطینه را وارد کنید';
}
return null;
},
),
submitButtonWidget(isOnEdit),
],
),
),
SizedBox(),
],
),
),
),
);
}
Widget submitButtonWidget(bool isOnEdit) {
return ObxValue((data) {
return RElevated(
isFullWidth: true,
backgroundColor: AppColor.greenNormal,
text: isOnEdit ? 'ویرایش' : 'ثبت',
onPressed: data.value
? () async {
var res = isOnEdit ? await controller.editSale() : await controller.createSale();
if (res) {
controller.getOutProvinceSales();
controller.clearSaleForm();
Get.back();
}
}
: null,
height: 40,
);
}, controller.isSaleSubmitButtonEnabled);
}
Widget _buyerWidget() {
return Obx(() {
return OverlayDropdownWidget<OutProvinceCarcassesBuyer>(
items: controller.buyerLogic.buyerList.value.data?.results ?? [],
onChanged: (value) {
controller.selectedBuyer.value = value;
},
selectedItem: controller.selectedBuyer.value,
itemBuilder: (item) => Text(item.buyer?.fullname ?? 'بدون نام'),
labelBuilder: (item) => Text(item?.buyer?.fullname ?? 'انتخاب خریدار'),
);
});
}
Widget _productDropDown() {
return Obx(() {
return OverlayDropdownWidget<ProductModel>(
items: controller.rootLogic.rolesProductsModel,
height: 56,
hasDropIcon: false,
background: Colors.white,
onChanged: (value) {
controller.selectedProduct.value = value;
},
selectedItem: controller.selectedProduct.value,
initialValue: controller.selectedProduct.value,
itemBuilder: (item) => Text(item.name ?? 'بدون نام'),
labelBuilder: (item) => Row(
spacing: 8,
children: [
(item?.name?.contains('مرغ گرم') ?? false)
? Assets.images.chicken.image(width: 40, height: 40)
: Assets.vec.placeHolderSvg.svg(width: 40, height: 40),
Text(item?.name ?? 'انتخاب محصول'),
Spacer(),
Text(
'موجودی:${controller.rootLogic.inventoryModel.value?.totalRemainWeight.separatedByComma ?? 0}',
),
],
),
);
});
}
GestureDetector timeFilterWidget({
isFrom = true,
required Rx<Jalali> date,
required Function(Jalali jalali) onChanged,
}) {
return GestureDetector(
onTap: () {
Get.bottomSheet(modalDatePicker((value) => onChanged(value)));
},
child: Container(
height: 40,
decoration: BoxDecoration(
color: AppColor.bgLight,
borderRadius: BorderRadius.circular(8),
border: Border.all(width: 1, color: AppColor.darkGreyLight),
),
padding: EdgeInsets.symmetric(horizontal: 11, vertical: 4),
child: Row(
spacing: 8,
children: [
Assets.vec.calendarSvg.svg(
width: 24,
height: 24,
colorFilter: const ColorFilter.mode(AppColor.bgDark, BlendMode.srcIn),
),
Text('تاریخ', style: AppFonts.yekan16.copyWith(color: AppColor.bgDark)),
Expanded(
child: ObxValue((data) {
return Text(
date.value.formatCompactDate(),
textAlign: TextAlign.center,
style: AppFonts.yekan16.copyWith(color: AppColor.darkGreyDark),
);
}, date),
),
],
),
),
);
}
Container modalDatePicker(ValueChanged<Jalali> onDateSelected) {
Jalali? tempPickedDate;
return Container(
height: 250,
color: Colors.white,
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Container(
child: Row(
children: [
SizedBox(width: 20),
RElevated(
height: 35,
width: 70,
textStyle: AppFonts.yekan14.copyWith(color: Colors.white),
onPressed: () {
onDateSelected(tempPickedDate ?? Jalali.now());
Get.back();
},
text: 'تایید',
),
Spacer(),
RElevated(
height: 35,
width: 70,
backgroundColor: AppColor.error,
textStyle: AppFonts.yekan14.copyWith(color: Colors.white),
onPressed: () {
onDateSelected(tempPickedDate ?? Jalali.now());
Get.back();
},
text: 'لغو',
),
SizedBox(width: 20),
],
),
),
Divider(height: 0, thickness: 1),
Expanded(
child: Container(
child: PersianCupertinoDatePicker(
initialDateTime: controller.saleDate.value,
mode: PersianCupertinoDatePickerMode.date,
onDateTimeChanged: (dateTime) {
tempPickedDate = dateTime;
},
),
),
),
],
),
);
}
}

View File

@@ -13,8 +13,7 @@ class SalesOutOfProvinceBuyersLogic extends GetxController {
SaleLogic get saleLogic => Get.find<SaleLogic>();
SalesOutOfProvinceLogic get saleOutOfProvince =>
Get.find<SalesOutOfProvinceLogic>();
SalesOutOfProvinceLogic get saleOutOfProvince => Get.find<SalesOutOfProvinceLogic>();
RxInt currentPage = 1.obs;
RxList<int> isExpandedList = <int>[].obs;
@@ -39,9 +38,12 @@ class SalesOutOfProvinceBuyersLogic extends GetxController {
Rx<Resource<PaginationModel<OutProvinceCarcassesBuyer>>> buyerList =
Resource<PaginationModel<OutProvinceCarcassesBuyer>>.loading().obs;
RxList<String> routesName = RxList();
@override
void onInit() {
super.onInit();
routesName.value = [...saleLogic.routesName, 'خریداران'].toList();
getOutProvinceCarcassesBuyer();
}
@@ -56,6 +58,8 @@ class SalesOutOfProvinceBuyersLogic extends GetxController {
(callback) => getOutProvinceCarcassesBuyer(),
time: Duration(milliseconds: timeDebounce),
);
setupListeners();
}
@override
@@ -70,14 +74,11 @@ class SalesOutOfProvinceBuyersLogic extends GetxController {
super.onClose();
}
Future<void> getOutProvinceCarcassesBuyer([
bool isLoadingMore = false,
]) async {
Future<void> getOutProvinceCarcassesBuyer([bool isLoadingMore = false]) async {
if (isLoadingMore) {
isLoadingMoreAllocationsMade.value = true;
} else {
buyerList.value =
Resource<PaginationModel<OutProvinceCarcassesBuyer>>.loading();
buyerList.value = Resource<PaginationModel<OutProvinceCarcassesBuyer>>.loading();
}
if (searchedValue.value != null &&
@@ -98,25 +99,19 @@ class SalesOutOfProvinceBuyersLogic extends GetxController {
value: searchedValue.value ?? '',
),
),
onError: (error, stackTrace) =>
isLoadingMoreAllocationsMade.value = false,
onError: (error, stackTrace) => isLoadingMoreAllocationsMade.value = false,
onSuccess: (res) {
if ((res?.count ?? 0) == 0) {
buyerList.value =
Resource<PaginationModel<OutProvinceCarcassesBuyer>>.empty();
buyerList.value = Resource<PaginationModel<OutProvinceCarcassesBuyer>>.empty();
} else {
buyerList.value =
Resource<PaginationModel<OutProvinceCarcassesBuyer>>.success(
PaginationModel<OutProvinceCarcassesBuyer>(
count: res?.count ?? 0,
next: res?.next,
previous: res?.previous,
results: [
...(buyerList.value.data?.results ?? []),
...(res?.results ?? []),
],
),
);
buyerList.value = Resource<PaginationModel<OutProvinceCarcassesBuyer>>.success(
PaginationModel<OutProvinceCarcassesBuyer>(
count: res?.count ?? 0,
next: res?.next,
previous: res?.previous,
results: [...(buyerList.value.data?.results ?? []), ...(res?.results ?? [])],
),
);
isLoadingMoreAllocationsMade.value = false;
}
@@ -135,9 +130,8 @@ class SalesOutOfProvinceBuyersLogic 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;
@@ -181,11 +175,10 @@ class SalesOutOfProvinceBuyersLogic extends GetxController {
mobile: buyerPhoneController.text,
role: 'Steward',
);
final res = await rootLogic.chickenRepository
.createOutProvinceCarcassesBuyer(
token: rootLogic.tokenService.accessToken.value!,
body: buyer,
);
final res = await rootLogic.chickenRepository.createOutProvinceCarcassesBuyer(
token: rootLogic.tokenService.accessToken.value!,
body: buyer,
);
},
onSuccess: (result) {
getOutProvinceCarcassesBuyer();
@@ -205,4 +198,14 @@ class SalesOutOfProvinceBuyersLogic extends GetxController {
selectedCity.value = IranProvinceCityModel(name: item.city);
isBuyerSubmitButtonEnabled.value = true;
}
void setSearchValue(String? value) {
searchedValue.value = value?.trim();
}
void submitFilter() {
fromDateFilter.value = fromDateFilter.value;
toDateFilter.value = toDateFilter.value;
getOutProvinceCarcassesBuyer();
}
}

View File

@@ -1,8 +1,11 @@
import 'package:flutter/material.dart';
import 'package:rasadyar_chicken/data/models/response/iran_province_city/iran_province_city_model.dart';
import 'package:rasadyar_chicken/data/models/response/out_province_carcasses_buyer/out_province_carcasses_buyer.dart';
import 'package:rasadyar_chicken/presentation/widget/base_page/view.dart';
import 'package:rasadyar_chicken/presentation/widget/filter_bottom_sheet.dart';
import 'package:rasadyar_chicken/presentation/widget/list_item/list_item.dart';
import 'package:rasadyar_chicken/presentation/widget/list_row_item.dart';
import 'package:rasadyar_chicken/presentation/widget/page_route.dart';
import 'package:rasadyar_core/core.dart';
import 'logic.dart';
@@ -12,36 +15,44 @@ class SalesOutOfProvinceBuyersPage extends GetView<SalesOutOfProvinceBuyersLogic
@override
Widget build(BuildContext context) {
return Scaffold(
body: ObxValue((data) {
return RPaginatedListView(
onLoadMore: () async => controller.getOutProvinceCarcassesBuyer(true),
onRefresh: () async {
controller.currentPage.value = 1;
await controller.getOutProvinceCarcassesBuyer();
},
hasMore: data.value.data?.next!= null,
listType: ListType.separated,
resource: data.value,
padding: EdgeInsets.fromLTRB(8, 8, 8, 80),
itemBuilder: (context, index) {
var item = data.value.data!.results![index];
return ObxValue((val) {
return ListItem2(
selected: val.contains(index),
onTap: () => controller.isExpandedList.toggle(index),
index: index,
child: itemListWidget(item),
secondChild: itemListExpandedWidget(item),
labelColor: AppColor.blueLight,
labelIcon: Assets.vec.userRaduisSvg.path,
);
}, controller.isExpandedList);
},
itemCount: data.value.data?.results?.length ?? 0,
separatorBuilder: (context, index) => SizedBox(height: 8.h),
);
}, controller.buyerList),
return BasePage(
routesWidget: ObxValue((route) => buildPageRoute(route), controller.routesName),
onBackPressed: () => Get.back(id: 1),
onSearchChanged: (data) => controller.setSearchValue(data),
filteringWidget: filterBottomSheet(),
widgets: [
Expanded(
child: ObxValue((data) {
return RPaginatedListView(
onLoadMore: () async => controller.getOutProvinceCarcassesBuyer(true),
onRefresh: () async {
controller.currentPage.value = 1;
await controller.getOutProvinceCarcassesBuyer();
},
hasMore: data.value.data?.next != null,
listType: ListType.separated,
resource: data.value,
padding: EdgeInsets.fromLTRB(8, 8, 8, 80),
itemBuilder: (context, index) {
var item = data.value.data!.results![index];
return ObxValue((val) {
return ListItem2(
selected: val.contains(index),
onTap: () => controller.isExpandedList.toggle(index),
index: index,
child: itemListWidget(item),
secondChild: itemListExpandedWidget(item),
labelColor: AppColor.blueLight,
labelIcon: Assets.vec.userRaduisSvg.path,
);
}, controller.isExpandedList);
},
itemCount: data.value.data?.results?.length ?? 0,
separatorBuilder: (context, index) => SizedBox(height: 8.h),
);
}, controller.buyerList),
),
],
floatingActionButton: RFab.add(
onPressed: () {
Get.bottomSheet(addOrEditBuyerBottomSheet(), isScrollControlled: true);
@@ -296,4 +307,12 @@ class SalesOutOfProvinceBuyersPage extends GetView<SalesOutOfProvinceBuyersLogic
),
);
}
Widget filterBottomSheet() => filterBottomSheetWidget(
fromDate: controller.fromDateFilter,
onChangedFromDate: (jalali) => controller.fromDateFilter.value = jalali,
toDate: controller.toDateFilter,
onChangedToDate: (jalali) => controller.toDateFilter.value = jalali,
onSubmit: () => controller.submitFilter(),
);
}

View File

@@ -82,10 +82,7 @@ class SegmentationLogic extends GetxController {
void validateForm() {
var weight = int.tryParse(weightController.text.clearComma.trim());
isSubmitButtonEnabled.value =
selectedProduct.value != null &&
weightController.text.isNotEmpty &&
weight! > 0
;
selectedProduct.value != null && weightController.text.isNotEmpty && weight! > 0;
}
Future<void> getAllSegmentation([bool isLoadingMore = false]) async {
@@ -155,7 +152,7 @@ class SegmentationLogic extends GetxController {
token: rootLogic.tokenService.accessToken.value!,
model: SegmentationModel(
key: selectedSegment.value?.key,
weight: int.tryParse(weightController.text) ?? 0,
weight: int.tryParse(weightController.text.clearComma) ?? 0,
),
),
onSuccess: (result) {
@@ -170,13 +167,16 @@ class SegmentationLogic extends GetxController {
Future<bool> createSegment() async {
var res = true;
SegmentationModel segmentationModel = SegmentationModel(
productKey: selectedProduct.value?.key,
weight: int.tryParse(weightController.text.clearComma) ?? 0,
);
iLog(segmentationModel.toString());
safeCall(
call: () async => await rootLogic.chickenRepository.createSegmentation(
token: rootLogic.tokenService.accessToken.value!,
model: SegmentationModel(
key: selectedProduct.value?.key,
weight: int.tryParse(weightController.text) ?? 0,
),
model: segmentationModel,
),
onSuccess: (result) {
res = true;

View File

@@ -283,7 +283,7 @@ class SegmentationPage extends GetView<SegmentationLogic> {
? await controller.editSegment()
: await controller.createSegment();
if (res) {
controller.getAllSegmentation();
await controller.getAllSegmentation();
controller.clearForm();
Get.back();
}

View File

@@ -50,22 +50,41 @@ class BasePage extends StatefulWidget {
class _BasePageState extends State<BasePage> {
BaseLogic get controller => Get.find<BaseLogic>();
Worker? filterWorker;
bool _isBottomSheetOpen = false;
@override
void initState() {
super.initState();
filterWorker = ever(controller.isFilterSelected, (bool isSelected) {
/* filterWorker = ever(controller.isFilterSelected, (bool isSelected) {
if (!mounted) return;
if (isSelected && widget.filteringWidget != null) {
// بررسی اینکه آیا bottomSheet از قبل باز است یا نه
if (_isBottomSheetOpen) {
controller.isFilterSelected.value = false;
return;
}
// بررسی اینکه آیا route فعلی current است یا نه
if (ModalRoute.of(context)?.isCurrent != true) {
controller.isFilterSelected.value = false;
return;
}
_isBottomSheetOpen = true;
Get.bottomSheet(
widget.filteringWidget!,
isScrollControlled: true,
isDismissible: true,
enableDrag: true,
).then((_) {
controller.isFilterSelected.value = false;
// تنظیم مقدار به false بعد از بسته شدن bottomSheet
if (mounted) {
_isBottomSheetOpen = false;
controller.isFilterSelected.value = false;
}
});
}
});
});*/
}
@override
@@ -73,6 +92,24 @@ class _BasePageState extends State<BasePage> {
filterWorker?.dispose();
super.dispose();
}
void _onFilterTap() {
if (widget.hasFilter && widget.filteringWidget != null) {
// بررسی اینکه آیا این route در top است یا نه
final currentRoute = ModalRoute.of(context);
if (currentRoute?.isCurrent != true) {
return;
}
// مستقیماً bottomSheet را باز کنید
Get.bottomSheet(
widget.filteringWidget!,
isScrollControlled: true,
isDismissible: true,
enableDrag: true,
);
}
}
@override
Widget build(BuildContext context) {
@@ -87,7 +124,7 @@ class _BasePageState extends State<BasePage> {
hasFilter: widget.hasFilter,
hasSearch: widget.hasSearch,
isBase: widget.isBase,
onFilterTap: widget.hasFilter ? () => controller.toggleFilter() : null,
onFilterTap: widget.hasFilter ? _onFilterTap : null,
onSearchTap: widget.hasSearch ? () => Get.find<SearchLogic>().toggleSearch() : null,
),
body: Column(

View File

@@ -15,12 +15,12 @@ class DioRemote implements IHttpClient {
if (kDebugMode) {
dio.interceptors.add(
PrettyDioLogger(
request: false,
enabled: false,
requestHeader: false,
responseHeader: false,
requestBody: false,
responseBody: false,
request: true,
enabled: true,
requestHeader: true,
responseHeader: true,
requestBody: true,
responseBody: true,
),
);
}