refactor: update SDUIFormWidget error handling, enhance StepperSDUI with state management and scrolling behavior, and clean up SDUIWidgetModel documentation
This commit is contained in:
@@ -255,7 +255,7 @@ class SDUIFormWidget extends StatelessWidget {
|
|||||||
iLog('Stack trace: $stackTrace');
|
iLog('Stack trace: $stackTrace');
|
||||||
return Container(
|
return Container(
|
||||||
padding: EdgeInsets.all(16),
|
padding: EdgeInsets.all(16),
|
||||||
color: Colors.orange.withOpacity(0.1),
|
color: Colors.orange.withAlpha(10),
|
||||||
child: Text('Card Error: $e'),
|
child: Text('Card Error: $e'),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -526,7 +526,7 @@ class SDUIFormWidget extends StatelessWidget {
|
|||||||
iLog('Error building stepper: $e');
|
iLog('Error building stepper: $e');
|
||||||
iLog('Stack trace: $stackTrace');
|
iLog('Stack trace: $stackTrace');
|
||||||
return Container(
|
return Container(
|
||||||
padding: EdgeInsets.all(16),
|
padding: EdgeInsets.symmetric(horizontal: 16),
|
||||||
color: Colors.orange.withAlpha(10),
|
color: Colors.orange.withAlpha(10),
|
||||||
child: Text('Stepper Error: $e'),
|
child: Text('Stepper Error: $e'),
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -0,0 +1,640 @@
|
|||||||
|
{
|
||||||
|
"info": {
|
||||||
|
"type": "column",
|
||||||
|
"visible": true,
|
||||||
|
"visible_condition": null,
|
||||||
|
"spacing": 30.0,
|
||||||
|
"children": [
|
||||||
|
{
|
||||||
|
"type": "stepper",
|
||||||
|
"visible": true,
|
||||||
|
"visible_condition": null,
|
||||||
|
"data": {
|
||||||
|
"key": "activeStepperIndex",
|
||||||
|
"total_steps": 2,
|
||||||
|
"active_step": 0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "card_label_item",
|
||||||
|
"visible": true,
|
||||||
|
"visible_condition": "activeStepperIndex == 0",
|
||||||
|
"data": {
|
||||||
|
"title": "اطلاعات پایه واحد",
|
||||||
|
"padding_horizontal": 12.0,
|
||||||
|
"padding_vertical": 11.0
|
||||||
|
},
|
||||||
|
"child": {
|
||||||
|
"type": "column",
|
||||||
|
"visible": true,
|
||||||
|
"visible_condition": null,
|
||||||
|
"spacing": 10.0,
|
||||||
|
"children": [
|
||||||
|
{
|
||||||
|
"type": "text_form_field",
|
||||||
|
"visible": true,
|
||||||
|
"visible_condition": null,
|
||||||
|
"data": {
|
||||||
|
"key": "unit_name",
|
||||||
|
"label": "نام واحد مرغداری",
|
||||||
|
"keyboard_type": "text",
|
||||||
|
"readonly": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "text_form_field",
|
||||||
|
"visible": true,
|
||||||
|
"visible_condition": null,
|
||||||
|
"data": {
|
||||||
|
"key": "breeding_unique_id",
|
||||||
|
"label": "کد یکتا / شناسه واحد",
|
||||||
|
"keyboard_type": "text",
|
||||||
|
"readonly": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "text_form_field",
|
||||||
|
"visible": true,
|
||||||
|
"visible_condition": null,
|
||||||
|
"data": {
|
||||||
|
"key": "health_license",
|
||||||
|
"label": "پروانه بهداشتی",
|
||||||
|
"keyboard_type": "text"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "text_form_field",
|
||||||
|
"visible": true,
|
||||||
|
"visible_condition": null,
|
||||||
|
"data": {
|
||||||
|
"key": "tenant_status",
|
||||||
|
"label": "وضعیت مستاجر",
|
||||||
|
"keyboard_type": "text"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "text_form_field",
|
||||||
|
"visible": true,
|
||||||
|
"visible_condition": "tenant_status == 'دارد'",
|
||||||
|
"data": {
|
||||||
|
"key": "tenant_name",
|
||||||
|
"label": "نام مستاجر",
|
||||||
|
"keyboard_type": "text"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "text_form_field",
|
||||||
|
"visible": true,
|
||||||
|
"visible_condition": "tenant_status == 'دارد'",
|
||||||
|
"data": {
|
||||||
|
"key": "tenant_national_id",
|
||||||
|
"label": "کد ملی مستاجر",
|
||||||
|
"keyboard_type": "text"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "text_form_field",
|
||||||
|
"visible": true,
|
||||||
|
"visible_condition": "tenant_status == 'دارد'",
|
||||||
|
"data": {
|
||||||
|
"key": "tenant_phone_number",
|
||||||
|
"label": "شماره تماس مستاجر",
|
||||||
|
"keyboard_type": "text"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "text_form_field",
|
||||||
|
"visible": true,
|
||||||
|
"visible_condition": null,
|
||||||
|
"data": {
|
||||||
|
"key": "owner_national_code",
|
||||||
|
"label": "کد ملی بهرهبردار",
|
||||||
|
"keyboard_type": "text",
|
||||||
|
"readonly": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "text_form_field",
|
||||||
|
"visible": true,
|
||||||
|
"visible_condition": null,
|
||||||
|
"data": {
|
||||||
|
"key": "owner_phone_number",
|
||||||
|
"label": "شماره تماس بهرهبردار",
|
||||||
|
"keyboard_type": "text",
|
||||||
|
"readonly": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "text_form_field",
|
||||||
|
"visible": true,
|
||||||
|
"visible_condition": null,
|
||||||
|
"data": {
|
||||||
|
"key": "total_capacity",
|
||||||
|
"label": "ظرفیت اسمی سالنها",
|
||||||
|
"keyboard_type": "number",
|
||||||
|
"comma_separator": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "card_label_item",
|
||||||
|
"visible": true,
|
||||||
|
"visible_condition": "activeStepperIndex == 0",
|
||||||
|
"data": {
|
||||||
|
"title": "اطلاعات جوجه ریزی",
|
||||||
|
"padding_horizontal": 12.0,
|
||||||
|
"padding_vertical": 11.0
|
||||||
|
},
|
||||||
|
"child": {
|
||||||
|
"type": "column",
|
||||||
|
"visible": true,
|
||||||
|
"visible_condition": null,
|
||||||
|
"spacing": 10.0,
|
||||||
|
"children": [
|
||||||
|
{
|
||||||
|
"type": "text_form_field",
|
||||||
|
"visible": true,
|
||||||
|
"visible_condition": null,
|
||||||
|
"data": {
|
||||||
|
"key": "hatching_date",
|
||||||
|
"label": "تاریخ جوجه ریزی",
|
||||||
|
"keyboard_type": "text",
|
||||||
|
"readonly": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "text_form_field",
|
||||||
|
"visible": true,
|
||||||
|
"visible_condition": null,
|
||||||
|
"data": {
|
||||||
|
"key": "visit_date",
|
||||||
|
"label": "تاریخ بازدید",
|
||||||
|
"keyboard_type": "text",
|
||||||
|
"readonly": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "text_form_field",
|
||||||
|
"visible": true,
|
||||||
|
"visible_condition": null,
|
||||||
|
"data": {
|
||||||
|
"key": "hatching_count",
|
||||||
|
"label": "تعداد جوجهریزی اولیه",
|
||||||
|
"keyboard_type": "number",
|
||||||
|
"readonly": true,
|
||||||
|
"comma_separator": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "text_form_field",
|
||||||
|
"visible": true,
|
||||||
|
"visible_condition": null,
|
||||||
|
"data": {
|
||||||
|
"key": "hatching_breed",
|
||||||
|
"label": "نوع نژاد",
|
||||||
|
"keyboard_type": "text"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "text_form_field",
|
||||||
|
"visible": true,
|
||||||
|
"visible_condition": null,
|
||||||
|
"data": {
|
||||||
|
"key": "hatching_average_weight",
|
||||||
|
"label": "میانگین وزن جوجه",
|
||||||
|
"keyboard_type": "number",
|
||||||
|
"comma_separator": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "image_picker",
|
||||||
|
"visible": true,
|
||||||
|
"visible_condition": null,
|
||||||
|
"data": {
|
||||||
|
"key": "pultry_images",
|
||||||
|
"label": "تعداد موجود فعلی"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "chip_selection",
|
||||||
|
"visible": true,
|
||||||
|
"visible_condition": null,
|
||||||
|
"data": {
|
||||||
|
"key": "sanitary_condition_of_the_hall",
|
||||||
|
"label": "وضعیت بهداشتی سالن",
|
||||||
|
"selectedIndex": -1,
|
||||||
|
"options": [
|
||||||
|
{
|
||||||
|
"index": 0,
|
||||||
|
"label": "عالی",
|
||||||
|
"value": "عالی"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"index": 1,
|
||||||
|
"label": "خوب",
|
||||||
|
"value": "خوب"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"index": 2,
|
||||||
|
"label": "متوسط",
|
||||||
|
"value": "متوسط"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"index": 3,
|
||||||
|
"label": "ضعیف",
|
||||||
|
"value": "ضعیف"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "chip_selection",
|
||||||
|
"visible": true,
|
||||||
|
"visible_condition": null,
|
||||||
|
"data": {
|
||||||
|
"key": "ventilation_status",
|
||||||
|
"label": "وضعیت تهویه",
|
||||||
|
"selectedIndex": -1,
|
||||||
|
"options": [
|
||||||
|
{
|
||||||
|
"index": 0,
|
||||||
|
"label": "عالی",
|
||||||
|
"value": "عالی"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"index": 1,
|
||||||
|
"label": "خوب",
|
||||||
|
"value": "خوب"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"index": 2,
|
||||||
|
"label": "متوسط",
|
||||||
|
"value": "متوسط"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"index": 3,
|
||||||
|
"label": "ضعیف",
|
||||||
|
"value": "ضعیف"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "chip_selection",
|
||||||
|
"visible": true,
|
||||||
|
"visible_condition": null,
|
||||||
|
"data": {
|
||||||
|
"key": "bedding_status",
|
||||||
|
"label": "وضعیت بستر",
|
||||||
|
"selectedIndex": -1,
|
||||||
|
"options": [
|
||||||
|
{
|
||||||
|
"index": 0,
|
||||||
|
"label": "خشک",
|
||||||
|
"value": "خشک"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"index": 1,
|
||||||
|
"label": "نیمهمرطوب",
|
||||||
|
"value": "نیمهمرطوب"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"index": 2,
|
||||||
|
"label": "مرطوب",
|
||||||
|
"value": "مرطوب"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "text_form_field",
|
||||||
|
"visible": true,
|
||||||
|
"visible_condition": null,
|
||||||
|
"data": {
|
||||||
|
"key": "hatching_temperature",
|
||||||
|
"label": "دمای سالن",
|
||||||
|
"keyboard_type": "number"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "card_label_item",
|
||||||
|
"visible": true,
|
||||||
|
"visible_condition": "activeStepperIndex == 1",
|
||||||
|
"data": {
|
||||||
|
"title": "وضعیت عمومی سالن",
|
||||||
|
"padding_horizontal": 12.0,
|
||||||
|
"padding_vertical": 11.0
|
||||||
|
},
|
||||||
|
"child": {
|
||||||
|
"type": "column",
|
||||||
|
"visible": true,
|
||||||
|
"visible_condition": null,
|
||||||
|
"spacing": 10.0,
|
||||||
|
"children": [
|
||||||
|
{
|
||||||
|
"type": "image_picker",
|
||||||
|
"visible": true,
|
||||||
|
"visible_condition": null,
|
||||||
|
"data": {
|
||||||
|
"key": "pultry_images",
|
||||||
|
"label": "تعداد موجود فعلی"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "chip_selection",
|
||||||
|
"visible": true,
|
||||||
|
"visible_condition": null,
|
||||||
|
"data": {
|
||||||
|
"key": "sanitary_condition_of_the_hall",
|
||||||
|
"label": "وضعیت بهداشتی سالن",
|
||||||
|
"selectedIndex": -1,
|
||||||
|
"options": [
|
||||||
|
{
|
||||||
|
"index": 0,
|
||||||
|
"label": "عالی",
|
||||||
|
"value": "عالی"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"index": 1,
|
||||||
|
"label": "خوب",
|
||||||
|
"value": "خوب"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"index": 2,
|
||||||
|
"label": "متوسط",
|
||||||
|
"value": "متوسط"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"index": 3,
|
||||||
|
"label": "ضعیف",
|
||||||
|
"value": "ضعیف"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "chip_selection",
|
||||||
|
"visible": true,
|
||||||
|
"visible_condition": null,
|
||||||
|
"data": {
|
||||||
|
"key": "ventilation_status",
|
||||||
|
"label": "وضعیت تهویه",
|
||||||
|
"selectedIndex": -1,
|
||||||
|
"options": [
|
||||||
|
{
|
||||||
|
"index": 0,
|
||||||
|
"label": "عالی",
|
||||||
|
"value": "عالی"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"index": 1,
|
||||||
|
"label": "خوب",
|
||||||
|
"value": "خوب"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"index": 2,
|
||||||
|
"label": "متوسط",
|
||||||
|
"value": "متوسط"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"index": 3,
|
||||||
|
"label": "ضعیف",
|
||||||
|
"value": "ضعیف"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "chip_selection",
|
||||||
|
"visible": true,
|
||||||
|
"visible_condition": null,
|
||||||
|
"data": {
|
||||||
|
"key": "bedding_status",
|
||||||
|
"label": "وضعیت بستر",
|
||||||
|
"selectedIndex": -1,
|
||||||
|
"options": [
|
||||||
|
{
|
||||||
|
"index": 0,
|
||||||
|
"label": "خشک",
|
||||||
|
"value": "خشک"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"index": 1,
|
||||||
|
"label": "نیمهمرطوب",
|
||||||
|
"value": "نیمهمرطوب"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"index": 2,
|
||||||
|
"label": "مرطوب",
|
||||||
|
"value": "مرطوب"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "text_form_field",
|
||||||
|
"visible": true,
|
||||||
|
"visible_condition": null,
|
||||||
|
"data": {
|
||||||
|
"key": "hatching_temperature",
|
||||||
|
"label": "دمای سالن",
|
||||||
|
"keyboard_type": "number"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "chip_selection",
|
||||||
|
"visible": true,
|
||||||
|
"visible_condition": null,
|
||||||
|
"data": {
|
||||||
|
"key": "water_quality",
|
||||||
|
"label": "آب مصرفی",
|
||||||
|
"selectedIndex": -1,
|
||||||
|
"options": [
|
||||||
|
{
|
||||||
|
"index": 0,
|
||||||
|
"label": "چاه",
|
||||||
|
"value": "چاه"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"index": 1,
|
||||||
|
"label": "شهری",
|
||||||
|
"value": "شهری"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"index": 2,
|
||||||
|
"label": "تصفیهشده",
|
||||||
|
"value": "تصفیهشده"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"index": 3,
|
||||||
|
"label": "حمل تانکر",
|
||||||
|
"value": "حمل تانکر"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "text_form_field",
|
||||||
|
"visible": true,
|
||||||
|
"visible_condition": null,
|
||||||
|
"data": {
|
||||||
|
"key": "water_hardness",
|
||||||
|
"label": "درصد سختی آب (PPM)",
|
||||||
|
"keyboard_type": "number",
|
||||||
|
"decimal": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "card_label_item",
|
||||||
|
"visible": true,
|
||||||
|
"visible_condition": "activeStepperIndex == 1",
|
||||||
|
"data": {
|
||||||
|
"title": "تلفات",
|
||||||
|
"padding_horizontal": 12.0,
|
||||||
|
"padding_vertical": 11.0
|
||||||
|
},
|
||||||
|
"child": {
|
||||||
|
"type": "column",
|
||||||
|
"visible": true,
|
||||||
|
"visible_condition": null,
|
||||||
|
"spacing": 10.0,
|
||||||
|
"children": [
|
||||||
|
{
|
||||||
|
"type": "text_form_field",
|
||||||
|
"visible": true,
|
||||||
|
"visible_condition": null,
|
||||||
|
"data": {
|
||||||
|
"key": "normal_losses",
|
||||||
|
"label": "تعداد تلفات عادی دوره",
|
||||||
|
"keyboard_type": "number",
|
||||||
|
"comma_separator": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "text_form_field",
|
||||||
|
"visible": true,
|
||||||
|
"visible_condition": null,
|
||||||
|
"data": {
|
||||||
|
"key": "abnormal_losses",
|
||||||
|
"label": "تلفات غیرعادی",
|
||||||
|
"keyboard_type": "number",
|
||||||
|
"comma_separator": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "dropdown",
|
||||||
|
"visible": true,
|
||||||
|
"visible_condition": null,
|
||||||
|
"data": {
|
||||||
|
"key": "cause_of_unusual_casualties",
|
||||||
|
"label": "علت تلفات غیرعادی",
|
||||||
|
"placeholder": "علت تلفات غیرعادی",
|
||||||
|
"items": [
|
||||||
|
"بیماری",
|
||||||
|
"قطعی برق",
|
||||||
|
"استرس گرمایی",
|
||||||
|
"مشکلات دان",
|
||||||
|
"کیفیت جوجه",
|
||||||
|
"سایر (شرح…)"
|
||||||
|
],
|
||||||
|
"selectedValue": null,
|
||||||
|
"enabled": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "text_form_field",
|
||||||
|
"visible": true,
|
||||||
|
"visible_condition": "cause_of_unusual_casualties == 'سایر (شرح…)'",
|
||||||
|
"data": {
|
||||||
|
"key": "other_cause_of_unusual_casualties",
|
||||||
|
"label": "علت تلفات غیرعادی",
|
||||||
|
"keyboard_type": "text"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "dropdown",
|
||||||
|
"visible": true,
|
||||||
|
"visible_condition": null,
|
||||||
|
"data": {
|
||||||
|
"key": "type_of_disease",
|
||||||
|
"label": "نوع بیماری تشخیص دادهشده / مشکوک",
|
||||||
|
"placeholder": "نوع بیماری تشخیص دادهشده / مشکوک",
|
||||||
|
"items": [
|
||||||
|
"آنفلوانزا",
|
||||||
|
"نیوکاسل",
|
||||||
|
"IB",
|
||||||
|
"عفونتهای باکتریایی",
|
||||||
|
"مشکلات گوارشی",
|
||||||
|
"سایر (شرح)"
|
||||||
|
],
|
||||||
|
"selectedValue": null,
|
||||||
|
"enabled": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "text_form_field",
|
||||||
|
"visible": true,
|
||||||
|
"visible_condition": "type_of_disease == 'سایر (شرح)'",
|
||||||
|
"data": {
|
||||||
|
"key": "other_type_of_disease",
|
||||||
|
"label": "نوع بیماری",
|
||||||
|
"keyboard_type": "text"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "dropdown",
|
||||||
|
"visible": true,
|
||||||
|
"visible_condition": null,
|
||||||
|
"data": {
|
||||||
|
"key": "sampling_done",
|
||||||
|
"label": "نمونهبرداری انجامشده",
|
||||||
|
"placeholder": "نمونهبرداری انجامشده",
|
||||||
|
"items": [
|
||||||
|
"انجام شد",
|
||||||
|
"انجام نشد"
|
||||||
|
],
|
||||||
|
"selectedValue": null,
|
||||||
|
"enabled": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "chip_selection",
|
||||||
|
"visible": true,
|
||||||
|
"visible_condition": "sampling_done == 'انجام شد'",
|
||||||
|
"data": {
|
||||||
|
"key": "sample_type",
|
||||||
|
"label": "نوع نمونه",
|
||||||
|
"selectedIndex": -1,
|
||||||
|
"options": [
|
||||||
|
{
|
||||||
|
"index": 0,
|
||||||
|
"label": "لاشه",
|
||||||
|
"value": "لاشه"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"index": 1,
|
||||||
|
"label": "آب",
|
||||||
|
"value": "آب"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"index": 2,
|
||||||
|
"label": "دانه",
|
||||||
|
"value": "دانه"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -95,7 +95,7 @@ sealed class SDUIWidgetModel with _$SDUIWidgetModel {
|
|||||||
String? visibleCondition,
|
String? visibleCondition,
|
||||||
}) = _SizedBox;
|
}) = _SizedBox;
|
||||||
|
|
||||||
// تبدیل مستقیم JSON به مدل بدون هیچ واسطهای
|
|
||||||
factory SDUIWidgetModel.fromJson(Map<String, dynamic> json) =>
|
factory SDUIWidgetModel.fromJson(Map<String, dynamic> json) =>
|
||||||
_$SDUIWidgetModelFromJson(json);
|
_$SDUIWidgetModelFromJson(json);
|
||||||
|
|
||||||
|
|||||||
@@ -2,40 +2,91 @@ import 'package:flutter/material.dart';
|
|||||||
import 'package:rasadyar_chicken/presentation/widget/sdui/widgets/stepper/model/stepper_sdui_model.dart';
|
import 'package:rasadyar_chicken/presentation/widget/sdui/widgets/stepper/model/stepper_sdui_model.dart';
|
||||||
import 'package:rasadyar_core/core.dart';
|
import 'package:rasadyar_core/core.dart';
|
||||||
|
|
||||||
class StepperSDUI extends StatelessWidget {
|
class StepperSDUI extends StatefulWidget {
|
||||||
final StepperSDUIModel model;
|
final StepperSDUIModel model;
|
||||||
final RxMap<String, dynamic>? state;
|
final RxMap<String, dynamic>? state;
|
||||||
|
|
||||||
const StepperSDUI({super.key, required this.model, this.state});
|
const StepperSDUI({super.key, required this.model, this.state});
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<StepperSDUI> createState() => _StepperSDUIState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _StepperSDUIState extends State<StepperSDUI> {
|
||||||
|
late final ScrollController _scrollController;
|
||||||
|
List<GlobalKey>? itemKeys;
|
||||||
|
int? _lastActiveStep;
|
||||||
|
late int totalSteps;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
_scrollController = ScrollController();
|
||||||
|
totalSteps = widget.model.totalSteps ?? 1;
|
||||||
|
itemKeys = List.generate(totalSteps, (index) => GlobalKey());
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
_scrollController.dispose();
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final totalSteps = model.totalSteps ?? 5;
|
|
||||||
|
|
||||||
|
// Update keys if totalSteps changed
|
||||||
|
if (itemKeys == null || itemKeys!.length != totalSteps) {
|
||||||
|
itemKeys = List.generate(totalSteps, (index) => GlobalKey());
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((totalSteps * 24.w + ((totalSteps - 1) * (40.w))) < Get.width) {
|
||||||
|
return Obx(() {
|
||||||
|
final activeStep =
|
||||||
|
widget.state?[widget.model.key] as int? ??
|
||||||
|
widget.model.activeStep ??
|
||||||
|
0;
|
||||||
|
return Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
|
children: _buildSteps(totalSteps, activeStep),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
return Obx(() {
|
return Obx(() {
|
||||||
final activeStep = state?[model.key] as int? ?? model.activeStep ?? 0;
|
final activeStep =
|
||||||
|
widget.state?[widget.model.key] as int? ??
|
||||||
|
widget.model.activeStep ??
|
||||||
|
0;
|
||||||
|
|
||||||
return SingleChildScrollView(
|
// Scroll to active step if it changed
|
||||||
scrollDirection: Axis.horizontal,
|
if (_lastActiveStep != activeStep) {
|
||||||
child: Directionality(
|
_lastActiveStep = activeStep;
|
||||||
textDirection: TextDirection.ltr,
|
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||||
child: SizedBox(
|
scrollToActive(activeStep);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return SizedBox(
|
||||||
height: 30.h,
|
height: 30.h,
|
||||||
width: Get.width,
|
child: SingleChildScrollView(
|
||||||
child: Row(children: _buildSteps(totalSteps, activeStep)),
|
controller: _scrollController,
|
||||||
),
|
scrollDirection: Axis.horizontal,
|
||||||
|
child: Row(children: _buildScrolledSteps(totalSteps, activeStep)),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
List<Widget> _buildSteps(int totalSteps, int activeStep) {
|
List<Widget> _buildScrolledSteps(int totalSteps, int activeStep) {
|
||||||
final List<Widget> widgets = [];
|
final List<Widget> widgets = [];
|
||||||
|
|
||||||
for (int i = 0; i < totalSteps; i++) {
|
for (int i = 0; i < totalSteps; i++) {
|
||||||
// Add step circle
|
// Add step circle
|
||||||
widgets.add(
|
widgets.add(
|
||||||
Container(
|
Container(
|
||||||
|
key: itemKeys?[i],
|
||||||
alignment: Alignment.center,
|
alignment: Alignment.center,
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: activeStep >= i
|
color: activeStep >= i
|
||||||
@@ -73,4 +124,84 @@ class StepperSDUI extends StatelessWidget {
|
|||||||
|
|
||||||
return widgets;
|
return widgets;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
List<Widget> _buildSteps(int totalSteps, int activeStep) {
|
||||||
|
final List<Widget> widgets = [];
|
||||||
|
double space = 0;
|
||||||
|
|
||||||
|
if (totalSteps < 2) {
|
||||||
|
space = 0;
|
||||||
|
} else if (totalSteps == 2) {
|
||||||
|
space = Get.width - (2 * (24.w)) - (51.w);
|
||||||
|
} else {
|
||||||
|
space = ((Get.width - (51.w)) - (totalSteps * (24.w))) / (totalSteps - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < totalSteps; i++) {
|
||||||
|
// Add step circle
|
||||||
|
widgets.add(
|
||||||
|
Container(
|
||||||
|
key: itemKeys?[i],
|
||||||
|
alignment: Alignment.center,
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: activeStep >= i
|
||||||
|
? AppColor.greenNormalHover
|
||||||
|
: AppColor.whiteNormalActive,
|
||||||
|
shape: BoxShape.circle,
|
||||||
|
),
|
||||||
|
width: 24.w,
|
||||||
|
height: 24.h,
|
||||||
|
child: Text(
|
||||||
|
'${i + 1}',
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
style: AppFonts.yekan16.copyWith(
|
||||||
|
color: activeStep >= i ? Colors.white : AppColor.iconColor,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
// Add divider between steps (except after last step)
|
||||||
|
if (i < totalSteps - 1) {
|
||||||
|
widgets.add(
|
||||||
|
SizedBox(
|
||||||
|
width: space,
|
||||||
|
child: Divider(
|
||||||
|
color: activeStep >= i + 1
|
||||||
|
? AppColor.greenNormalHover
|
||||||
|
: AppColor.whiteNormalActive,
|
||||||
|
thickness: 8,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return widgets;
|
||||||
|
}
|
||||||
|
|
||||||
|
void scrollToActive(int index) {
|
||||||
|
if (itemKeys == null || index < 0 || index >= itemKeys!.length) return;
|
||||||
|
|
||||||
|
final context = itemKeys![index].currentContext;
|
||||||
|
if (context != null) {
|
||||||
|
Scrollable.ensureVisible(
|
||||||
|
context,
|
||||||
|
duration: const Duration(milliseconds: 400),
|
||||||
|
curve: Curves.easeInOut,
|
||||||
|
alignment: 0.5, // دکمه بیاد وسط صفحه
|
||||||
|
);
|
||||||
|
} else if (_scrollController.hasClients) {
|
||||||
|
// Fallback: calculate position manually
|
||||||
|
final double itemWidth = 24.w + 40.w; // step width + divider width
|
||||||
|
final double targetOffset =
|
||||||
|
(index * itemWidth) - (Get.width / 2) + (24.w / 2);
|
||||||
|
final double maxScroll = _scrollController.position.maxScrollExtent;
|
||||||
|
_scrollController.animateTo(
|
||||||
|
targetOffset.clamp(0.0, maxScroll),
|
||||||
|
duration: const Duration(milliseconds: 400),
|
||||||
|
curve: Curves.easeInOut,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user