feat : information_card_widget and use it in poultry since

This commit is contained in:
2025-09-09 11:38:20 +03:30
parent 58bbe767fb
commit d03a1ee62e
4 changed files with 290 additions and 142 deletions

View File

@@ -34,7 +34,7 @@ Future<void> setupChickenDI() async {
await tokenService.saveAccessToken(Module.chicken, newToken);
},
clearTokenCallback: () async {
await tokenService.deleteAllTokens();
await tokenService.deleteModuleTokens(Module.chicken);
Get.offAllNamed(ChickenRoutes.auth, arguments: Module.chicken);
},
),

View File

@@ -2,6 +2,7 @@ import 'package:flutter/material.dart';
import 'package:rasadyar_chicken/data/models/response/poultry_science/home_poultry_science/home_poultry_science_model.dart';
import 'package:rasadyar_chicken/presentation/pages/poultry_science/root/logic.dart';
import 'package:rasadyar_core/core.dart';
import 'package:rasadyar_core/presentation/widget/custom/information_card_widget.dart';
class PoultryScienceHomeLogic extends GetxController {
PoultryScienceRootLogic rootLogic = Get.find<PoultryScienceRootLogic>();
@@ -53,7 +54,6 @@ class PoultryScienceHomeLogic extends GetxController {
iconColor: Color(0xFF5C4D64),
labelBgColor: Color(0xFFC8B8D1),
valueBgColor: Color(0xFFDAD4DD),
),
],
@@ -79,6 +79,27 @@ class PoultryScienceHomeLogic extends GetxController {
],
});
RxList<InformationCardData> ageCardData = [
InformationCardData(
labelTitle: 'بیشترین سن جوجه ریزی',
isLoading: true,
unit: 'روز',
labelVecIcon: Assets.vec.homeTrendUpSvg.path,
iconColor: const Color.fromRGBO(85, 97, 93, 1),
cardBgColor: const Color(0xFFE6FAF5),
labelBgColor: const Color(0xFFB0EFDF),
),
InformationCardData(
labelTitle: 'کمترین سن جوجه ریزی',
isLoading: true,
unit: 'روز',
labelVecIcon: Assets.vec.homeTrendDownSvg.path,
iconColor: const Color(0xFF6F6164),
cardBgColor: const Color(0xFFEDDCE0),
labelBgColor: const Color(0xFFE0BCC5),
),
].obs;
@override
void onReady() {
super.onReady();
@@ -145,6 +166,24 @@ class PoultryScienceHomeLogic extends GetxController {
return tag;
}
}).toList();
ageCardData.value = ageCardData.map((element) {
switch (element.labelTitle) {
case 'کمترین سن جوجه ریزی':
return element.copyWith(
value: result.hatchingMinAge?.separatedByComma ?? '0',
isLoading: false,
);
case 'بیشترین سن جوجه ریزی':
return element.copyWith(
value: result.hatchingMaxAge?.separatedByComma ?? '0',
isLoading: false,
);
default:
return element;
}
}).toList();
}
},
onError: (error, stackTrace) {},

View File

@@ -3,6 +3,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_core/core.dart';
import 'package:rasadyar_core/presentation/widget/custom/information_card_widget.dart';
import 'logic.dart';
@@ -133,44 +134,12 @@ class PoultryScienceHomePage extends GetView<PoultryScienceHomeLogic> {
),
secondTagInformation(),
thirdTagInformation(),
ageWidget(),
ageCardInformation(),
],
),
);
}
Widget ageWidget() {
return Padding(
padding: const EdgeInsets.fromLTRB(0, 8, 0, 13),
child: ObxValue((data) {
return Row(
mainAxisAlignment: MainAxisAlignment.center,
spacing: 8,
children: [
_informationIconCard(
title: 'کمترین سن جوجه ریزیط',
isLoading: data.value == null,
description: '${data.value?.hatchingMinAge.separatedByComma} روز' ?? '0',
iconPath: Assets.vec.homeTrendUpSvg.path,
iconColor: const Color.fromRGBO(85, 97, 93, 1),
bgDescriptionColor: const Color(0xFFE6FAF5),
bgLabelColor: const Color(0xFFB0EFDF),
),
_informationIconCard(
title: 'بیشترین سن جوجه ریزی',
description: '${data.value?.hatchingMaxAge.separatedByComma} روز' ?? '0',
iconPath: Assets.vec.homeTrendUpSvg.path,
iconColor: const Color(0xFF6F6164),
bgDescriptionColor: const Color(0xFFEDDCE0),
bgLabelColor: const Color(0xFFE0BCC5),
),
],
);
}, controller.homeInformation),
);
}
Widget firstTagInformation() {
return Padding(
padding: const EdgeInsets.fromLTRB(0, 8, 0, 13),
@@ -219,115 +188,18 @@ class PoultryScienceHomePage extends GetView<PoultryScienceHomeLogic> {
);
}
Container _informationIconCard({
required String title,
required String description,
String? unit,
bool isLoading = false,
required String iconPath,
required Color iconColor,
required Color bgDescriptionColor,
required Color bgLabelColor,
}) {
return Container(
height: 100.h,
width: 145.w,
decoration: BoxDecoration(borderRadius: BorderRadius.circular(8)),
clipBehavior: Clip.hardEdge,
child: Stack(
alignment: Alignment.topCenter,
children: [
Positioned(
bottom: 0,
right: 0,
left: 0,
child: Container(
height: 91,
decoration: BoxDecoration(
color: bgDescriptionColor,
borderRadius: BorderRadius.circular(8),
border: Border.all(width: 0.25, color: const Color(0xFFB4B4B4)),
),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
spacing: 4,
children: [
Text(
title,
textAlign: TextAlign.right,
style: AppFonts.yekan14.copyWith(color: AppColor.mediumGreyDarkActive),
),
isLoading
? Center(child: CupertinoActivityIndicator())
: Text(
description,
textAlign: TextAlign.right,
style: AppFonts.yekan16.copyWith(color: AppColor.mediumGreyDarkActive),
),
Visibility(
visible: unit != null,
child: Text(
unit ?? '',
textAlign: TextAlign.center,
style: AppFonts.yekan12.copyWith(color: AppColor.mediumGreyDarkActive),
),
),
],
),
),
),
Positioned(
top: 0,
child: Container(
width: 32,
height: 32,
decoration: ShapeDecoration(
color: bgLabelColor,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(30),
side: BorderSide(width: 0.25, color: const Color(0xFFD5D5D5)),
),
),
child: Center(
child: SvgGenImage.vec(iconPath).svg(
width: 24,
height: 24,
colorFilter: ColorFilter.mode(iconColor, BlendMode.srcIn),
),
),
),
),
],
),
);
}
Widget buildRow(String title, String value) {
Widget ageCardInformation() {
return Padding(
padding: const EdgeInsets.symmetric(vertical: 4.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Flexible(
flex: 2,
child: Text(
title,
textAlign: TextAlign.right,
style: AppFonts.yekan14.copyWith(color: AppColor.darkGreyDarkHover),
),
padding: EdgeInsets.fromLTRB(30.w, 8, 30.w, 13),
child: ObxValue((data) {
return Row(
spacing: 8,
children: List.generate(
data.length,
(index) => Expanded(child: InformationCard(data: data[index])),
),
Flexible(
flex: 1,
child: Text(
value,
textAlign: TextAlign.center,
style: AppFonts.yekan14.copyWith(color: AppColor.darkGreyDarkHover),
),
),
],
),
);
}, controller.ageCardData),
);
}

View File

@@ -0,0 +1,237 @@
import 'package:flutter/cupertino.dart';
import 'package:rasadyar_core/core.dart';
class InformationCardData {
//card
final BoxBorder? cardBorder;
final Color? cardBgColor;
final LinearGradient? cardGradient;
final int? widthLabel;
final int? heightLabel;
//label
final String? labelVecIcon;
final String? labelSvgIcon;
final String? labelTitle;
final Color? iconColor;
final Color? labelBgColor;
final Color? labelTitleColor;
final TextStyle? labelTitleStyle;
final LinearGradient? labelGradient;
final int? widthIcon;
final int? heightIcon;
final BoxBorder? labelBorder;
//value
final String? value;
final TextStyle? valueStyle;
final Color? valueColor;
final bool isLoading;
//unit
final String? unit;
final TextStyle? unitStyle;
final Color? unitColor;
//global
final int? width;
final int? height;
InformationCardData({
this.labelVecIcon,
this.labelBorder,
this.labelSvgIcon,
this.labelTitle,
this.cardBorder,
this.iconColor,
this.labelBgColor,
this.labelTitleColor,
this.labelTitleStyle,
this.labelGradient,
this.value,
this.valueStyle,
this.valueColor,
this.cardBgColor,
this.cardGradient,
this.isLoading = false,
this.unit,
this.unitStyle,
this.unitColor,
this.width,
this.height,
this.heightIcon,
this.widthIcon,
this.heightLabel,
this.widthLabel,
}) : assert(
(labelVecIcon != null) ^ (labelSvgIcon != null),
'Either labelVecIcon or labelSvgIcon must be provided, but not both.',
),
assert(isLoading || value != null, 'When isLoading is false, value must not be null.'),
assert(
(labelBgColor != null) ^ (labelGradient != null),
'Either labelBgColor or labelGradient must be provided, but not both.',
),
assert(
(cardBgColor != null) ^ (cardGradient != null),
'Either valueBgColor or valueGradient must be provided, but not both.',
);
/// copyWith method
InformationCardData copyWith({
String? labelVecIcon,
String? labelSvgIcon,
String? labelTitle,
Color? iconColor,
Color? labelBgColor,
Color? labelTitleColor,
TextStyle? labelTitleStyle,
LinearGradient? labelGradient,
int? widthIcon,
int? heightIcon,
String? value,
TextStyle? valueStyle,
Color? valueColor,
Color? cardBgColor,
LinearGradient? cardGradient,
bool? isLoading,
String? unit,
TextStyle? unitStyle,
Color? unitColor,
int? width,
int? height,
BoxBorder? labelBorder,
BoxBorder? cardBorder,
int? heightLabel,
int? widthLabel,
}) {
return InformationCardData(
labelVecIcon: labelVecIcon ?? this.labelVecIcon,
labelSvgIcon: labelSvgIcon ?? this.labelSvgIcon,
labelTitle: labelTitle ?? this.labelTitle,
iconColor: iconColor ?? this.iconColor,
labelBgColor: labelBgColor ?? this.labelBgColor,
labelTitleColor: labelTitleColor ?? this.labelTitleColor,
labelTitleStyle: labelTitleStyle ?? this.labelTitleStyle,
labelGradient: labelGradient ?? this.labelGradient,
widthIcon: widthIcon ?? this.widthIcon,
heightIcon: heightIcon ?? this.heightIcon,
value: value ?? this.value,
valueStyle: valueStyle ?? this.valueStyle,
valueColor: valueColor ?? this.valueColor,
cardBgColor: cardBgColor ?? this.cardBgColor,
cardGradient: cardGradient ?? this.cardGradient,
isLoading: isLoading ?? this.isLoading,
unit: unit ?? this.unit,
unitStyle: unitStyle ?? this.unitStyle,
unitColor: unitColor ?? this.unitColor,
width: width ?? this.width,
height: height ?? this.height,
labelBorder: labelBorder ?? this.labelBorder,
cardBorder: cardBorder ?? this.cardBorder,
heightLabel: heightLabel ?? this.heightLabel,
widthLabel: widthLabel ?? this.widthLabel,
);
}
@override
String toString() {
return 'InformationCardData{cardBorder: $cardBorder, cardBgColor: $cardBgColor, cardGradient: $cardGradient, widthLabel: $widthLabel, heightLabel: $heightLabel, labelVecIcon: $labelVecIcon, labelSvgIcon: $labelSvgIcon, labelTitle: $labelTitle, iconColor: $iconColor, labelBgColor: $labelBgColor, labelTitleColor: $labelTitleColor, labelTitleStyle: $labelTitleStyle, labelGradient: $labelGradient, widthIcon: $widthIcon, heightIcon: $heightIcon, labelBorder: $labelBorder, value: $value, valueStyle: $valueStyle, valueColor: $valueColor, isLoading: $isLoading, unit: $unit, unitStyle: $unitStyle, unitColor: $unitColor, width: $width, height: $height}';
}
}
class InformationCard extends StatelessWidget {
const InformationCard({super.key, required this.data});
final InformationCardData data;
@override
Widget build(BuildContext context) {
return Container(
height: (data.width ?? 100).h,
width: (data.height ?? 165).w,
decoration: BoxDecoration(borderRadius: BorderRadius.circular(8)),
clipBehavior: Clip.none,
child: Stack(
alignment: Alignment.topCenter,
clipBehavior: Clip.none,
children: [
Positioned(
bottom: 0,
right: 0,
left: 0,
child: Container(
height: 91.h,
decoration: BoxDecoration(
color: data.cardBgColor,
gradient: data.cardGradient,
borderRadius: BorderRadius.circular(8),
border: Border.all(width: 0.25, color: const Color(0xFFB4B4B4)),
),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
spacing: 8.h,
children: [
Text(
data.labelTitle ?? '',
textAlign: TextAlign.right,
style:
data.labelTitleStyle ??
AppFonts.yekan14.copyWith(
color: data.labelTitleColor ?? AppColor.mediumGreyDarkActive,
),
),
data.isLoading
? CupertinoActivityIndicator()
: Text(
'${data.value} ${data.unit} ',
textAlign: TextAlign.center,
style:
data.valueStyle ??
AppFonts.yekan12.copyWith(
color: data.valueColor ?? AppColor.mediumGreyDarkActive,
),
),
],
),
),
),
Positioned(
top: -7,
child: Container(
width: (data.widthLabel ?? 32).w,
height: (data.heightLabel ?? 32).h,
decoration: ShapeDecoration(
color: data.labelBgColor,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(30),
side: BorderSide(width: 0.25, color: const Color(0xFFD5D5D5)),
),
),
child: Center(
child: data.labelVecIcon != null
? SvgGenImage.vec(data.labelVecIcon!).svg(
width: (data.widthIcon ?? 24).w,
height: (data.heightIcon ?? 24).h,
colorFilter: ColorFilter.mode(
data.iconColor ?? AppColor.mediumGreyDarkActive,
BlendMode.srcIn,
),
)
: SvgGenImage(data.labelSvgIcon!).svg(
width: (data.widthIcon ?? 24).w,
height: (data.heightIcon ?? 24).h,
colorFilter: ColorFilter.mode(
data.iconColor ?? AppColor.mediumGreyDarkActive,
BlendMode.srcIn,
),
),
),
),
),
],
),
);
}
}