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

@@ -1,13 +1,15 @@
import 'package:rasadyar_chicken/features/vet_farm/data/repositories/vet_farm_repository.dart';
import 'package:flutter/material.dart';
import 'package:rasadyar_chicken/features/vet_farm/presentation/pages/root/logic.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/model/sdui_widget_model.dart';
import 'package:rasadyar_core/core.dart';
class NewPageLogic extends GetxController {
VetFarmRootLogic rootLogic = Get.find<VetFarmRootLogic>();
Rxn<TextFormFieldSDUIModel> textFormFieldSDUIModel =
Rxn<TextFormFieldSDUIModel>();
Rxn<SDUIWidgetModel> sduiModel = Rxn<SDUIWidgetModel>();
Map<String, TextEditingController> controllers = {};
RxMap<String, dynamic> formState = <String, dynamic>{}.obs;
Map<String, RxList<XFile>> images = {};
@override
void onInit() {
@@ -24,23 +26,106 @@ class NewPageLogic extends GetxController {
@override
void onClose() {
// Dispose all controllers
for (var controller in controllers.values) {
controller.dispose();
}
controllers.clear();
super.onClose();
// Cleanup logic here
}
Future<void> getSDUIForm() async {
await safeCall(
call: () async => await rootLogic.vetFarmRepository.getSDUIForm(),
onSuccess: (result) {
textFormFieldSDUIModel.value = TextFormFieldSDUIModel.fromJson(
result.data ?? {},
);
if (result.data != null) {
try {
iLog('SDUI JSON received: ${result.data}');
// Extract SDUI data from info structure
// JSON structure: { "info": { "type": "column", "visible": true, "data": {...}, "children": [...] } }
Map<String, dynamic>? sduiData;
if (result.data!['info'] != null && result.data!['info'] is Map) {
final infoMap = result.data!['info'] as Map<String, dynamic>;
// Check if info has type field (meaning it's the SDUI structure itself)
if (infoMap.containsKey('type')) {
sduiData = infoMap;
iLog(
'SDUI data extracted from info (info contains type field)',
);
} else if (infoMap['data'] != null) {
// Fallback: if info.data exists, use it
sduiData = infoMap['data'] as Map<String, dynamic>;
iLog('SDUI data extracted from info.data');
} else {
iLog('info exists but has no type or data field');
}
} else {
// Fallback: try direct data structure
sduiData = result.data;
iLog('Using direct data structure (no info field)');
}
if (sduiData != null) {
iLog('SDUI data to parse: $sduiData');
sduiModel.value = SDUIWidgetModel.fromJson(sduiData);
iLog(
'SDUI Model parsed successfully. Type: ${sduiModel.value?.type}, Visible: ${sduiModel.value?.visible}, Children count: ${sduiModel.value?.children?.length ?? 0}',
);
_initializeControllers(sduiModel.value!);
} else {
iLog('SDUI data is null after extraction');
}
} catch (e, stackTrace) {
eLog('Error parsing SDUI model: $e');
eLog('Stack trace: $stackTrace');
eLog('JSON data: ${result.data}');
}
} else {
iLog('SDUI result.data is null');
}
},
onError: (error, stackTrace) {
print(error);
eLog('Error fetching SDUI form: $error');
eLog('Stack trace: $stackTrace');
},
);
}
void onButtonPressed() {}
void _initializeControllers(SDUIWidgetModel model) {
// Extract all text form field keys from the model and create controllers
_extractTextFields(model);
}
void _extractTextFields(SDUIWidgetModel model) {
if (model.type == 'text_form_field' && model.data != null) {
final key = model.data!['key'] as String?;
final value = model.data!['value'] as String?;
if (key != null && !controllers.containsKey(key)) {
controllers[key] = TextEditingController(text: value ?? '');
}
}
if (model.child != null) {
_extractTextFields(SDUIWidgetModel.fromJson(model.child!));
}
if (model.children != null) {
for (var child in model.children!) {
_extractTextFields(SDUIWidgetModel.fromJson(child));
}
}
}
void onButtonPressed() {
// Example: Get all form values
controllers.forEach((key, controller) {
iLog('Field $key: ${controller.text}');
});
// Example: Get all chip selection values
formState.forEach((key, value) {
iLog('State $key: $value');
});
}
}

View File

@@ -1,7 +1,7 @@
import 'package:flutter/material.dart';
import 'package:rasadyar_chicken/presentation/utils/nested_keys_utils.dart';
import 'package:rasadyar_chicken/presentation/widget/base_page/view.dart';
import 'package:rasadyar_chicken/presentation/widget/sdui/widgets/text_form_filed/text_form_filed_sdui.dart';
import 'package:rasadyar_chicken/presentation/widget/sdui/form/sdui_form_widget.dart';
import 'package:rasadyar_core/core.dart';
import 'logic.dart';
@@ -19,17 +19,31 @@ class NewPage extends GetView<NewPageLogic> {
}
Widget contentWidget() {
return Center(
return SingleChildScrollView(
physics: BouncingScrollPhysics(),
padding: EdgeInsets.all(16.w),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
SizedBox(height: 24.h),
ObxValue((data) {
if (data.value == null) {
return const SizedBox.shrink();
return Center(child: CircularProgressIndicator());
}
return textFormFiledSDUI(model: data.value!);
}, controller.textFormFieldSDUIModel),
return Obx(
() => SDUIFormWidget(
model: data.value!,
controllers: controller.controllers,
state: controller.formState,
onStateChanged: (key, value) {
controller.formState[key] = value;
},
images: controller.images,
onImagesChanged: (key, imageList) {
controller.images[key] = imageList;
},
),
);
}, controller.sduiModel),
SizedBox(height: 24.h),
RElevated(
text: 'دکمه نمونه',
@@ -37,6 +51,7 @@ class NewPage extends GetView<NewPageLogic> {
controller.onButtonPressed();
},
),
SizedBox(height: 24.h),
],
),
);