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:
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user