feat: refactor NewPageLogic to utilize SDUIWidgetModel, enhance form handling with dynamic controllers, and implement SDUIFormWidget for rendering UI components

This commit is contained in:
2025-12-28 13:50:48 +03:30
parent 0b49302434
commit 71952bef5a
27 changed files with 3022 additions and 52 deletions

View File

@@ -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;
}
}
}