feat: refactor NewPageLogic to utilize SDUIWidgetModel, enhance form handling with dynamic controllers, and implement SDUIFormWidget for rendering UI components
This commit is contained in:
@@ -0,0 +1,418 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:rasadyar_chicken/presentation/widget/sdui/model/sdui_widget_model.dart';
|
||||
import 'package:rasadyar_chicken/presentation/widget/sdui/widgets/card_label_item/card_label_item_sdui.dart';
|
||||
import 'package:rasadyar_chicken/presentation/widget/sdui/widgets/card_label_item/model/card_label_item_sdui_model.dart';
|
||||
import 'package:rasadyar_chicken/presentation/widget/sdui/widgets/chip_selection/chip_selection_sdui.dart';
|
||||
import 'package:rasadyar_chicken/presentation/widget/sdui/widgets/chip_selection/model/chip_selection_sdui_model.dart';
|
||||
import 'package:rasadyar_chicken/presentation/widget/sdui/widgets/dropdown/dropdown_sdui.dart';
|
||||
import 'package:rasadyar_chicken/presentation/widget/sdui/widgets/dropdown/model/dropdown_sdui_model.dart';
|
||||
import 'package:rasadyar_chicken/presentation/widget/sdui/widgets/image_picker/image_picker_sdui.dart';
|
||||
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_core/core.dart';
|
||||
|
||||
class SDUIFormWidget extends StatelessWidget {
|
||||
final SDUIWidgetModel model;
|
||||
final Map<String, TextEditingController>? controllers;
|
||||
final RxMap<String, dynamic>? state;
|
||||
final Function(String key, dynamic value)? onStateChanged;
|
||||
final Map<String, RxList<XFile>>? images;
|
||||
final Function(String key, RxList<XFile> images)? onImagesChanged;
|
||||
|
||||
const SDUIFormWidget({
|
||||
super.key,
|
||||
required this.model,
|
||||
this.controllers,
|
||||
this.state,
|
||||
this.onStateChanged,
|
||||
this.images,
|
||||
this.onImagesChanged,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
if (model.visible == false) {
|
||||
return const SizedBox.shrink();
|
||||
}
|
||||
|
||||
try {
|
||||
return _buildWidget(model);
|
||||
} catch (e, stackTrace) {
|
||||
iLog('Error in SDUIFormWidget.build: $e');
|
||||
iLog('Stack trace: $stackTrace');
|
||||
return Container(
|
||||
padding: EdgeInsets.all(16),
|
||||
color: Colors.red.withOpacity(0.1),
|
||||
child: Text('Error: $e'),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Widget _buildWidget(SDUIWidgetModel widgetModel) {
|
||||
final type = widgetModel.type;
|
||||
|
||||
if (type == null || type.isEmpty) {
|
||||
iLog('SDUIWidgetModel type is null or empty');
|
||||
return const SizedBox.shrink();
|
||||
}
|
||||
|
||||
switch (type) {
|
||||
case 'text_form_field':
|
||||
return _buildTextFormField(widgetModel);
|
||||
case 'card_label_item':
|
||||
return _buildCardLabelItem(widgetModel);
|
||||
case 'chip_selection':
|
||||
return _buildChipSelection(widgetModel);
|
||||
case 'dropdown':
|
||||
return _buildDropdown(widgetModel);
|
||||
case 'image_picker':
|
||||
return _buildImagePicker(widgetModel);
|
||||
case 'column':
|
||||
return _buildColumn(widgetModel);
|
||||
case 'row':
|
||||
return _buildRow(widgetModel);
|
||||
case 'sized_box':
|
||||
return _buildSizedBox(widgetModel);
|
||||
default:
|
||||
iLog('Unknown SDUI widget type: $type');
|
||||
return const SizedBox.shrink();
|
||||
}
|
||||
}
|
||||
|
||||
Widget _buildTextFormField(SDUIWidgetModel widgetModel) {
|
||||
if (widgetModel.data == null) {
|
||||
return const SizedBox.shrink();
|
||||
}
|
||||
|
||||
try {
|
||||
final textFieldModel = TextFormFieldSDUIModel.fromJson(widgetModel.data!);
|
||||
|
||||
// Use provided controller or create a new one
|
||||
final key = textFieldModel.key ?? '';
|
||||
TextEditingController controller;
|
||||
|
||||
if (controllers != null &&
|
||||
key.isNotEmpty &&
|
||||
controllers!.containsKey(key)) {
|
||||
controller = controllers![key]!;
|
||||
} else {
|
||||
controller = TextEditingController(text: textFieldModel.value ?? '');
|
||||
// Store the controller in the map if controllers map is provided
|
||||
if (controllers != null && key.isNotEmpty) {
|
||||
controllers![key] = controller;
|
||||
}
|
||||
}
|
||||
|
||||
return textFormFiledSDUI(model: textFieldModel, controller: controller);
|
||||
} catch (e) {
|
||||
iLog('Error building text_form_field: $e');
|
||||
return const SizedBox.shrink();
|
||||
}
|
||||
}
|
||||
|
||||
Widget _buildCardLabelItem(SDUIWidgetModel widgetModel) {
|
||||
try {
|
||||
final cardModel = CardLabelItemSDUI.fromJson({
|
||||
'type': widgetModel.type,
|
||||
'visible': widgetModel.visible,
|
||||
'data': widgetModel.data,
|
||||
'child': widgetModel.child,
|
||||
});
|
||||
|
||||
// If there's a child, build it recursively
|
||||
Widget? childWidget;
|
||||
if (widgetModel.child != null) {
|
||||
try {
|
||||
childWidget = SDUIFormWidget(
|
||||
model: SDUIWidgetModel.fromJson(widgetModel.child!),
|
||||
controllers: controllers,
|
||||
state: state,
|
||||
onStateChanged: onStateChanged,
|
||||
images: images,
|
||||
onImagesChanged: onImagesChanged,
|
||||
);
|
||||
} catch (e) {
|
||||
iLog('Error building card_label_item child: $e');
|
||||
iLog('Child data: ${widgetModel.child}');
|
||||
}
|
||||
} else if (widgetModel.children != null &&
|
||||
widgetModel.children!.isNotEmpty) {
|
||||
// If there are children, build them as a column
|
||||
try {
|
||||
childWidget = Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: widgetModel.children!
|
||||
.map(
|
||||
(child) => SDUIFormWidget(
|
||||
model: SDUIWidgetModel.fromJson(child),
|
||||
controllers: controllers,
|
||||
state: state,
|
||||
onStateChanged: onStateChanged,
|
||||
images: images,
|
||||
onImagesChanged: onImagesChanged,
|
||||
),
|
||||
)
|
||||
.toList(),
|
||||
);
|
||||
} catch (e) {
|
||||
iLog('Error building card_label_item children: $e');
|
||||
}
|
||||
}
|
||||
|
||||
// Create a modified card model with the child widget
|
||||
return cardLabelItemSDUI(model: cardModel, child: childWidget);
|
||||
} 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 _buildColumn(SDUIWidgetModel widgetModel) {
|
||||
if (widgetModel.children == null || widgetModel.children!.isEmpty) {
|
||||
iLog('Column has no children');
|
||||
return const SizedBox.shrink();
|
||||
}
|
||||
|
||||
try {
|
||||
final spacing = widgetModel.data?['spacing'];
|
||||
final spacingValue = spacing is int
|
||||
? spacing.toDouble()
|
||||
: (spacing as double?) ?? 0.0;
|
||||
|
||||
final mainAxisSize = widgetModel.data?['mainAxisSize'] == 'min'
|
||||
? MainAxisSize.min
|
||||
: MainAxisSize.max;
|
||||
final crossAxisAlignment = _parseCrossAxisAlignment(
|
||||
widgetModel.data?['crossAxisAlignment'],
|
||||
);
|
||||
|
||||
final children = widgetModel.children!.map((child) {
|
||||
try {
|
||||
return SDUIFormWidget(
|
||||
model: SDUIWidgetModel.fromJson(child),
|
||||
controllers: controllers,
|
||||
state: state,
|
||||
onStateChanged: onStateChanged,
|
||||
images: images,
|
||||
onImagesChanged: onImagesChanged,
|
||||
);
|
||||
} catch (e) {
|
||||
iLog('Error building column child: $e');
|
||||
iLog('Child data: $child');
|
||||
return Container(
|
||||
padding: EdgeInsets.all(8),
|
||||
color: Colors.yellow.withOpacity(0.1),
|
||||
child: Text('Child Error'),
|
||||
);
|
||||
}
|
||||
}).toList();
|
||||
|
||||
// Add spacing between children
|
||||
if (spacingValue > 0 && children.length > 1) {
|
||||
final spacedChildren = <Widget>[];
|
||||
for (int i = 0; i < children.length; i++) {
|
||||
spacedChildren.add(children[i]);
|
||||
if (i < children.length - 1) {
|
||||
spacedChildren.add(SizedBox(height: spacingValue));
|
||||
}
|
||||
}
|
||||
return Column(
|
||||
mainAxisSize: mainAxisSize,
|
||||
crossAxisAlignment: crossAxisAlignment,
|
||||
children: spacedChildren,
|
||||
);
|
||||
}
|
||||
|
||||
return Column(
|
||||
mainAxisSize: mainAxisSize,
|
||||
crossAxisAlignment: crossAxisAlignment,
|
||||
children: children,
|
||||
);
|
||||
} catch (e, stackTrace) {
|
||||
iLog('Error building column: $e');
|
||||
iLog('Stack trace: $stackTrace');
|
||||
return Container(
|
||||
padding: EdgeInsets.all(16),
|
||||
color: Colors.blue.withOpacity(0.1),
|
||||
child: Text('Column Error: $e'),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Widget _buildRow(SDUIWidgetModel widgetModel) {
|
||||
if (widgetModel.children == null || widgetModel.children!.isEmpty) {
|
||||
return const SizedBox.shrink();
|
||||
}
|
||||
|
||||
final spacing = widgetModel.data?['spacing'] as double? ?? 0.0;
|
||||
final mainAxisAlignment = _parseMainAxisAlignment(
|
||||
widgetModel.data?['mainAxisAlignment'],
|
||||
);
|
||||
|
||||
final children = widgetModel.children!
|
||||
.map(
|
||||
(child) => SDUIFormWidget(
|
||||
model: SDUIWidgetModel.fromJson(child),
|
||||
controllers: controllers,
|
||||
state: state,
|
||||
onStateChanged: onStateChanged,
|
||||
images: images,
|
||||
onImagesChanged: onImagesChanged,
|
||||
),
|
||||
)
|
||||
.toList();
|
||||
|
||||
// Add spacing between children
|
||||
if (spacing > 0 && children.length > 1) {
|
||||
final spacedChildren = <Widget>[];
|
||||
for (int i = 0; i < children.length; i++) {
|
||||
spacedChildren.add(children[i]);
|
||||
if (i < children.length - 1) {
|
||||
spacedChildren.add(SizedBox(width: spacing));
|
||||
}
|
||||
}
|
||||
return Row(
|
||||
mainAxisAlignment: mainAxisAlignment,
|
||||
children: spacedChildren,
|
||||
);
|
||||
}
|
||||
|
||||
return Row(mainAxisAlignment: mainAxisAlignment, children: children);
|
||||
}
|
||||
|
||||
Widget _buildSizedBox(SDUIWidgetModel widgetModel) {
|
||||
final data = widgetModel.data ?? {};
|
||||
final width = data['width'] as double?;
|
||||
final height = data['height'] as double?;
|
||||
|
||||
return SizedBox(width: width, height: height);
|
||||
}
|
||||
|
||||
Widget _buildChipSelection(SDUIWidgetModel widgetModel) {
|
||||
if (widgetModel.data == null) {
|
||||
return const SizedBox.shrink();
|
||||
}
|
||||
|
||||
try {
|
||||
final chipModel = ChipSelectionSDUIModel.fromJson(widgetModel.data!);
|
||||
|
||||
return ChipSelectionSDUI(
|
||||
model: chipModel,
|
||||
state: state,
|
||||
onChanged: (key, index, value) {
|
||||
if (onStateChanged != null) {
|
||||
onStateChanged!(key, index);
|
||||
}
|
||||
},
|
||||
);
|
||||
} catch (e, stackTrace) {
|
||||
iLog('Error building chip_selection: $e');
|
||||
iLog('Stack trace: $stackTrace');
|
||||
return Container(
|
||||
padding: EdgeInsets.all(16),
|
||||
color: Colors.purple.withOpacity(0.1),
|
||||
child: Text('Chip Selection Error: $e'),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Widget _buildDropdown(SDUIWidgetModel widgetModel) {
|
||||
if (widgetModel.data == null) {
|
||||
return const SizedBox.shrink();
|
||||
}
|
||||
|
||||
try {
|
||||
final dropdownModel = DropdownSDUIModel.fromJson(widgetModel.data!);
|
||||
|
||||
return DropdownSDUI(
|
||||
model: dropdownModel,
|
||||
state: state,
|
||||
onChanged: (key, value) {
|
||||
if (onStateChanged != null) {
|
||||
onStateChanged!(key, value);
|
||||
}
|
||||
},
|
||||
);
|
||||
} catch (e, stackTrace) {
|
||||
iLog('Error building dropdown: $e');
|
||||
iLog('Stack trace: $stackTrace');
|
||||
return Container(
|
||||
padding: EdgeInsets.all(16),
|
||||
color: Colors.blue.withOpacity(0.1),
|
||||
child: Text('Dropdown Error: $e'),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Widget _buildImagePicker(SDUIWidgetModel widgetModel) {
|
||||
if (widgetModel.data == null) {
|
||||
return const SizedBox.shrink();
|
||||
}
|
||||
|
||||
try {
|
||||
final imagePickerModel = ImagePickerSDUIModel.fromJson(widgetModel.data!);
|
||||
|
||||
return ImagePickerSDUI(
|
||||
model: imagePickerModel,
|
||||
images: images,
|
||||
onImagesChanged: (key, imageList) {
|
||||
if (onImagesChanged != null) {
|
||||
onImagesChanged!(key, imageList);
|
||||
}
|
||||
},
|
||||
);
|
||||
} catch (e, stackTrace) {
|
||||
iLog('Error building image_picker: $e');
|
||||
iLog('Stack trace: $stackTrace');
|
||||
return Container(
|
||||
padding: EdgeInsets.all(16),
|
||||
color: Colors.green.withOpacity(0.1),
|
||||
child: Text('Image Picker Error: $e'),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
CrossAxisAlignment _parseCrossAxisAlignment(dynamic value) {
|
||||
if (value == null) return CrossAxisAlignment.center;
|
||||
switch (value.toString()) {
|
||||
case 'start':
|
||||
return CrossAxisAlignment.start;
|
||||
case 'end':
|
||||
return CrossAxisAlignment.end;
|
||||
case 'center':
|
||||
return CrossAxisAlignment.center;
|
||||
case 'stretch':
|
||||
return CrossAxisAlignment.stretch;
|
||||
default:
|
||||
return CrossAxisAlignment.center;
|
||||
}
|
||||
}
|
||||
|
||||
MainAxisAlignment _parseMainAxisAlignment(dynamic value) {
|
||||
if (value == null) return MainAxisAlignment.start;
|
||||
switch (value.toString()) {
|
||||
case 'start':
|
||||
return MainAxisAlignment.start;
|
||||
case 'end':
|
||||
return MainAxisAlignment.end;
|
||||
case 'center':
|
||||
return MainAxisAlignment.center;
|
||||
case 'spaceBetween':
|
||||
return MainAxisAlignment.spaceBetween;
|
||||
case 'spaceAround':
|
||||
return MainAxisAlignment.spaceAround;
|
||||
case 'spaceEvenly':
|
||||
return MainAxisAlignment.spaceEvenly;
|
||||
default:
|
||||
return MainAxisAlignment.start;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user