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,4 +1,4 @@
sdk.dir=C:\\Users\\Housh11\\AppData\\Local\\Android\\sdk sdk.dir=C:/Users/Housh11/AppData/Local/Android/Sdk
flutter.sdk=C:\\src\\flutter flutter.sdk=C:\\src\\flutter
flutter.buildMode=debug flutter.buildMode=debug
flutter.versionName=1.3.42 flutter.versionName=1.3.42

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/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_chicken/features/vet_farm/data/datasources/remote/vet_farm_remote_data_source.dart';
import 'package:rasadyar_core/core.dart'; import 'package:rasadyar_core/core.dart';
@@ -38,11 +38,9 @@ class VetFarmRemoteDataSourceImpl implements VetFarmRemoteDataSource {
} }
@override @override
Future<DioResponse<Map<String, dynamic>>> getSDUIForm({ Future<DioResponse<Map<String, dynamic>>> getSDUIForm({required String token}) async {
required String token,
}) async {
var res = await _httpClient.get( var res = await _httpClient.get(
'/inspection_form_sd_ui/?name=b1', '/form-information/?hatching=232&form=b1',
headers: {'Authorization': 'Bearer $token'}, headers: {'Authorization': 'Bearer $token'},
fromJson: (json) { fromJson: (json) {
return 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) // Check if info has type field (meaning it's the SDUI structure itself)
if (infoMap.containsKey('type')) { if (infoMap.containsKey('type')) {
sduiData = infoMap; sduiData = infoMap;
iLog( iLog('SDUI data extracted from info (info contains type field)');
'SDUI data extracted from info (info contains type field)',
);
} else if (infoMap['data'] != null) { } else if (infoMap['data'] != null) {
// Fallback: if info.data exists, use it // Fallback: if info.data exists, use it
sduiData = infoMap['data'] as Map<String, dynamic>; sduiData = infoMap['data'] as Map<String, dynamic>;
@@ -64,16 +62,12 @@ class NewPageLogic extends GetxController {
// Log model info using pattern matching // Log model info using pattern matching
final modelType = final modelType =
sduiModel.value?.maybeWhen( sduiModel.value?.maybeWhen(
textFormField: (data, visible, visibleCondition) => textFormField: (data, visible, visibleCondition) => 'text_form_field',
'text_form_field', cardLabelItem: (data, child, children, visible, visibleCondition) =>
cardLabelItem: 'card_label_item',
(data, child, children, visible, visibleCondition) => chipSelection: (data, visible, visibleCondition) => 'chip_selection',
'card_label_item',
chipSelection: (data, visible, visibleCondition) =>
'chip_selection',
dropdown: (data, visible, visibleCondition) => 'dropdown', dropdown: (data, visible, visibleCondition) => 'dropdown',
imagePicker: (data, visible, visibleCondition) => imagePicker: (data, visible, visibleCondition) => 'image_picker',
'image_picker',
column: column:
( (
children, children,
@@ -85,20 +79,10 @@ class NewPageLogic extends GetxController {
paddingVertical, paddingVertical,
visibleCondition, visibleCondition,
) => 'column', ) => 'column',
row: row: (children, spacing, mainAxisAlignment, visible, visibleCondition) => 'row',
( sizedBox: (width, height, visible, visibleCondition) => 'sized_box',
children, stepper: (data, children, visible, visibleCondition) => 'stepper',
spacing, pageView: (data, children, visible, visibleCondition) => 'page_view',
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', orElse: () => 'unknown',
) ?? ) ??
'null'; 'null';
@@ -116,21 +100,12 @@ class NewPageLogic extends GetxController {
paddingVertical, paddingVertical,
visibleCondition, visibleCondition,
) => children.length, ) => children.length,
row: row: (children, spacing, mainAxisAlignment, visible, visibleCondition) =>
(
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, 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, orElse: () => 0,
) ?? ) ??
0; 0;
@@ -170,7 +145,7 @@ class NewPageLogic extends GetxController {
final key = data.key; final key = data.key;
final value = data.value; final value = data.value;
if (key != null && !controllers.containsKey(key)) { if (key != null && !controllers.containsKey(key)) {
controllers[key] = TextEditingController(text: value ?? ''); controllers[key] = TextEditingController(text: value.toString() ?? '');
} }
}, },
orElse: () {}, 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? hintText,
String? variant, String? variant,
String? keyboardType, String? keyboardType,
String? value, dynamic value,
int? maxLength, int? maxLength,
int? minLine, int? minLine,
int? maxLine, int? maxLine,
bool? required, bool? required,
bool? enabled, bool? enabled,
bool? readonly, bool? readonly,
bool? commaSperator, bool? commaSeparator,
bool? decimal, bool? decimal,
int? decimalPlaces, int? decimalPlaces,
String? type, String? type,

View File

@@ -15,7 +15,7 @@ T _$identity<T>(T value) => value;
/// @nodoc /// @nodoc
mixin _$TextFormFieldSDUIModel { 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 /// Create a copy of TextFormFieldSDUIModel
/// with the given fields replaced by the non-null parameter values. /// with the given fields replaced by the non-null parameter values.
@JsonKey(includeFromJson: false, includeToJson: false) @JsonKey(includeFromJson: false, includeToJson: false)
@@ -28,16 +28,16 @@ $TextFormFieldSDUIModelCopyWith<TextFormFieldSDUIModel> get copyWith => _$TextFo
@override @override
bool operator ==(Object other) { 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) @JsonKey(includeFromJson: false, includeToJson: false)
@override @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 @override
String toString() { 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; factory $TextFormFieldSDUIModelCopyWith(TextFormFieldSDUIModel value, $Res Function(TextFormFieldSDUIModel) _then) = _$TextFormFieldSDUIModelCopyWithImpl;
@useResult @useResult
$Res call({ $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 /// Create a copy of TextFormFieldSDUIModel
/// with the given fields replaced by the non-null parameter values. /// 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( return _then(_self.copyWith(
key: freezed == key ? _self.key : key // ignore: cast_nullable_to_non_nullable 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 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?,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?,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?,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?,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?,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 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?,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?,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?,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 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 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) { switch (_that) {
case _TextFormFieldSDUIModel() when $default != null: 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(); 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) { switch (_that) {
case _TextFormFieldSDUIModel(): 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'); 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) { switch (_that) {
case _TextFormFieldSDUIModel() when $default != null: 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; return null;
} }
@@ -224,7 +224,7 @@ return $default(_that.key,_that.label,_that.hintText,_that.variant,_that.keyboar
@JsonSerializable() @JsonSerializable()
class _TextFormFieldSDUIModel implements TextFormFieldSDUIModel { 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); factory _TextFormFieldSDUIModel.fromJson(Map<String, dynamic> json) => _$TextFormFieldSDUIModelFromJson(json);
@override final String? key; @override final String? key;
@@ -232,14 +232,14 @@ class _TextFormFieldSDUIModel implements TextFormFieldSDUIModel {
@override final String? hintText; @override final String? hintText;
@override final String? variant; @override final String? variant;
@override final String? keyboardType; @override final String? keyboardType;
@override final String? value; @override final dynamic value;
@override final int? maxLength; @override final int? maxLength;
@override final int? minLine; @override final int? minLine;
@override final int? maxLine; @override final int? maxLine;
@override final bool? required; @override final bool? required;
@override final bool? enabled; @override final bool? enabled;
@override final bool? readonly; @override final bool? readonly;
@override final bool? commaSperator; @override final bool? commaSeparator;
@override final bool? decimal; @override final bool? decimal;
@override final int? decimalPlaces; @override final int? decimalPlaces;
@override final String? type; @override final String? type;
@@ -257,16 +257,16 @@ Map<String, dynamic> toJson() {
@override @override
bool operator ==(Object other) { 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) @JsonKey(includeFromJson: false, includeToJson: false)
@override @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 @override
String toString() { 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; factory _$TextFormFieldSDUIModelCopyWith(_TextFormFieldSDUIModel value, $Res Function(_TextFormFieldSDUIModel) _then) = __$TextFormFieldSDUIModelCopyWithImpl;
@override @useResult @override @useResult
$Res call({ $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 /// Create a copy of TextFormFieldSDUIModel
/// with the given fields replaced by the non-null parameter values. /// 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( return _then(_TextFormFieldSDUIModel(
key: freezed == key ? _self.key : key // ignore: cast_nullable_to_non_nullable 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 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?,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?,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?,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?,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?,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 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?,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?,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?,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 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 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?, hintText: json['hint_text'] as String?,
variant: json['variant'] as String?, variant: json['variant'] as String?,
keyboardType: json['keyboard_type'] as String?, keyboardType: json['keyboard_type'] as String?,
value: json['value'] as String?, value: json['value'],
maxLength: (json['max_length'] as num?)?.toInt(), maxLength: (json['max_length'] as num?)?.toInt(),
minLine: (json['min_line'] as num?)?.toInt(), minLine: (json['min_line'] as num?)?.toInt(),
maxLine: (json['max_line'] as num?)?.toInt(), maxLine: (json['max_line'] as num?)?.toInt(),
required: json['required'] as bool?, required: json['required'] as bool?,
enabled: json['enabled'] as bool?, enabled: json['enabled'] as bool?,
readonly: json['readonly'] as bool?, readonly: json['readonly'] as bool?,
commaSperator: json['comma_sperator'] as bool?, commaSeparator: json['comma_separator'] as bool?,
decimal: json['decimal'] as bool?, decimal: json['decimal'] as bool?,
decimalPlaces: (json['decimal_places'] as num?)?.toInt(), decimalPlaces: (json['decimal_places'] as num?)?.toInt(),
type: json['type'] as String?, type: json['type'] as String?,
@@ -42,7 +42,7 @@ Map<String, dynamic> _$TextFormFieldSDUIModelToJson(
'required': instance.required, 'required': instance.required,
'enabled': instance.enabled, 'enabled': instance.enabled,
'readonly': instance.readonly, 'readonly': instance.readonly,
'comma_sperator': instance.commaSperator, 'comma_separator': instance.commaSeparator,
'decimal': instance.decimal, 'decimal': instance.decimal,
'decimal_places': instance.decimalPlaces, 'decimal_places': instance.decimalPlaces,
'type': instance.type, 'type': instance.type,

View File

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