feat: add stepper and page view components to SDUI, enhance form handling with dynamic visibility conditions and improved error handling
This commit is contained in:
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"type": "stepper",
|
||||
"visible": true,
|
||||
"data": {
|
||||
"key": "activeStepperIndex",
|
||||
"totalSteps": 5,
|
||||
"activeStep": 0
|
||||
}
|
||||
}
|
||||
@@ -10,6 +10,10 @@ import 'package:rasadyar_chicken/presentation/widget/sdui/widgets/image_picker/i
|
||||
import 'package:rasadyar_chicken/presentation/widget/sdui/widgets/image_picker/model/image_picker_sdui_model.dart';
|
||||
import 'package:rasadyar_chicken/presentation/widget/sdui/widgets/text_form_filed/model/text_form_field_sdui_model.dart';
|
||||
import 'package:rasadyar_chicken/presentation/widget/sdui/widgets/text_form_filed/text_form_filed_sdui.dart';
|
||||
import 'package:rasadyar_chicken/presentation/widget/sdui/widgets/stepper/stepper_sdui.dart';
|
||||
import 'package:rasadyar_chicken/presentation/widget/sdui/widgets/stepper/model/stepper_sdui_model.dart';
|
||||
import 'package:rasadyar_chicken/presentation/widget/sdui/widgets/page_view/page_view_sdui.dart';
|
||||
import 'package:rasadyar_chicken/presentation/widget/sdui/widgets/page_view/model/page_view_sdui_model.dart';
|
||||
import 'package:rasadyar_core/core.dart';
|
||||
|
||||
class SDUIFormWidget extends StatelessWidget {
|
||||
@@ -19,6 +23,7 @@ class SDUIFormWidget extends StatelessWidget {
|
||||
final Function(String key, dynamic value)? onStateChanged;
|
||||
final Map<String, RxList<XFile>>? images;
|
||||
final Function(String key, RxList<XFile> images)? onImagesChanged;
|
||||
final Map<String, PageController>? pageControllers;
|
||||
|
||||
const SDUIFormWidget({
|
||||
super.key,
|
||||
@@ -28,6 +33,7 @@ class SDUIFormWidget extends StatelessWidget {
|
||||
this.onStateChanged,
|
||||
this.images,
|
||||
this.onImagesChanged,
|
||||
this.pageControllers,
|
||||
});
|
||||
|
||||
@override
|
||||
@@ -74,6 +80,10 @@ class SDUIFormWidget extends StatelessWidget {
|
||||
return _buildRow(widgetModel);
|
||||
case 'sized_box':
|
||||
return _buildSizedBox(widgetModel);
|
||||
case 'stepper':
|
||||
return _buildStepper(widgetModel);
|
||||
case 'page_view':
|
||||
return _buildPageView(widgetModel);
|
||||
default:
|
||||
iLog('Unknown SDUI widget type: $type');
|
||||
return const SizedBox.shrink();
|
||||
@@ -113,10 +123,57 @@ class SDUIFormWidget extends StatelessWidget {
|
||||
|
||||
Widget _buildCardLabelItem(SDUIWidgetModel widgetModel) {
|
||||
try {
|
||||
// Check visible_condition if present in data
|
||||
if (widgetModel.data != null) {
|
||||
final visibleCondition =
|
||||
widgetModel.data!['visible_condition'] as String?;
|
||||
if (visibleCondition != null && visibleCondition.isNotEmpty) {
|
||||
if (state != null) {
|
||||
return Obx(() {
|
||||
if (!_evaluateVisibleCondition(visibleCondition)) {
|
||||
return const SizedBox.shrink();
|
||||
}
|
||||
return _buildCardLabelItemInternal(widgetModel);
|
||||
});
|
||||
} else {
|
||||
// If state is null, only show first step (0) by default
|
||||
// This allows the form to work even without state initialization
|
||||
if (visibleCondition.contains('activeStepperIndex == 0')) {
|
||||
return _buildCardLabelItemInternal(widgetModel);
|
||||
}
|
||||
return const SizedBox.shrink();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return _buildCardLabelItemInternal(widgetModel);
|
||||
} catch (e, stackTrace) {
|
||||
iLog('Error building card_label_item: $e');
|
||||
iLog('Stack trace: $stackTrace');
|
||||
iLog('WidgetModel data: ${widgetModel.data}');
|
||||
return Container(
|
||||
padding: EdgeInsets.all(16),
|
||||
color: Colors.orange.withOpacity(0.1),
|
||||
child: Text('Card Error: $e'),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Widget _buildCardLabelItemInternal(SDUIWidgetModel widgetModel) {
|
||||
try {
|
||||
// Remove visible_condition from data before creating CardLabelItemData
|
||||
// because it's not part of the model
|
||||
final dataWithoutCondition = widgetModel.data != null
|
||||
? Map<String, dynamic>.from(widgetModel.data!)
|
||||
: null;
|
||||
if (dataWithoutCondition != null) {
|
||||
dataWithoutCondition.remove('visible_condition');
|
||||
}
|
||||
|
||||
final cardModel = CardLabelItemSDUI.fromJson({
|
||||
'type': widgetModel.type,
|
||||
'visible': widgetModel.visible,
|
||||
'data': widgetModel.data,
|
||||
'data': dataWithoutCondition,
|
||||
'child': widgetModel.child,
|
||||
});
|
||||
|
||||
@@ -203,6 +260,7 @@ class SDUIFormWidget extends StatelessWidget {
|
||||
onStateChanged: onStateChanged,
|
||||
images: images,
|
||||
onImagesChanged: onImagesChanged,
|
||||
pageControllers: pageControllers,
|
||||
);
|
||||
} catch (e) {
|
||||
iLog('Error building column child: $e');
|
||||
@@ -415,4 +473,148 @@ class SDUIFormWidget extends StatelessWidget {
|
||||
return MainAxisAlignment.start;
|
||||
}
|
||||
}
|
||||
|
||||
Widget _buildStepper(SDUIWidgetModel widgetModel) {
|
||||
if (widgetModel.data == null) {
|
||||
return const SizedBox.shrink();
|
||||
}
|
||||
|
||||
try {
|
||||
final stepperModel = StepperSDUIModel.fromJson(widgetModel.data!);
|
||||
|
||||
return StepperSDUI(model: stepperModel, state: state);
|
||||
} catch (e, stackTrace) {
|
||||
iLog('Error building stepper: $e');
|
||||
iLog('Stack trace: $stackTrace');
|
||||
return Container(
|
||||
padding: EdgeInsets.all(16),
|
||||
color: Colors.orange.withOpacity(0.1),
|
||||
child: Text('Stepper Error: $e'),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Widget _buildPageView(SDUIWidgetModel widgetModel) {
|
||||
if (widgetModel.data == null) {
|
||||
return const SizedBox.shrink();
|
||||
}
|
||||
|
||||
try {
|
||||
final pageViewModel = PageViewSDUIModel.fromJson(widgetModel.data!);
|
||||
|
||||
// Get PageController from map if key is provided
|
||||
PageController? pageController;
|
||||
if (pageViewModel.key != null &&
|
||||
pageViewModel.key!.isNotEmpty &&
|
||||
pageControllers != null &&
|
||||
pageControllers!.containsKey(pageViewModel.key!)) {
|
||||
pageController = pageControllers![pageViewModel.key!];
|
||||
}
|
||||
|
||||
// Build children if they exist
|
||||
List<Widget> pageChildren = [];
|
||||
if (widgetModel.children != null && widgetModel.children!.isNotEmpty) {
|
||||
pageChildren = widgetModel.children!.map((child) {
|
||||
try {
|
||||
return SDUIFormWidget(
|
||||
model: SDUIWidgetModel.fromJson(child),
|
||||
controllers: controllers,
|
||||
state: state,
|
||||
onStateChanged: onStateChanged,
|
||||
images: images,
|
||||
onImagesChanged: onImagesChanged,
|
||||
pageControllers: pageControllers,
|
||||
);
|
||||
} catch (e) {
|
||||
iLog('Error building page_view child: $e');
|
||||
iLog('Child data: $child');
|
||||
return Container(
|
||||
padding: EdgeInsets.all(8),
|
||||
color: Colors.yellow.withOpacity(0.1),
|
||||
child: Text('Child Error'),
|
||||
);
|
||||
}
|
||||
}).toList();
|
||||
}
|
||||
|
||||
return PageViewSDUI(
|
||||
model: pageViewModel,
|
||||
controller: pageController,
|
||||
children: pageChildren,
|
||||
state: state,
|
||||
controllers: controllers,
|
||||
onStateChanged: onStateChanged,
|
||||
images: images,
|
||||
onImagesChanged: onImagesChanged,
|
||||
);
|
||||
} catch (e, stackTrace) {
|
||||
iLog('Error building page_view: $e');
|
||||
iLog('Stack trace: $stackTrace');
|
||||
return Container(
|
||||
padding: EdgeInsets.all(16),
|
||||
color: Colors.blue.withOpacity(0.1),
|
||||
child: Text('PageView Error: $e'),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
bool _evaluateVisibleCondition(String condition) {
|
||||
if (state == null) {
|
||||
// If state is null, return true for first step (0) by default
|
||||
// This allows the form to work even without state initialization
|
||||
if (condition.contains('activeStepperIndex == 0')) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
// Simple condition evaluation
|
||||
// Supports: variable == value
|
||||
|
||||
if (condition.contains(' == ')) {
|
||||
final parts = condition.split(' == ');
|
||||
if (parts.length == 2) {
|
||||
final variable = parts[0].trim();
|
||||
var value = parts[1].trim();
|
||||
|
||||
// Remove quotes if present
|
||||
if ((value.startsWith("'") && value.endsWith("'")) ||
|
||||
(value.startsWith('"') && value.endsWith('"'))) {
|
||||
value = value.substring(1, value.length - 1);
|
||||
}
|
||||
|
||||
final stateValue = state![variable];
|
||||
if (stateValue == null) {
|
||||
// If variable doesn't exist in state, default to showing first step (0)
|
||||
if (variable == 'activeStepperIndex' && value == '0') {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Handle int comparison
|
||||
final intValue = int.tryParse(value);
|
||||
if (intValue != null) {
|
||||
if (stateValue is int) {
|
||||
return stateValue == intValue;
|
||||
}
|
||||
if (stateValue is num) {
|
||||
return stateValue.toInt() == intValue;
|
||||
}
|
||||
}
|
||||
|
||||
// Handle string comparison
|
||||
return stateValue.toString() == value;
|
||||
}
|
||||
}
|
||||
|
||||
// If condition format is not recognized, return false
|
||||
iLog('Unsupported visible_condition format: $condition');
|
||||
return false;
|
||||
} catch (e) {
|
||||
iLog('Error evaluating visible_condition: $e');
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,4 +16,3 @@ abstract class SDUIWidgetModel with _$SDUIWidgetModel {
|
||||
factory SDUIWidgetModel.fromJson(Map<String, dynamic> json) =>
|
||||
_$SDUIWidgetModelFromJson(json);
|
||||
}
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,76 @@
|
||||
# PageView SDUI Widget
|
||||
|
||||
این ویجت برای استفاده از PageView در ساختار SDUI طراحی شده است.
|
||||
|
||||
## استفاده در کد
|
||||
|
||||
```dart
|
||||
import 'package:rasadyar_chicken/presentation/widget/sdui/widgets/page_view/page_view_sdui.dart';
|
||||
import 'package:rasadyar_chicken/presentation/widget/sdui/widgets/page_view/model/page_view_sdui_model.dart';
|
||||
|
||||
// ایجاد مدل
|
||||
final pageViewModel = PageViewSDUIModel(
|
||||
key: 'pageController', // کلید برای دسترسی به PageController
|
||||
reverse: true,
|
||||
physics: 'neverScrollable', // 'neverScrollable', 'bouncing', 'clamping', 'alwaysScrollable'
|
||||
itemCount: 5,
|
||||
);
|
||||
|
||||
// استفاده از ویجت
|
||||
PageViewSDUI(
|
||||
model: pageViewModel,
|
||||
controller: controller.pageController, // PageController از logic
|
||||
children: pages, // لیست صفحات
|
||||
)
|
||||
```
|
||||
|
||||
## استفاده در JSON
|
||||
|
||||
```json
|
||||
{
|
||||
"type": "page_view",
|
||||
"visible": true,
|
||||
"data": {
|
||||
"key": "pageController",
|
||||
"reverse": true,
|
||||
"physics": "neverScrollable",
|
||||
"itemCount": 5
|
||||
},
|
||||
"children": [
|
||||
{
|
||||
"type": "column",
|
||||
"visible": true,
|
||||
"children": [...]
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
## پارامترها
|
||||
|
||||
- `key`: کلید برای دسترسی به PageController از map
|
||||
- `reverse`: جهت معکوس (پیشفرض: true)
|
||||
- `physics`: نوع فیزیک اسکرول ('neverScrollable', 'bouncing', 'clamping', 'alwaysScrollable')
|
||||
- `itemCount`: تعداد آیتمها (پیشفرض: تعداد children)
|
||||
|
||||
## مثال استفاده در create_inspection_bottom_sheet.dart
|
||||
|
||||
```dart
|
||||
import 'package:rasadyar_chicken/presentation/widget/sdui/widgets/page_view/page_view_sdui.dart';
|
||||
import 'package:rasadyar_chicken/presentation/widget/sdui/widgets/page_view/model/page_view_sdui_model.dart';
|
||||
|
||||
// در build method:
|
||||
Expanded(
|
||||
child: PageViewSDUI(
|
||||
model: PageViewSDUIModel(
|
||||
key: 'pageController',
|
||||
reverse: true,
|
||||
physics: 'neverScrollable',
|
||||
itemCount: pages.length,
|
||||
),
|
||||
controller: controller.pageController,
|
||||
children: pages,
|
||||
),
|
||||
),
|
||||
```
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
{
|
||||
"type": "page_view",
|
||||
"visible": true,
|
||||
"data": {
|
||||
"key": "pageController",
|
||||
"reverse": true,
|
||||
"physics": "neverScrollable",
|
||||
"itemCount": 5
|
||||
},
|
||||
"children": [
|
||||
{
|
||||
"type": "column",
|
||||
"visible": true,
|
||||
"data": {
|
||||
"spacing": 10.0
|
||||
},
|
||||
"children": [
|
||||
{
|
||||
"type": "text_form_field",
|
||||
"visible": true,
|
||||
"data": {
|
||||
"key": "field1",
|
||||
"label": "Field 1"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "column",
|
||||
"visible": true,
|
||||
"data": {
|
||||
"spacing": 10.0
|
||||
},
|
||||
"children": [
|
||||
{
|
||||
"type": "text_form_field",
|
||||
"visible": true,
|
||||
"data": {
|
||||
"key": "field2",
|
||||
"label": "Field 2"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||
|
||||
part 'page_view_sdui_model.freezed.dart';
|
||||
part 'page_view_sdui_model.g.dart';
|
||||
|
||||
@freezed
|
||||
abstract class PageViewSDUIModel with _$PageViewSDUIModel {
|
||||
const factory PageViewSDUIModel({
|
||||
String? key,
|
||||
bool? reverse,
|
||||
String? physics, // 'neverScrollable', 'bouncing', 'clamping', 'alwaysScrollable'
|
||||
int? itemCount,
|
||||
}) = _PageViewSDUIModel;
|
||||
|
||||
factory PageViewSDUIModel.fromJson(Map<String, dynamic> json) =>
|
||||
_$PageViewSDUIModelFromJson(json);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,288 @@
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
// coverage:ignore-file
|
||||
// ignore_for_file: type=lint
|
||||
// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark
|
||||
|
||||
part of 'page_view_sdui_model.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// FreezedGenerator
|
||||
// **************************************************************************
|
||||
|
||||
// dart format off
|
||||
T _$identity<T>(T value) => value;
|
||||
|
||||
/// @nodoc
|
||||
mixin _$PageViewSDUIModel {
|
||||
|
||||
String? get key; bool? get reverse; String? get physics;// 'neverScrollable', 'bouncing', 'clamping', 'alwaysScrollable'
|
||||
int? get itemCount;
|
||||
/// Create a copy of PageViewSDUIModel
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@pragma('vm:prefer-inline')
|
||||
$PageViewSDUIModelCopyWith<PageViewSDUIModel> get copyWith => _$PageViewSDUIModelCopyWithImpl<PageViewSDUIModel>(this as PageViewSDUIModel, _$identity);
|
||||
|
||||
/// Serializes this PageViewSDUIModel to a JSON map.
|
||||
Map<String, dynamic> toJson();
|
||||
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is PageViewSDUIModel&&(identical(other.key, key) || other.key == key)&&(identical(other.reverse, reverse) || other.reverse == reverse)&&(identical(other.physics, physics) || other.physics == physics)&&(identical(other.itemCount, itemCount) || other.itemCount == itemCount));
|
||||
}
|
||||
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType,key,reverse,physics,itemCount);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'PageViewSDUIModel(key: $key, reverse: $reverse, physics: $physics, itemCount: $itemCount)';
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract mixin class $PageViewSDUIModelCopyWith<$Res> {
|
||||
factory $PageViewSDUIModelCopyWith(PageViewSDUIModel value, $Res Function(PageViewSDUIModel) _then) = _$PageViewSDUIModelCopyWithImpl;
|
||||
@useResult
|
||||
$Res call({
|
||||
String? key, bool? reverse, String? physics, int? itemCount
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
/// @nodoc
|
||||
class _$PageViewSDUIModelCopyWithImpl<$Res>
|
||||
implements $PageViewSDUIModelCopyWith<$Res> {
|
||||
_$PageViewSDUIModelCopyWithImpl(this._self, this._then);
|
||||
|
||||
final PageViewSDUIModel _self;
|
||||
final $Res Function(PageViewSDUIModel) _then;
|
||||
|
||||
/// Create a copy of PageViewSDUIModel
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@pragma('vm:prefer-inline') @override $Res call({Object? key = freezed,Object? reverse = freezed,Object? physics = freezed,Object? itemCount = freezed,}) {
|
||||
return _then(_self.copyWith(
|
||||
key: freezed == key ? _self.key : key // ignore: cast_nullable_to_non_nullable
|
||||
as String?,reverse: freezed == reverse ? _self.reverse : reverse // ignore: cast_nullable_to_non_nullable
|
||||
as bool?,physics: freezed == physics ? _self.physics : physics // ignore: cast_nullable_to_non_nullable
|
||||
as String?,itemCount: freezed == itemCount ? _self.itemCount : itemCount // ignore: cast_nullable_to_non_nullable
|
||||
as int?,
|
||||
));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/// Adds pattern-matching-related methods to [PageViewSDUIModel].
|
||||
extension PageViewSDUIModelPatterns on PageViewSDUIModel {
|
||||
/// A variant of `map` that fallback to returning `orElse`.
|
||||
///
|
||||
/// It is equivalent to doing:
|
||||
/// ```dart
|
||||
/// switch (sealedClass) {
|
||||
/// case final Subclass value:
|
||||
/// return ...;
|
||||
/// case _:
|
||||
/// return orElse();
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult maybeMap<TResult extends Object?>(TResult Function( _PageViewSDUIModel value)? $default,{required TResult orElse(),}){
|
||||
final _that = this;
|
||||
switch (_that) {
|
||||
case _PageViewSDUIModel() when $default != null:
|
||||
return $default(_that);case _:
|
||||
return orElse();
|
||||
|
||||
}
|
||||
}
|
||||
/// A `switch`-like method, using callbacks.
|
||||
///
|
||||
/// Callbacks receives the raw object, upcasted.
|
||||
/// It is equivalent to doing:
|
||||
/// ```dart
|
||||
/// switch (sealedClass) {
|
||||
/// case final Subclass value:
|
||||
/// return ...;
|
||||
/// case final Subclass2 value:
|
||||
/// return ...;
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult map<TResult extends Object?>(TResult Function( _PageViewSDUIModel value) $default,){
|
||||
final _that = this;
|
||||
switch (_that) {
|
||||
case _PageViewSDUIModel():
|
||||
return $default(_that);case _:
|
||||
throw StateError('Unexpected subclass');
|
||||
|
||||
}
|
||||
}
|
||||
/// A variant of `map` that fallback to returning `null`.
|
||||
///
|
||||
/// It is equivalent to doing:
|
||||
/// ```dart
|
||||
/// switch (sealedClass) {
|
||||
/// case final Subclass value:
|
||||
/// return ...;
|
||||
/// case _:
|
||||
/// return null;
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult? mapOrNull<TResult extends Object?>(TResult? Function( _PageViewSDUIModel value)? $default,){
|
||||
final _that = this;
|
||||
switch (_that) {
|
||||
case _PageViewSDUIModel() when $default != null:
|
||||
return $default(_that);case _:
|
||||
return null;
|
||||
|
||||
}
|
||||
}
|
||||
/// A variant of `when` that fallback to an `orElse` callback.
|
||||
///
|
||||
/// It is equivalent to doing:
|
||||
/// ```dart
|
||||
/// switch (sealedClass) {
|
||||
/// case Subclass(:final field):
|
||||
/// return ...;
|
||||
/// case _:
|
||||
/// return orElse();
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( String? key, bool? reverse, String? physics, int? itemCount)? $default,{required TResult orElse(),}) {final _that = this;
|
||||
switch (_that) {
|
||||
case _PageViewSDUIModel() when $default != null:
|
||||
return $default(_that.key,_that.reverse,_that.physics,_that.itemCount);case _:
|
||||
return orElse();
|
||||
|
||||
}
|
||||
}
|
||||
/// A `switch`-like method, using callbacks.
|
||||
///
|
||||
/// As opposed to `map`, this offers destructuring.
|
||||
/// It is equivalent to doing:
|
||||
/// ```dart
|
||||
/// switch (sealedClass) {
|
||||
/// case Subclass(:final field):
|
||||
/// return ...;
|
||||
/// case Subclass2(:final field2):
|
||||
/// return ...;
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( String? key, bool? reverse, String? physics, int? itemCount) $default,) {final _that = this;
|
||||
switch (_that) {
|
||||
case _PageViewSDUIModel():
|
||||
return $default(_that.key,_that.reverse,_that.physics,_that.itemCount);case _:
|
||||
throw StateError('Unexpected subclass');
|
||||
|
||||
}
|
||||
}
|
||||
/// A variant of `when` that fallback to returning `null`
|
||||
///
|
||||
/// It is equivalent to doing:
|
||||
/// ```dart
|
||||
/// switch (sealedClass) {
|
||||
/// case Subclass(:final field):
|
||||
/// return ...;
|
||||
/// case _:
|
||||
/// return null;
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( String? key, bool? reverse, String? physics, int? itemCount)? $default,) {final _that = this;
|
||||
switch (_that) {
|
||||
case _PageViewSDUIModel() when $default != null:
|
||||
return $default(_that.key,_that.reverse,_that.physics,_that.itemCount);case _:
|
||||
return null;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
@JsonSerializable()
|
||||
|
||||
class _PageViewSDUIModel implements PageViewSDUIModel {
|
||||
const _PageViewSDUIModel({this.key, this.reverse, this.physics, this.itemCount});
|
||||
factory _PageViewSDUIModel.fromJson(Map<String, dynamic> json) => _$PageViewSDUIModelFromJson(json);
|
||||
|
||||
@override final String? key;
|
||||
@override final bool? reverse;
|
||||
@override final String? physics;
|
||||
// 'neverScrollable', 'bouncing', 'clamping', 'alwaysScrollable'
|
||||
@override final int? itemCount;
|
||||
|
||||
/// Create a copy of PageViewSDUIModel
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override @JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@pragma('vm:prefer-inline')
|
||||
_$PageViewSDUIModelCopyWith<_PageViewSDUIModel> get copyWith => __$PageViewSDUIModelCopyWithImpl<_PageViewSDUIModel>(this, _$identity);
|
||||
|
||||
@override
|
||||
Map<String, dynamic> toJson() {
|
||||
return _$PageViewSDUIModelToJson(this, );
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is _PageViewSDUIModel&&(identical(other.key, key) || other.key == key)&&(identical(other.reverse, reverse) || other.reverse == reverse)&&(identical(other.physics, physics) || other.physics == physics)&&(identical(other.itemCount, itemCount) || other.itemCount == itemCount));
|
||||
}
|
||||
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType,key,reverse,physics,itemCount);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'PageViewSDUIModel(key: $key, reverse: $reverse, physics: $physics, itemCount: $itemCount)';
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract mixin class _$PageViewSDUIModelCopyWith<$Res> implements $PageViewSDUIModelCopyWith<$Res> {
|
||||
factory _$PageViewSDUIModelCopyWith(_PageViewSDUIModel value, $Res Function(_PageViewSDUIModel) _then) = __$PageViewSDUIModelCopyWithImpl;
|
||||
@override @useResult
|
||||
$Res call({
|
||||
String? key, bool? reverse, String? physics, int? itemCount
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
/// @nodoc
|
||||
class __$PageViewSDUIModelCopyWithImpl<$Res>
|
||||
implements _$PageViewSDUIModelCopyWith<$Res> {
|
||||
__$PageViewSDUIModelCopyWithImpl(this._self, this._then);
|
||||
|
||||
final _PageViewSDUIModel _self;
|
||||
final $Res Function(_PageViewSDUIModel) _then;
|
||||
|
||||
/// Create a copy of PageViewSDUIModel
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override @pragma('vm:prefer-inline') $Res call({Object? key = freezed,Object? reverse = freezed,Object? physics = freezed,Object? itemCount = freezed,}) {
|
||||
return _then(_PageViewSDUIModel(
|
||||
key: freezed == key ? _self.key : key // ignore: cast_nullable_to_non_nullable
|
||||
as String?,reverse: freezed == reverse ? _self.reverse : reverse // ignore: cast_nullable_to_non_nullable
|
||||
as bool?,physics: freezed == physics ? _self.physics : physics // ignore: cast_nullable_to_non_nullable
|
||||
as String?,itemCount: freezed == itemCount ? _self.itemCount : itemCount // ignore: cast_nullable_to_non_nullable
|
||||
as int?,
|
||||
));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
// dart format on
|
||||
@@ -0,0 +1,23 @@
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'page_view_sdui_model.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// JsonSerializableGenerator
|
||||
// **************************************************************************
|
||||
|
||||
_PageViewSDUIModel _$PageViewSDUIModelFromJson(Map<String, dynamic> json) =>
|
||||
_PageViewSDUIModel(
|
||||
key: json['key'] as String?,
|
||||
reverse: json['reverse'] as bool?,
|
||||
physics: json['physics'] as String?,
|
||||
itemCount: (json['item_count'] as num?)?.toInt(),
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$PageViewSDUIModelToJson(_PageViewSDUIModel instance) =>
|
||||
<String, dynamic>{
|
||||
'key': instance.key,
|
||||
'reverse': instance.reverse,
|
||||
'physics': instance.physics,
|
||||
'item_count': instance.itemCount,
|
||||
};
|
||||
@@ -0,0 +1,61 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:rasadyar_chicken/presentation/widget/sdui/widgets/page_view/model/page_view_sdui_model.dart';
|
||||
import 'package:rasadyar_core/core.dart';
|
||||
|
||||
class PageViewSDUI extends StatelessWidget {
|
||||
final PageViewSDUIModel model;
|
||||
final PageController? controller;
|
||||
final List<Widget> children;
|
||||
final RxMap<String, dynamic>? state;
|
||||
final Map<String, TextEditingController>? controllers;
|
||||
final Function(String key, dynamic value)? onStateChanged;
|
||||
final Map<String, RxList<XFile>>? images;
|
||||
final Function(String key, RxList<XFile> images)? onImagesChanged;
|
||||
|
||||
const PageViewSDUI({
|
||||
super.key,
|
||||
required this.model,
|
||||
required this.children,
|
||||
this.controller,
|
||||
this.state,
|
||||
this.controllers,
|
||||
this.onStateChanged,
|
||||
this.images,
|
||||
this.onImagesChanged,
|
||||
});
|
||||
|
||||
ScrollPhysics? _parsePhysics(String? physics) {
|
||||
switch (physics) {
|
||||
case 'neverScrollable':
|
||||
return const NeverScrollableScrollPhysics();
|
||||
case 'bouncing':
|
||||
return const BouncingScrollPhysics();
|
||||
case 'clamping':
|
||||
return const ClampingScrollPhysics();
|
||||
case 'alwaysScrollable':
|
||||
return const AlwaysScrollableScrollPhysics();
|
||||
default:
|
||||
return const NeverScrollableScrollPhysics();
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final physics = _parsePhysics(model.physics);
|
||||
final reverse = model.reverse ?? true;
|
||||
final itemCount = model.itemCount ?? children.length;
|
||||
|
||||
return PageView.builder(
|
||||
physics: physics,
|
||||
reverse: reverse,
|
||||
controller: controller,
|
||||
itemCount: itemCount,
|
||||
itemBuilder: (context, index) {
|
||||
if (index < children.length) {
|
||||
return children[index];
|
||||
}
|
||||
return const SizedBox.shrink();
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"type": "stepper",
|
||||
"visible": true,
|
||||
"data": {
|
||||
"key": "activeStepperIndex",
|
||||
"totalSteps": 5,
|
||||
"activeStep": 0
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||
|
||||
part 'stepper_sdui_model.freezed.dart';
|
||||
part 'stepper_sdui_model.g.dart';
|
||||
|
||||
@freezed
|
||||
abstract class StepperSDUIModel with _$StepperSDUIModel {
|
||||
const factory StepperSDUIModel({
|
||||
String? key,
|
||||
int? totalSteps,
|
||||
int? activeStep,
|
||||
}) = _StepperSDUIModel;
|
||||
|
||||
factory StepperSDUIModel.fromJson(Map<String, dynamic> json) =>
|
||||
_$StepperSDUIModelFromJson(json);
|
||||
}
|
||||
@@ -0,0 +1,283 @@
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
// coverage:ignore-file
|
||||
// ignore_for_file: type=lint
|
||||
// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark
|
||||
|
||||
part of 'stepper_sdui_model.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// FreezedGenerator
|
||||
// **************************************************************************
|
||||
|
||||
// dart format off
|
||||
T _$identity<T>(T value) => value;
|
||||
|
||||
/// @nodoc
|
||||
mixin _$StepperSDUIModel {
|
||||
|
||||
String? get key; int? get totalSteps; int? get activeStep;
|
||||
/// Create a copy of StepperSDUIModel
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@pragma('vm:prefer-inline')
|
||||
$StepperSDUIModelCopyWith<StepperSDUIModel> get copyWith => _$StepperSDUIModelCopyWithImpl<StepperSDUIModel>(this as StepperSDUIModel, _$identity);
|
||||
|
||||
/// Serializes this StepperSDUIModel to a JSON map.
|
||||
Map<String, dynamic> toJson();
|
||||
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is StepperSDUIModel&&(identical(other.key, key) || other.key == key)&&(identical(other.totalSteps, totalSteps) || other.totalSteps == totalSteps)&&(identical(other.activeStep, activeStep) || other.activeStep == activeStep));
|
||||
}
|
||||
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType,key,totalSteps,activeStep);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'StepperSDUIModel(key: $key, totalSteps: $totalSteps, activeStep: $activeStep)';
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract mixin class $StepperSDUIModelCopyWith<$Res> {
|
||||
factory $StepperSDUIModelCopyWith(StepperSDUIModel value, $Res Function(StepperSDUIModel) _then) = _$StepperSDUIModelCopyWithImpl;
|
||||
@useResult
|
||||
$Res call({
|
||||
String? key, int? totalSteps, int? activeStep
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
/// @nodoc
|
||||
class _$StepperSDUIModelCopyWithImpl<$Res>
|
||||
implements $StepperSDUIModelCopyWith<$Res> {
|
||||
_$StepperSDUIModelCopyWithImpl(this._self, this._then);
|
||||
|
||||
final StepperSDUIModel _self;
|
||||
final $Res Function(StepperSDUIModel) _then;
|
||||
|
||||
/// Create a copy of StepperSDUIModel
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@pragma('vm:prefer-inline') @override $Res call({Object? key = freezed,Object? totalSteps = freezed,Object? activeStep = freezed,}) {
|
||||
return _then(_self.copyWith(
|
||||
key: freezed == key ? _self.key : key // ignore: cast_nullable_to_non_nullable
|
||||
as String?,totalSteps: freezed == totalSteps ? _self.totalSteps : totalSteps // ignore: cast_nullable_to_non_nullable
|
||||
as int?,activeStep: freezed == activeStep ? _self.activeStep : activeStep // ignore: cast_nullable_to_non_nullable
|
||||
as int?,
|
||||
));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/// Adds pattern-matching-related methods to [StepperSDUIModel].
|
||||
extension StepperSDUIModelPatterns on StepperSDUIModel {
|
||||
/// A variant of `map` that fallback to returning `orElse`.
|
||||
///
|
||||
/// It is equivalent to doing:
|
||||
/// ```dart
|
||||
/// switch (sealedClass) {
|
||||
/// case final Subclass value:
|
||||
/// return ...;
|
||||
/// case _:
|
||||
/// return orElse();
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult maybeMap<TResult extends Object?>(TResult Function( _StepperSDUIModel value)? $default,{required TResult orElse(),}){
|
||||
final _that = this;
|
||||
switch (_that) {
|
||||
case _StepperSDUIModel() when $default != null:
|
||||
return $default(_that);case _:
|
||||
return orElse();
|
||||
|
||||
}
|
||||
}
|
||||
/// A `switch`-like method, using callbacks.
|
||||
///
|
||||
/// Callbacks receives the raw object, upcasted.
|
||||
/// It is equivalent to doing:
|
||||
/// ```dart
|
||||
/// switch (sealedClass) {
|
||||
/// case final Subclass value:
|
||||
/// return ...;
|
||||
/// case final Subclass2 value:
|
||||
/// return ...;
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult map<TResult extends Object?>(TResult Function( _StepperSDUIModel value) $default,){
|
||||
final _that = this;
|
||||
switch (_that) {
|
||||
case _StepperSDUIModel():
|
||||
return $default(_that);case _:
|
||||
throw StateError('Unexpected subclass');
|
||||
|
||||
}
|
||||
}
|
||||
/// A variant of `map` that fallback to returning `null`.
|
||||
///
|
||||
/// It is equivalent to doing:
|
||||
/// ```dart
|
||||
/// switch (sealedClass) {
|
||||
/// case final Subclass value:
|
||||
/// return ...;
|
||||
/// case _:
|
||||
/// return null;
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult? mapOrNull<TResult extends Object?>(TResult? Function( _StepperSDUIModel value)? $default,){
|
||||
final _that = this;
|
||||
switch (_that) {
|
||||
case _StepperSDUIModel() when $default != null:
|
||||
return $default(_that);case _:
|
||||
return null;
|
||||
|
||||
}
|
||||
}
|
||||
/// A variant of `when` that fallback to an `orElse` callback.
|
||||
///
|
||||
/// It is equivalent to doing:
|
||||
/// ```dart
|
||||
/// switch (sealedClass) {
|
||||
/// case Subclass(:final field):
|
||||
/// return ...;
|
||||
/// case _:
|
||||
/// return orElse();
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( String? key, int? totalSteps, int? activeStep)? $default,{required TResult orElse(),}) {final _that = this;
|
||||
switch (_that) {
|
||||
case _StepperSDUIModel() when $default != null:
|
||||
return $default(_that.key,_that.totalSteps,_that.activeStep);case _:
|
||||
return orElse();
|
||||
|
||||
}
|
||||
}
|
||||
/// A `switch`-like method, using callbacks.
|
||||
///
|
||||
/// As opposed to `map`, this offers destructuring.
|
||||
/// It is equivalent to doing:
|
||||
/// ```dart
|
||||
/// switch (sealedClass) {
|
||||
/// case Subclass(:final field):
|
||||
/// return ...;
|
||||
/// case Subclass2(:final field2):
|
||||
/// return ...;
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( String? key, int? totalSteps, int? activeStep) $default,) {final _that = this;
|
||||
switch (_that) {
|
||||
case _StepperSDUIModel():
|
||||
return $default(_that.key,_that.totalSteps,_that.activeStep);case _:
|
||||
throw StateError('Unexpected subclass');
|
||||
|
||||
}
|
||||
}
|
||||
/// A variant of `when` that fallback to returning `null`
|
||||
///
|
||||
/// It is equivalent to doing:
|
||||
/// ```dart
|
||||
/// switch (sealedClass) {
|
||||
/// case Subclass(:final field):
|
||||
/// return ...;
|
||||
/// case _:
|
||||
/// return null;
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( String? key, int? totalSteps, int? activeStep)? $default,) {final _that = this;
|
||||
switch (_that) {
|
||||
case _StepperSDUIModel() when $default != null:
|
||||
return $default(_that.key,_that.totalSteps,_that.activeStep);case _:
|
||||
return null;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
@JsonSerializable()
|
||||
|
||||
class _StepperSDUIModel implements StepperSDUIModel {
|
||||
const _StepperSDUIModel({this.key, this.totalSteps, this.activeStep});
|
||||
factory _StepperSDUIModel.fromJson(Map<String, dynamic> json) => _$StepperSDUIModelFromJson(json);
|
||||
|
||||
@override final String? key;
|
||||
@override final int? totalSteps;
|
||||
@override final int? activeStep;
|
||||
|
||||
/// Create a copy of StepperSDUIModel
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override @JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@pragma('vm:prefer-inline')
|
||||
_$StepperSDUIModelCopyWith<_StepperSDUIModel> get copyWith => __$StepperSDUIModelCopyWithImpl<_StepperSDUIModel>(this, _$identity);
|
||||
|
||||
@override
|
||||
Map<String, dynamic> toJson() {
|
||||
return _$StepperSDUIModelToJson(this, );
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is _StepperSDUIModel&&(identical(other.key, key) || other.key == key)&&(identical(other.totalSteps, totalSteps) || other.totalSteps == totalSteps)&&(identical(other.activeStep, activeStep) || other.activeStep == activeStep));
|
||||
}
|
||||
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType,key,totalSteps,activeStep);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'StepperSDUIModel(key: $key, totalSteps: $totalSteps, activeStep: $activeStep)';
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract mixin class _$StepperSDUIModelCopyWith<$Res> implements $StepperSDUIModelCopyWith<$Res> {
|
||||
factory _$StepperSDUIModelCopyWith(_StepperSDUIModel value, $Res Function(_StepperSDUIModel) _then) = __$StepperSDUIModelCopyWithImpl;
|
||||
@override @useResult
|
||||
$Res call({
|
||||
String? key, int? totalSteps, int? activeStep
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
/// @nodoc
|
||||
class __$StepperSDUIModelCopyWithImpl<$Res>
|
||||
implements _$StepperSDUIModelCopyWith<$Res> {
|
||||
__$StepperSDUIModelCopyWithImpl(this._self, this._then);
|
||||
|
||||
final _StepperSDUIModel _self;
|
||||
final $Res Function(_StepperSDUIModel) _then;
|
||||
|
||||
/// Create a copy of StepperSDUIModel
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override @pragma('vm:prefer-inline') $Res call({Object? key = freezed,Object? totalSteps = freezed,Object? activeStep = freezed,}) {
|
||||
return _then(_StepperSDUIModel(
|
||||
key: freezed == key ? _self.key : key // ignore: cast_nullable_to_non_nullable
|
||||
as String?,totalSteps: freezed == totalSteps ? _self.totalSteps : totalSteps // ignore: cast_nullable_to_non_nullable
|
||||
as int?,activeStep: freezed == activeStep ? _self.activeStep : activeStep // ignore: cast_nullable_to_non_nullable
|
||||
as int?,
|
||||
));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
// dart format on
|
||||
@@ -0,0 +1,21 @@
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'stepper_sdui_model.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// JsonSerializableGenerator
|
||||
// **************************************************************************
|
||||
|
||||
_StepperSDUIModel _$StepperSDUIModelFromJson(Map<String, dynamic> json) =>
|
||||
_StepperSDUIModel(
|
||||
key: json['key'] as String?,
|
||||
totalSteps: (json['total_steps'] as num?)?.toInt(),
|
||||
activeStep: (json['active_step'] as num?)?.toInt(),
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$StepperSDUIModelToJson(_StepperSDUIModel instance) =>
|
||||
<String, dynamic>{
|
||||
'key': instance.key,
|
||||
'total_steps': instance.totalSteps,
|
||||
'active_step': instance.activeStep,
|
||||
};
|
||||
@@ -0,0 +1,75 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:rasadyar_chicken/presentation/widget/sdui/widgets/stepper/model/stepper_sdui_model.dart';
|
||||
import 'package:rasadyar_core/core.dart';
|
||||
|
||||
class StepperSDUI extends StatelessWidget {
|
||||
final StepperSDUIModel model;
|
||||
final RxMap<String, dynamic>? state;
|
||||
|
||||
const StepperSDUI({super.key, required this.model, this.state});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final totalSteps = model.totalSteps ?? 5;
|
||||
|
||||
return Obx(() {
|
||||
final activeStep = state?[model.key] as int? ?? model.activeStep ?? 0;
|
||||
|
||||
return Directionality(
|
||||
textDirection: TextDirection.ltr,
|
||||
child: SizedBox(
|
||||
height: 24,
|
||||
width: Get.width,
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: _buildSteps(totalSteps, activeStep),
|
||||
),
|
||||
),
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
List<Widget> _buildSteps(int totalSteps, int activeStep) {
|
||||
final List<Widget> widgets = [];
|
||||
|
||||
for (int i = 0; i < totalSteps; i++) {
|
||||
// Add step circle
|
||||
widgets.add(
|
||||
Container(
|
||||
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(
|
||||
Expanded(
|
||||
child: Divider(
|
||||
color: activeStep >= i + 1
|
||||
? AppColor.greenNormalHover
|
||||
: AppColor.whiteNormalActive,
|
||||
thickness: 8,
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return widgets;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user