refactor: update text form field model to use dynamic value type, enhance condition evaluator for step index extraction, and improve SDK path formatting

This commit is contained in:
2026-01-07 15:57:01 +03:30
parent 17f8a2d79b
commit f25b8514cd
10 changed files with 568 additions and 1589 deletions

View File

@@ -1,5 +1,5 @@
import 'package:rasadyar_chicken/features/poultry_science/data/model/response/poultry_science_report/poultry_science_report.dart';
import 'package:rasadyar_chicken/features/poultry_science/data/model/request/submit_inspection/submit_inspection_response.dart';
import 'package:rasadyar_chicken/features/poultry_science/data/model/response/poultry_science_report/poultry_science_report.dart';
import 'package:rasadyar_chicken/features/vet_farm/data/datasources/remote/vet_farm_remote_data_source.dart';
import 'package:rasadyar_core/core.dart';
@@ -38,11 +38,9 @@ class VetFarmRemoteDataSourceImpl implements VetFarmRemoteDataSource {
}
@override
Future<DioResponse<Map<String, dynamic>>> getSDUIForm({
required String token,
}) async {
Future<DioResponse<Map<String, dynamic>>> getSDUIForm({required String token}) async {
var res = await _httpClient.get(
'/inspection_form_sd_ui/?name=b1',
'/form-information/?hatching=232&form=b1',
headers: {'Authorization': 'Bearer $token'},
fromJson: (json) {
return json;

View File

@@ -41,9 +41,7 @@ class NewPageLogic extends GetxController {
// Check if info has type field (meaning it's the SDUI structure itself)
if (infoMap.containsKey('type')) {
sduiData = infoMap;
iLog(
'SDUI data extracted from info (info contains type field)',
);
iLog('SDUI data extracted from info (info contains type field)');
} else if (infoMap['data'] != null) {
// Fallback: if info.data exists, use it
sduiData = infoMap['data'] as Map<String, dynamic>;
@@ -64,16 +62,12 @@ class NewPageLogic extends GetxController {
// Log model info using pattern matching
final modelType =
sduiModel.value?.maybeWhen(
textFormField: (data, visible, visibleCondition) =>
'text_form_field',
cardLabelItem:
(data, child, children, visible, visibleCondition) =>
'card_label_item',
chipSelection: (data, visible, visibleCondition) =>
'chip_selection',
textFormField: (data, visible, visibleCondition) => 'text_form_field',
cardLabelItem: (data, child, children, visible, visibleCondition) =>
'card_label_item',
chipSelection: (data, visible, visibleCondition) => 'chip_selection',
dropdown: (data, visible, visibleCondition) => 'dropdown',
imagePicker: (data, visible, visibleCondition) =>
'image_picker',
imagePicker: (data, visible, visibleCondition) => 'image_picker',
column:
(
children,
@@ -85,20 +79,10 @@ class NewPageLogic extends GetxController {
paddingVertical,
visibleCondition,
) => 'column',
row:
(
children,
spacing,
mainAxisAlignment,
visible,
visibleCondition,
) => 'row',
sizedBox: (width, height, visible, visibleCondition) =>
'sized_box',
stepper: (data, children, visible, visibleCondition) =>
'stepper',
pageView: (data, children, visible, visibleCondition) =>
'page_view',
row: (children, spacing, mainAxisAlignment, visible, visibleCondition) => 'row',
sizedBox: (width, height, visible, visibleCondition) => 'sized_box',
stepper: (data, children, visible, visibleCondition) => 'stepper',
pageView: (data, children, visible, visibleCondition) => 'page_view',
orElse: () => 'unknown',
) ??
'null';
@@ -116,21 +100,12 @@ class NewPageLogic extends GetxController {
paddingVertical,
visibleCondition,
) => children.length,
row:
(
children,
spacing,
mainAxisAlignment,
visible,
visibleCondition,
) => children.length,
cardLabelItem:
(data, child, children, visible, visibleCondition) =>
(child != null ? 1 : 0) + (children?.length ?? 0),
stepper: (data, children, visible, visibleCondition) =>
children?.length ?? 0,
pageView: (data, children, visible, visibleCondition) =>
row: (children, spacing, mainAxisAlignment, visible, visibleCondition) =>
children.length,
cardLabelItem: (data, child, children, visible, visibleCondition) =>
(child != null ? 1 : 0) + (children?.length ?? 0),
stepper: (data, children, visible, visibleCondition) => children?.length ?? 0,
pageView: (data, children, visible, visibleCondition) => children.length,
orElse: () => 0,
) ??
0;
@@ -170,7 +145,7 @@ class NewPageLogic extends GetxController {
final key = data.key;
final value = data.value;
if (key != null && !controllers.containsKey(key)) {
controllers[key] = TextEditingController(text: value ?? '');
controllers[key] = TextEditingController(text: value.toString() ?? '');
}
},
orElse: () {},

View File

@@ -0,0 +1,61 @@
import 'package:flutter/foundation.dart';
import 'package:rasadyar_core/core.dart';
class ConditionEvaluator {
static bool check(String? condition, RxMap<String, dynamic>? state) {
if (condition == null || condition.isEmpty) return true;
if (state == null) {
return condition.contains('activeStepperIndex == 0');
}
try {
if (condition.contains(' == ')) {
final parts = condition.split(' == ');
if (parts.length != 2) return true;
final key = parts[0].trim();
var expectedValue = parts[1].trim();
// Remove quotes
if ((expectedValue.startsWith("'") && expectedValue.endsWith("'")) ||
(expectedValue.startsWith('"') && expectedValue.endsWith('"'))) {
expectedValue = expectedValue.substring(1, expectedValue.length - 1);
}
final actualValue = state[key];
if (actualValue == null) {
if (key == 'activeStepperIndex' && expectedValue == '0') return true;
return false;
}
// Handle numeric comparison if possible
final expectedInt = int.tryParse(expectedValue);
if (expectedInt != null) {
if (actualValue is int) return actualValue == expectedInt;
if (actualValue is String) return int.tryParse(actualValue) == expectedInt;
}
return actualValue.toString() == expectedValue;
}
return true;
} catch (e) {
debugPrint('Error parsing condition: $e');
return false;
}
}
/// Extracts step index without using expensive RegExp in a loop if possible,
/// or at least centralizes the logic.
static int? extractStepIndex(String? condition) {
if (condition == null || !condition.contains('activeStepperIndex')) return null;
try {
final parts = condition.split(' == ');
if (parts.length == 2 && parts[0].trim() == 'activeStepperIndex') {
return int.tryParse(parts[1].trim());
}
} catch (_) {}
return null;
}
}

View File

@@ -0,0 +1,11 @@
import 'package:rasadyar_chicken/presentation/widget/sdui/model/sdui_widget.dart';
import 'package:rasadyar_chicken/presentation/widget/sdui/widgets/stepper/model/stepper_sdui_model.dart';
extension SDUIModelExtensions on SDUIWidgetModel {
// چک میکند آیا این ویجت استپر است؟
bool get isStepper => this.maybeWhen(stepper: (_, _, _, _) => true, orElse: () => false);
// دیتای استپر را برمی‌گرداند (اگر استپر باشد)
StepperSDUIModel? get stepperData =>
maybeWhen(stepper: (data, _, _, _) => data, orElse: () => null);
}

View File

@@ -11,14 +11,14 @@ abstract class TextFormFieldSDUIModel with _$TextFormFieldSDUIModel {
String? hintText,
String? variant,
String? keyboardType,
String? value,
dynamic value,
int? maxLength,
int? minLine,
int? maxLine,
bool? required,
bool? enabled,
bool? readonly,
bool? commaSperator,
bool? commaSeparator,
bool? decimal,
int? decimalPlaces,
String? type,

View File

@@ -15,7 +15,7 @@ T _$identity<T>(T value) => value;
/// @nodoc
mixin _$TextFormFieldSDUIModel {
String? get key; String? get label; String? get hintText; String? get variant; String? get keyboardType; String? get value; int? get maxLength; int? get minLine; int? get maxLine; bool? get required; bool? get enabled; bool? get readonly; bool? get commaSperator; bool? get decimal; int? get decimalPlaces; String? get type;
String? get key; String? get label; String? get hintText; String? get variant; String? get keyboardType; dynamic get value; int? get maxLength; int? get minLine; int? get maxLine; bool? get required; bool? get enabled; bool? get readonly; bool? get commaSeparator; bool? get decimal; int? get decimalPlaces; String? get type;
/// Create a copy of TextFormFieldSDUIModel
/// with the given fields replaced by the non-null parameter values.
@JsonKey(includeFromJson: false, includeToJson: false)
@@ -28,16 +28,16 @@ $TextFormFieldSDUIModelCopyWith<TextFormFieldSDUIModel> get copyWith => _$TextFo
@override
bool operator ==(Object other) {
return identical(this, other) || (other.runtimeType == runtimeType&&other is TextFormFieldSDUIModel&&(identical(other.key, key) || other.key == key)&&(identical(other.label, label) || other.label == label)&&(identical(other.hintText, hintText) || other.hintText == hintText)&&(identical(other.variant, variant) || other.variant == variant)&&(identical(other.keyboardType, keyboardType) || other.keyboardType == keyboardType)&&(identical(other.value, value) || other.value == value)&&(identical(other.maxLength, maxLength) || other.maxLength == maxLength)&&(identical(other.minLine, minLine) || other.minLine == minLine)&&(identical(other.maxLine, maxLine) || other.maxLine == maxLine)&&(identical(other.required, required) || other.required == required)&&(identical(other.enabled, enabled) || other.enabled == enabled)&&(identical(other.readonly, readonly) || other.readonly == readonly)&&(identical(other.commaSperator, commaSperator) || other.commaSperator == commaSperator)&&(identical(other.decimal, decimal) || other.decimal == decimal)&&(identical(other.decimalPlaces, decimalPlaces) || other.decimalPlaces == decimalPlaces)&&(identical(other.type, type) || other.type == type));
return identical(this, other) || (other.runtimeType == runtimeType&&other is TextFormFieldSDUIModel&&(identical(other.key, key) || other.key == key)&&(identical(other.label, label) || other.label == label)&&(identical(other.hintText, hintText) || other.hintText == hintText)&&(identical(other.variant, variant) || other.variant == variant)&&(identical(other.keyboardType, keyboardType) || other.keyboardType == keyboardType)&&const DeepCollectionEquality().equals(other.value, value)&&(identical(other.maxLength, maxLength) || other.maxLength == maxLength)&&(identical(other.minLine, minLine) || other.minLine == minLine)&&(identical(other.maxLine, maxLine) || other.maxLine == maxLine)&&(identical(other.required, required) || other.required == required)&&(identical(other.enabled, enabled) || other.enabled == enabled)&&(identical(other.readonly, readonly) || other.readonly == readonly)&&(identical(other.commaSeparator, commaSeparator) || other.commaSeparator == commaSeparator)&&(identical(other.decimal, decimal) || other.decimal == decimal)&&(identical(other.decimalPlaces, decimalPlaces) || other.decimalPlaces == decimalPlaces)&&(identical(other.type, type) || other.type == type));
}
@JsonKey(includeFromJson: false, includeToJson: false)
@override
int get hashCode => Object.hash(runtimeType,key,label,hintText,variant,keyboardType,value,maxLength,minLine,maxLine,required,enabled,readonly,commaSperator,decimal,decimalPlaces,type);
int get hashCode => Object.hash(runtimeType,key,label,hintText,variant,keyboardType,const DeepCollectionEquality().hash(value),maxLength,minLine,maxLine,required,enabled,readonly,commaSeparator,decimal,decimalPlaces,type);
@override
String toString() {
return 'TextFormFieldSDUIModel(key: $key, label: $label, hintText: $hintText, variant: $variant, keyboardType: $keyboardType, value: $value, maxLength: $maxLength, minLine: $minLine, maxLine: $maxLine, required: $required, enabled: $enabled, readonly: $readonly, commaSperator: $commaSperator, decimal: $decimal, decimalPlaces: $decimalPlaces, type: $type)';
return 'TextFormFieldSDUIModel(key: $key, label: $label, hintText: $hintText, variant: $variant, keyboardType: $keyboardType, value: $value, maxLength: $maxLength, minLine: $minLine, maxLine: $maxLine, required: $required, enabled: $enabled, readonly: $readonly, commaSeparator: $commaSeparator, decimal: $decimal, decimalPlaces: $decimalPlaces, type: $type)';
}
@@ -48,7 +48,7 @@ abstract mixin class $TextFormFieldSDUIModelCopyWith<$Res> {
factory $TextFormFieldSDUIModelCopyWith(TextFormFieldSDUIModel value, $Res Function(TextFormFieldSDUIModel) _then) = _$TextFormFieldSDUIModelCopyWithImpl;
@useResult
$Res call({
String? key, String? label, String? hintText, String? variant, String? keyboardType, String? value, int? maxLength, int? minLine, int? maxLine, bool? required, bool? enabled, bool? readonly, bool? commaSperator, bool? decimal, int? decimalPlaces, String? type
String? key, String? label, String? hintText, String? variant, String? keyboardType, dynamic value, int? maxLength, int? minLine, int? maxLine, bool? required, bool? enabled, bool? readonly, bool? commaSeparator, bool? decimal, int? decimalPlaces, String? type
});
@@ -65,7 +65,7 @@ class _$TextFormFieldSDUIModelCopyWithImpl<$Res>
/// Create a copy of TextFormFieldSDUIModel
/// with the given fields replaced by the non-null parameter values.
@pragma('vm:prefer-inline') @override $Res call({Object? key = freezed,Object? label = freezed,Object? hintText = freezed,Object? variant = freezed,Object? keyboardType = freezed,Object? value = freezed,Object? maxLength = freezed,Object? minLine = freezed,Object? maxLine = freezed,Object? required = freezed,Object? enabled = freezed,Object? readonly = freezed,Object? commaSperator = freezed,Object? decimal = freezed,Object? decimalPlaces = freezed,Object? type = freezed,}) {
@pragma('vm:prefer-inline') @override $Res call({Object? key = freezed,Object? label = freezed,Object? hintText = freezed,Object? variant = freezed,Object? keyboardType = freezed,Object? value = freezed,Object? maxLength = freezed,Object? minLine = freezed,Object? maxLine = freezed,Object? required = freezed,Object? enabled = freezed,Object? readonly = freezed,Object? commaSeparator = freezed,Object? decimal = freezed,Object? decimalPlaces = freezed,Object? type = freezed,}) {
return _then(_self.copyWith(
key: freezed == key ? _self.key : key // ignore: cast_nullable_to_non_nullable
as String?,label: freezed == label ? _self.label : label // ignore: cast_nullable_to_non_nullable
@@ -73,13 +73,13 @@ as String?,hintText: freezed == hintText ? _self.hintText : hintText // ignore:
as String?,variant: freezed == variant ? _self.variant : variant // ignore: cast_nullable_to_non_nullable
as String?,keyboardType: freezed == keyboardType ? _self.keyboardType : keyboardType // ignore: cast_nullable_to_non_nullable
as String?,value: freezed == value ? _self.value : value // ignore: cast_nullable_to_non_nullable
as String?,maxLength: freezed == maxLength ? _self.maxLength : maxLength // ignore: cast_nullable_to_non_nullable
as dynamic,maxLength: freezed == maxLength ? _self.maxLength : maxLength // ignore: cast_nullable_to_non_nullable
as int?,minLine: freezed == minLine ? _self.minLine : minLine // ignore: cast_nullable_to_non_nullable
as int?,maxLine: freezed == maxLine ? _self.maxLine : maxLine // ignore: cast_nullable_to_non_nullable
as int?,required: freezed == required ? _self.required : required // ignore: cast_nullable_to_non_nullable
as bool?,enabled: freezed == enabled ? _self.enabled : enabled // ignore: cast_nullable_to_non_nullable
as bool?,readonly: freezed == readonly ? _self.readonly : readonly // ignore: cast_nullable_to_non_nullable
as bool?,commaSperator: freezed == commaSperator ? _self.commaSperator : commaSperator // ignore: cast_nullable_to_non_nullable
as bool?,commaSeparator: freezed == commaSeparator ? _self.commaSeparator : commaSeparator // ignore: cast_nullable_to_non_nullable
as bool?,decimal: freezed == decimal ? _self.decimal : decimal // ignore: cast_nullable_to_non_nullable
as bool?,decimalPlaces: freezed == decimalPlaces ? _self.decimalPlaces : decimalPlaces // ignore: cast_nullable_to_non_nullable
as int?,type: freezed == type ? _self.type : type // ignore: cast_nullable_to_non_nullable
@@ -168,10 +168,10 @@ return $default(_that);case _:
/// }
/// ```
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( String? key, String? label, String? hintText, String? variant, String? keyboardType, String? value, int? maxLength, int? minLine, int? maxLine, bool? required, bool? enabled, bool? readonly, bool? commaSperator, bool? decimal, int? decimalPlaces, String? type)? $default,{required TResult orElse(),}) {final _that = this;
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( String? key, String? label, String? hintText, String? variant, String? keyboardType, dynamic value, int? maxLength, int? minLine, int? maxLine, bool? required, bool? enabled, bool? readonly, bool? commaSeparator, bool? decimal, int? decimalPlaces, String? type)? $default,{required TResult orElse(),}) {final _that = this;
switch (_that) {
case _TextFormFieldSDUIModel() when $default != null:
return $default(_that.key,_that.label,_that.hintText,_that.variant,_that.keyboardType,_that.value,_that.maxLength,_that.minLine,_that.maxLine,_that.required,_that.enabled,_that.readonly,_that.commaSperator,_that.decimal,_that.decimalPlaces,_that.type);case _:
return $default(_that.key,_that.label,_that.hintText,_that.variant,_that.keyboardType,_that.value,_that.maxLength,_that.minLine,_that.maxLine,_that.required,_that.enabled,_that.readonly,_that.commaSeparator,_that.decimal,_that.decimalPlaces,_that.type);case _:
return orElse();
}
@@ -189,10 +189,10 @@ return $default(_that.key,_that.label,_that.hintText,_that.variant,_that.keyboar
/// }
/// ```
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( String? key, String? label, String? hintText, String? variant, String? keyboardType, String? value, int? maxLength, int? minLine, int? maxLine, bool? required, bool? enabled, bool? readonly, bool? commaSperator, bool? decimal, int? decimalPlaces, String? type) $default,) {final _that = this;
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( String? key, String? label, String? hintText, String? variant, String? keyboardType, dynamic value, int? maxLength, int? minLine, int? maxLine, bool? required, bool? enabled, bool? readonly, bool? commaSeparator, bool? decimal, int? decimalPlaces, String? type) $default,) {final _that = this;
switch (_that) {
case _TextFormFieldSDUIModel():
return $default(_that.key,_that.label,_that.hintText,_that.variant,_that.keyboardType,_that.value,_that.maxLength,_that.minLine,_that.maxLine,_that.required,_that.enabled,_that.readonly,_that.commaSperator,_that.decimal,_that.decimalPlaces,_that.type);case _:
return $default(_that.key,_that.label,_that.hintText,_that.variant,_that.keyboardType,_that.value,_that.maxLength,_that.minLine,_that.maxLine,_that.required,_that.enabled,_that.readonly,_that.commaSeparator,_that.decimal,_that.decimalPlaces,_that.type);case _:
throw StateError('Unexpected subclass');
}
@@ -209,10 +209,10 @@ return $default(_that.key,_that.label,_that.hintText,_that.variant,_that.keyboar
/// }
/// ```
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( String? key, String? label, String? hintText, String? variant, String? keyboardType, String? value, int? maxLength, int? minLine, int? maxLine, bool? required, bool? enabled, bool? readonly, bool? commaSperator, bool? decimal, int? decimalPlaces, String? type)? $default,) {final _that = this;
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( String? key, String? label, String? hintText, String? variant, String? keyboardType, dynamic value, int? maxLength, int? minLine, int? maxLine, bool? required, bool? enabled, bool? readonly, bool? commaSeparator, bool? decimal, int? decimalPlaces, String? type)? $default,) {final _that = this;
switch (_that) {
case _TextFormFieldSDUIModel() when $default != null:
return $default(_that.key,_that.label,_that.hintText,_that.variant,_that.keyboardType,_that.value,_that.maxLength,_that.minLine,_that.maxLine,_that.required,_that.enabled,_that.readonly,_that.commaSperator,_that.decimal,_that.decimalPlaces,_that.type);case _:
return $default(_that.key,_that.label,_that.hintText,_that.variant,_that.keyboardType,_that.value,_that.maxLength,_that.minLine,_that.maxLine,_that.required,_that.enabled,_that.readonly,_that.commaSeparator,_that.decimal,_that.decimalPlaces,_that.type);case _:
return null;
}
@@ -224,7 +224,7 @@ return $default(_that.key,_that.label,_that.hintText,_that.variant,_that.keyboar
@JsonSerializable()
class _TextFormFieldSDUIModel implements TextFormFieldSDUIModel {
const _TextFormFieldSDUIModel({this.key, this.label, this.hintText, this.variant, this.keyboardType, this.value, this.maxLength, this.minLine, this.maxLine, this.required, this.enabled, this.readonly, this.commaSperator, this.decimal, this.decimalPlaces, this.type});
const _TextFormFieldSDUIModel({this.key, this.label, this.hintText, this.variant, this.keyboardType, this.value, this.maxLength, this.minLine, this.maxLine, this.required, this.enabled, this.readonly, this.commaSeparator, this.decimal, this.decimalPlaces, this.type});
factory _TextFormFieldSDUIModel.fromJson(Map<String, dynamic> json) => _$TextFormFieldSDUIModelFromJson(json);
@override final String? key;
@@ -232,14 +232,14 @@ class _TextFormFieldSDUIModel implements TextFormFieldSDUIModel {
@override final String? hintText;
@override final String? variant;
@override final String? keyboardType;
@override final String? value;
@override final dynamic value;
@override final int? maxLength;
@override final int? minLine;
@override final int? maxLine;
@override final bool? required;
@override final bool? enabled;
@override final bool? readonly;
@override final bool? commaSperator;
@override final bool? commaSeparator;
@override final bool? decimal;
@override final int? decimalPlaces;
@override final String? type;
@@ -257,16 +257,16 @@ Map<String, dynamic> toJson() {
@override
bool operator ==(Object other) {
return identical(this, other) || (other.runtimeType == runtimeType&&other is _TextFormFieldSDUIModel&&(identical(other.key, key) || other.key == key)&&(identical(other.label, label) || other.label == label)&&(identical(other.hintText, hintText) || other.hintText == hintText)&&(identical(other.variant, variant) || other.variant == variant)&&(identical(other.keyboardType, keyboardType) || other.keyboardType == keyboardType)&&(identical(other.value, value) || other.value == value)&&(identical(other.maxLength, maxLength) || other.maxLength == maxLength)&&(identical(other.minLine, minLine) || other.minLine == minLine)&&(identical(other.maxLine, maxLine) || other.maxLine == maxLine)&&(identical(other.required, required) || other.required == required)&&(identical(other.enabled, enabled) || other.enabled == enabled)&&(identical(other.readonly, readonly) || other.readonly == readonly)&&(identical(other.commaSperator, commaSperator) || other.commaSperator == commaSperator)&&(identical(other.decimal, decimal) || other.decimal == decimal)&&(identical(other.decimalPlaces, decimalPlaces) || other.decimalPlaces == decimalPlaces)&&(identical(other.type, type) || other.type == type));
return identical(this, other) || (other.runtimeType == runtimeType&&other is _TextFormFieldSDUIModel&&(identical(other.key, key) || other.key == key)&&(identical(other.label, label) || other.label == label)&&(identical(other.hintText, hintText) || other.hintText == hintText)&&(identical(other.variant, variant) || other.variant == variant)&&(identical(other.keyboardType, keyboardType) || other.keyboardType == keyboardType)&&const DeepCollectionEquality().equals(other.value, value)&&(identical(other.maxLength, maxLength) || other.maxLength == maxLength)&&(identical(other.minLine, minLine) || other.minLine == minLine)&&(identical(other.maxLine, maxLine) || other.maxLine == maxLine)&&(identical(other.required, required) || other.required == required)&&(identical(other.enabled, enabled) || other.enabled == enabled)&&(identical(other.readonly, readonly) || other.readonly == readonly)&&(identical(other.commaSeparator, commaSeparator) || other.commaSeparator == commaSeparator)&&(identical(other.decimal, decimal) || other.decimal == decimal)&&(identical(other.decimalPlaces, decimalPlaces) || other.decimalPlaces == decimalPlaces)&&(identical(other.type, type) || other.type == type));
}
@JsonKey(includeFromJson: false, includeToJson: false)
@override
int get hashCode => Object.hash(runtimeType,key,label,hintText,variant,keyboardType,value,maxLength,minLine,maxLine,required,enabled,readonly,commaSperator,decimal,decimalPlaces,type);
int get hashCode => Object.hash(runtimeType,key,label,hintText,variant,keyboardType,const DeepCollectionEquality().hash(value),maxLength,minLine,maxLine,required,enabled,readonly,commaSeparator,decimal,decimalPlaces,type);
@override
String toString() {
return 'TextFormFieldSDUIModel(key: $key, label: $label, hintText: $hintText, variant: $variant, keyboardType: $keyboardType, value: $value, maxLength: $maxLength, minLine: $minLine, maxLine: $maxLine, required: $required, enabled: $enabled, readonly: $readonly, commaSperator: $commaSperator, decimal: $decimal, decimalPlaces: $decimalPlaces, type: $type)';
return 'TextFormFieldSDUIModel(key: $key, label: $label, hintText: $hintText, variant: $variant, keyboardType: $keyboardType, value: $value, maxLength: $maxLength, minLine: $minLine, maxLine: $maxLine, required: $required, enabled: $enabled, readonly: $readonly, commaSeparator: $commaSeparator, decimal: $decimal, decimalPlaces: $decimalPlaces, type: $type)';
}
@@ -277,7 +277,7 @@ abstract mixin class _$TextFormFieldSDUIModelCopyWith<$Res> implements $TextForm
factory _$TextFormFieldSDUIModelCopyWith(_TextFormFieldSDUIModel value, $Res Function(_TextFormFieldSDUIModel) _then) = __$TextFormFieldSDUIModelCopyWithImpl;
@override @useResult
$Res call({
String? key, String? label, String? hintText, String? variant, String? keyboardType, String? value, int? maxLength, int? minLine, int? maxLine, bool? required, bool? enabled, bool? readonly, bool? commaSperator, bool? decimal, int? decimalPlaces, String? type
String? key, String? label, String? hintText, String? variant, String? keyboardType, dynamic value, int? maxLength, int? minLine, int? maxLine, bool? required, bool? enabled, bool? readonly, bool? commaSeparator, bool? decimal, int? decimalPlaces, String? type
});
@@ -294,7 +294,7 @@ class __$TextFormFieldSDUIModelCopyWithImpl<$Res>
/// Create a copy of TextFormFieldSDUIModel
/// with the given fields replaced by the non-null parameter values.
@override @pragma('vm:prefer-inline') $Res call({Object? key = freezed,Object? label = freezed,Object? hintText = freezed,Object? variant = freezed,Object? keyboardType = freezed,Object? value = freezed,Object? maxLength = freezed,Object? minLine = freezed,Object? maxLine = freezed,Object? required = freezed,Object? enabled = freezed,Object? readonly = freezed,Object? commaSperator = freezed,Object? decimal = freezed,Object? decimalPlaces = freezed,Object? type = freezed,}) {
@override @pragma('vm:prefer-inline') $Res call({Object? key = freezed,Object? label = freezed,Object? hintText = freezed,Object? variant = freezed,Object? keyboardType = freezed,Object? value = freezed,Object? maxLength = freezed,Object? minLine = freezed,Object? maxLine = freezed,Object? required = freezed,Object? enabled = freezed,Object? readonly = freezed,Object? commaSeparator = freezed,Object? decimal = freezed,Object? decimalPlaces = freezed,Object? type = freezed,}) {
return _then(_TextFormFieldSDUIModel(
key: freezed == key ? _self.key : key // ignore: cast_nullable_to_non_nullable
as String?,label: freezed == label ? _self.label : label // ignore: cast_nullable_to_non_nullable
@@ -302,13 +302,13 @@ as String?,hintText: freezed == hintText ? _self.hintText : hintText // ignore:
as String?,variant: freezed == variant ? _self.variant : variant // ignore: cast_nullable_to_non_nullable
as String?,keyboardType: freezed == keyboardType ? _self.keyboardType : keyboardType // ignore: cast_nullable_to_non_nullable
as String?,value: freezed == value ? _self.value : value // ignore: cast_nullable_to_non_nullable
as String?,maxLength: freezed == maxLength ? _self.maxLength : maxLength // ignore: cast_nullable_to_non_nullable
as dynamic,maxLength: freezed == maxLength ? _self.maxLength : maxLength // ignore: cast_nullable_to_non_nullable
as int?,minLine: freezed == minLine ? _self.minLine : minLine // ignore: cast_nullable_to_non_nullable
as int?,maxLine: freezed == maxLine ? _self.maxLine : maxLine // ignore: cast_nullable_to_non_nullable
as int?,required: freezed == required ? _self.required : required // ignore: cast_nullable_to_non_nullable
as bool?,enabled: freezed == enabled ? _self.enabled : enabled // ignore: cast_nullable_to_non_nullable
as bool?,readonly: freezed == readonly ? _self.readonly : readonly // ignore: cast_nullable_to_non_nullable
as bool?,commaSperator: freezed == commaSperator ? _self.commaSperator : commaSperator // ignore: cast_nullable_to_non_nullable
as bool?,commaSeparator: freezed == commaSeparator ? _self.commaSeparator : commaSeparator // ignore: cast_nullable_to_non_nullable
as bool?,decimal: freezed == decimal ? _self.decimal : decimal // ignore: cast_nullable_to_non_nullable
as bool?,decimalPlaces: freezed == decimalPlaces ? _self.decimalPlaces : decimalPlaces // ignore: cast_nullable_to_non_nullable
as int?,type: freezed == type ? _self.type : type // ignore: cast_nullable_to_non_nullable

View File

@@ -14,14 +14,14 @@ _TextFormFieldSDUIModel _$TextFormFieldSDUIModelFromJson(
hintText: json['hint_text'] as String?,
variant: json['variant'] as String?,
keyboardType: json['keyboard_type'] as String?,
value: json['value'] as String?,
value: json['value'],
maxLength: (json['max_length'] as num?)?.toInt(),
minLine: (json['min_line'] as num?)?.toInt(),
maxLine: (json['max_line'] as num?)?.toInt(),
required: json['required'] as bool?,
enabled: json['enabled'] as bool?,
readonly: json['readonly'] as bool?,
commaSperator: json['comma_sperator'] as bool?,
commaSeparator: json['comma_separator'] as bool?,
decimal: json['decimal'] as bool?,
decimalPlaces: (json['decimal_places'] as num?)?.toInt(),
type: json['type'] as String?,
@@ -42,7 +42,7 @@ Map<String, dynamic> _$TextFormFieldSDUIModelToJson(
'required': instance.required,
'enabled': instance.enabled,
'readonly': instance.readonly,
'comma_sperator': instance.commaSperator,
'comma_separator': instance.commaSeparator,
'decimal': instance.decimal,
'decimal_places': instance.decimalPlaces,
'type': instance.type,

View File

@@ -7,24 +7,23 @@ import 'model/text_form_field_sdui_model.dart';
Widget textFormFiledSDUI({
required TextFormFieldSDUIModel model,
TextEditingController? controller,
ValueChanged<String>? onChanged,
}) {
List<TextInputFormatter>? inputFormatters = [];
TextInputType? keyboardType;
VoidCallback? onTap;
bool isReadonly = model.readonly ?? false;
String? initValue;
final textController = controller ?? TextEditingController(text: model.value);
if (model.type == 'date_picker') {
// برای date picker، readonly می‌کنیم و onTap اضافه می‌کنیم
isReadonly = true;
onTap = () {
// پارس کردن تاریخ فعلی اگر وجود دارد
Jalali? initialDate;
if (textController.text.isNotEmpty) {
try {
// فرض می‌کنیم تاریخ به فرمت '1404/01/01' یا '1404-01-01' است
final dateStr = textController.text.replaceAll('-', '/');
final parts = dateStr.split('/');
if (parts.length == 3) {
@@ -40,16 +39,15 @@ Widget textFormFiledSDUI({
}
}
// اگر نتوانستیم parse کنیم، از تاریخ امروز استفاده می‌کنیم
initialDate ??= Jalali.now();
// نمایش date picker
Get.bottomSheet(
modalDatePicker(
initialDate: initialDate,
onDateSelected: (selectedDate) {
// فرمت کردن تاریخ و قرار دادن در controller
textController.text = selectedDate.formatCompactDate();
final formattedDate = selectedDate.formatCompactDate();
textController.text = formattedDate;
onChanged?.call(formattedDate);
},
),
isScrollControlled: true,
@@ -67,16 +65,29 @@ Widget textFormFiledSDUI({
}
}
if ((model.commaSperator ?? false) &&
(model.decimal == null || model.decimal == false)) {
if ((model.commaSeparator ?? false) && (model.decimal == null || model.decimal == false)) {
inputFormatters.add(SeparatorInputFormatter());
// FIX: اگر مقدار اولیه وجود دارد، باید آن را هم فرمت کنیم تا با فرمتر هماهنگ باشد
if (model.value != null) {
try {
String tmp = model.value.replaceAll(',', '');
if (model.commaSeparator ?? false) {
textController.text = tmp.replaceAll(',', '').separatedByComma;
} else {
textController.text = int.tryParse(tmp).toString();
}
} catch (e) {
// اگر پارس نشد، همان مقدار اصلی می‌ماند
}
}
}
}
return RTextField(
controller: textController,
onChanged: (data) {
iLog(data);
onChanged?.call(data);
},
onTap: onTap,
label: model.label,