feat: refactor NewPageLogic to utilize SDUIWidgetModel, enhance form handling with dynamic controllers, and implement SDUIFormWidget for rendering UI components
This commit is contained in:
@@ -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');
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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),
|
||||
],
|
||||
),
|
||||
);
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
{
|
||||
"type": "chip_selection",
|
||||
"visible": true,
|
||||
"data": {
|
||||
"key": "grain_quality",
|
||||
"label": "کیفیت دانه",
|
||||
"selectedIndex": -1,
|
||||
"options": [
|
||||
{
|
||||
"index": 0,
|
||||
"label": "خوب",
|
||||
"value": "خوب"
|
||||
},
|
||||
{
|
||||
"index": 1,
|
||||
"label": "متوسط",
|
||||
"value": "متوسط"
|
||||
},
|
||||
{
|
||||
"index": 2,
|
||||
"label": "ضعیف",
|
||||
"value": "ضعیف"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"type": "dropdown",
|
||||
"visible": true,
|
||||
"data": {
|
||||
"key": "training_status",
|
||||
"label": "آموزشدیده در حوزه بهداشت و امنیت زیستی",
|
||||
"placeholder": "آموزشدیده در حوزه بهداشت و امنیت زیستی",
|
||||
"items": [
|
||||
"بله",
|
||||
"خیر"
|
||||
],
|
||||
"selectedValue": null,
|
||||
"enabled": true
|
||||
}
|
||||
}
|
||||
157
packages/chicken/lib/presentation/widget/sdui/example_form.json
Normal file
157
packages/chicken/lib/presentation/widget/sdui/example_form.json
Normal file
@@ -0,0 +1,157 @@
|
||||
{
|
||||
"type": "column",
|
||||
"visible": true,
|
||||
"data": {
|
||||
"spacing": 10.0,
|
||||
"crossAxisAlignment": "start"
|
||||
},
|
||||
"children": [
|
||||
{
|
||||
"type": "card_label_item",
|
||||
"visible": true,
|
||||
"data": {
|
||||
"title": "اطلاعات پایه واحد",
|
||||
"padding_horizontal": 12.0,
|
||||
"padding_vertical": 11.0
|
||||
},
|
||||
"child": {
|
||||
"type": "column",
|
||||
"visible": true,
|
||||
"data": {
|
||||
"spacing": 10.0
|
||||
},
|
||||
"children": [
|
||||
{
|
||||
"type": "text_form_field",
|
||||
"visible": true,
|
||||
"data": {
|
||||
"key": "unit_name",
|
||||
"label": "نام واحد مرغداری",
|
||||
"keyboardType": "text",
|
||||
"enabled": true,
|
||||
"readonly": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "text_form_field",
|
||||
"visible": true,
|
||||
"data": {
|
||||
"key": "breeding_unique_id",
|
||||
"label": "کد یکتا / شناسه واحد",
|
||||
"keyboardType": "text",
|
||||
"enabled": true,
|
||||
"readonly": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "text_form_field",
|
||||
"visible": true,
|
||||
"data": {
|
||||
"key": "health_license",
|
||||
"label": "پروانه بهداشتی",
|
||||
"keyboardType": "text",
|
||||
"enabled": true,
|
||||
"readonly": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "text_form_field",
|
||||
"visible": true,
|
||||
"data": {
|
||||
"key": "total_capacity",
|
||||
"label": "ظرفیت اسمی سالنها",
|
||||
"keyboardType": "number",
|
||||
"enabled": true,
|
||||
"readonly": false,
|
||||
"commaSperator": true
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "sized_box",
|
||||
"visible": true,
|
||||
"data": {
|
||||
"height": 30.0
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "card_label_item",
|
||||
"visible": true,
|
||||
"data": {
|
||||
"title": "اطلاعات جوجه ریزی",
|
||||
"padding_horizontal": 12.0,
|
||||
"padding_vertical": 11.0
|
||||
},
|
||||
"child": {
|
||||
"type": "column",
|
||||
"visible": true,
|
||||
"data": {
|
||||
"spacing": 10.0
|
||||
},
|
||||
"children": [
|
||||
{
|
||||
"type": "text_form_field",
|
||||
"visible": true,
|
||||
"data": {
|
||||
"key": "hatching_date",
|
||||
"label": "تاریخ جوجه ریزی",
|
||||
"keyboardType": "text",
|
||||
"enabled": true,
|
||||
"readonly": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "text_form_field",
|
||||
"visible": true,
|
||||
"data": {
|
||||
"key": "visit_date",
|
||||
"label": "تاریخ بازدید",
|
||||
"keyboardType": "text",
|
||||
"enabled": true,
|
||||
"readonly": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "text_form_field",
|
||||
"visible": true,
|
||||
"data": {
|
||||
"key": "hatching_count",
|
||||
"label": "تعداد جوجهریزی اولیه",
|
||||
"keyboardType": "number",
|
||||
"enabled": true,
|
||||
"readonly": true,
|
||||
"commaSperator": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "text_form_field",
|
||||
"visible": true,
|
||||
"data": {
|
||||
"key": "hatching_breed",
|
||||
"label": "نوع نژاد",
|
||||
"keyboardType": "text",
|
||||
"enabled": true,
|
||||
"readonly": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "text_form_field",
|
||||
"visible": true,
|
||||
"data": {
|
||||
"key": "hatching_average_weight",
|
||||
"label": "میانگین وزن جوجه",
|
||||
"keyboardType": "number",
|
||||
"enabled": true,
|
||||
"readonly": false,
|
||||
"commaSperator": true,
|
||||
"decimal": true
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"type": "image_picker",
|
||||
"visible": true,
|
||||
"data": {
|
||||
"key": "hall_images",
|
||||
"label": "ثبت عکس سالن (حداقل ۳ زاویه)",
|
||||
"required": true,
|
||||
"maxImages": null
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||
|
||||
part 'sdui_widget_model.freezed.dart';
|
||||
part 'sdui_widget_model.g.dart';
|
||||
|
||||
@freezed
|
||||
abstract class SDUIWidgetModel with _$SDUIWidgetModel {
|
||||
const factory SDUIWidgetModel({
|
||||
String? type,
|
||||
bool? visible,
|
||||
Map<String, dynamic>? data,
|
||||
Map<String, dynamic>? child,
|
||||
List<Map<String, dynamic>>? children,
|
||||
}) = _SDUIWidgetModel;
|
||||
|
||||
factory SDUIWidgetModel.fromJson(Map<String, dynamic> json) =>
|
||||
_$SDUIWidgetModelFromJson(json);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,313 @@
|
||||
// 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 'sdui_widget_model.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// FreezedGenerator
|
||||
// **************************************************************************
|
||||
|
||||
// dart format off
|
||||
T _$identity<T>(T value) => value;
|
||||
|
||||
/// @nodoc
|
||||
mixin _$SDUIWidgetModel {
|
||||
|
||||
String? get type; bool? get visible; Map<String, dynamic>? get data; Map<String, dynamic>? get child; List<Map<String, dynamic>>? get children;
|
||||
/// Create a copy of SDUIWidgetModel
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@pragma('vm:prefer-inline')
|
||||
$SDUIWidgetModelCopyWith<SDUIWidgetModel> get copyWith => _$SDUIWidgetModelCopyWithImpl<SDUIWidgetModel>(this as SDUIWidgetModel, _$identity);
|
||||
|
||||
/// Serializes this SDUIWidgetModel to a JSON map.
|
||||
Map<String, dynamic> toJson();
|
||||
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is SDUIWidgetModel&&(identical(other.type, type) || other.type == type)&&(identical(other.visible, visible) || other.visible == visible)&&const DeepCollectionEquality().equals(other.data, data)&&const DeepCollectionEquality().equals(other.child, child)&&const DeepCollectionEquality().equals(other.children, children));
|
||||
}
|
||||
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType,type,visible,const DeepCollectionEquality().hash(data),const DeepCollectionEquality().hash(child),const DeepCollectionEquality().hash(children));
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'SDUIWidgetModel(type: $type, visible: $visible, data: $data, child: $child, children: $children)';
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract mixin class $SDUIWidgetModelCopyWith<$Res> {
|
||||
factory $SDUIWidgetModelCopyWith(SDUIWidgetModel value, $Res Function(SDUIWidgetModel) _then) = _$SDUIWidgetModelCopyWithImpl;
|
||||
@useResult
|
||||
$Res call({
|
||||
String? type, bool? visible, Map<String, dynamic>? data, Map<String, dynamic>? child, List<Map<String, dynamic>>? children
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
/// @nodoc
|
||||
class _$SDUIWidgetModelCopyWithImpl<$Res>
|
||||
implements $SDUIWidgetModelCopyWith<$Res> {
|
||||
_$SDUIWidgetModelCopyWithImpl(this._self, this._then);
|
||||
|
||||
final SDUIWidgetModel _self;
|
||||
final $Res Function(SDUIWidgetModel) _then;
|
||||
|
||||
/// Create a copy of SDUIWidgetModel
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@pragma('vm:prefer-inline') @override $Res call({Object? type = freezed,Object? visible = freezed,Object? data = freezed,Object? child = freezed,Object? children = freezed,}) {
|
||||
return _then(_self.copyWith(
|
||||
type: freezed == type ? _self.type : type // ignore: cast_nullable_to_non_nullable
|
||||
as String?,visible: freezed == visible ? _self.visible : visible // ignore: cast_nullable_to_non_nullable
|
||||
as bool?,data: freezed == data ? _self.data : data // ignore: cast_nullable_to_non_nullable
|
||||
as Map<String, dynamic>?,child: freezed == child ? _self.child : child // ignore: cast_nullable_to_non_nullable
|
||||
as Map<String, dynamic>?,children: freezed == children ? _self.children : children // ignore: cast_nullable_to_non_nullable
|
||||
as List<Map<String, dynamic>>?,
|
||||
));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/// Adds pattern-matching-related methods to [SDUIWidgetModel].
|
||||
extension SDUIWidgetModelPatterns on SDUIWidgetModel {
|
||||
/// 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( _SDUIWidgetModel value)? $default,{required TResult orElse(),}){
|
||||
final _that = this;
|
||||
switch (_that) {
|
||||
case _SDUIWidgetModel() 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( _SDUIWidgetModel value) $default,){
|
||||
final _that = this;
|
||||
switch (_that) {
|
||||
case _SDUIWidgetModel():
|
||||
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( _SDUIWidgetModel value)? $default,){
|
||||
final _that = this;
|
||||
switch (_that) {
|
||||
case _SDUIWidgetModel() 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? type, bool? visible, Map<String, dynamic>? data, Map<String, dynamic>? child, List<Map<String, dynamic>>? children)? $default,{required TResult orElse(),}) {final _that = this;
|
||||
switch (_that) {
|
||||
case _SDUIWidgetModel() when $default != null:
|
||||
return $default(_that.type,_that.visible,_that.data,_that.child,_that.children);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? type, bool? visible, Map<String, dynamic>? data, Map<String, dynamic>? child, List<Map<String, dynamic>>? children) $default,) {final _that = this;
|
||||
switch (_that) {
|
||||
case _SDUIWidgetModel():
|
||||
return $default(_that.type,_that.visible,_that.data,_that.child,_that.children);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? type, bool? visible, Map<String, dynamic>? data, Map<String, dynamic>? child, List<Map<String, dynamic>>? children)? $default,) {final _that = this;
|
||||
switch (_that) {
|
||||
case _SDUIWidgetModel() when $default != null:
|
||||
return $default(_that.type,_that.visible,_that.data,_that.child,_that.children);case _:
|
||||
return null;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
@JsonSerializable()
|
||||
|
||||
class _SDUIWidgetModel implements SDUIWidgetModel {
|
||||
const _SDUIWidgetModel({this.type, this.visible, final Map<String, dynamic>? data, final Map<String, dynamic>? child, final List<Map<String, dynamic>>? children}): _data = data,_child = child,_children = children;
|
||||
factory _SDUIWidgetModel.fromJson(Map<String, dynamic> json) => _$SDUIWidgetModelFromJson(json);
|
||||
|
||||
@override final String? type;
|
||||
@override final bool? visible;
|
||||
final Map<String, dynamic>? _data;
|
||||
@override Map<String, dynamic>? get data {
|
||||
final value = _data;
|
||||
if (value == null) return null;
|
||||
if (_data is EqualUnmodifiableMapView) return _data;
|
||||
// ignore: implicit_dynamic_type
|
||||
return EqualUnmodifiableMapView(value);
|
||||
}
|
||||
|
||||
final Map<String, dynamic>? _child;
|
||||
@override Map<String, dynamic>? get child {
|
||||
final value = _child;
|
||||
if (value == null) return null;
|
||||
if (_child is EqualUnmodifiableMapView) return _child;
|
||||
// ignore: implicit_dynamic_type
|
||||
return EqualUnmodifiableMapView(value);
|
||||
}
|
||||
|
||||
final List<Map<String, dynamic>>? _children;
|
||||
@override List<Map<String, dynamic>>? get children {
|
||||
final value = _children;
|
||||
if (value == null) return null;
|
||||
if (_children is EqualUnmodifiableListView) return _children;
|
||||
// ignore: implicit_dynamic_type
|
||||
return EqualUnmodifiableListView(value);
|
||||
}
|
||||
|
||||
|
||||
/// Create a copy of SDUIWidgetModel
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override @JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@pragma('vm:prefer-inline')
|
||||
_$SDUIWidgetModelCopyWith<_SDUIWidgetModel> get copyWith => __$SDUIWidgetModelCopyWithImpl<_SDUIWidgetModel>(this, _$identity);
|
||||
|
||||
@override
|
||||
Map<String, dynamic> toJson() {
|
||||
return _$SDUIWidgetModelToJson(this, );
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is _SDUIWidgetModel&&(identical(other.type, type) || other.type == type)&&(identical(other.visible, visible) || other.visible == visible)&&const DeepCollectionEquality().equals(other._data, _data)&&const DeepCollectionEquality().equals(other._child, _child)&&const DeepCollectionEquality().equals(other._children, _children));
|
||||
}
|
||||
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType,type,visible,const DeepCollectionEquality().hash(_data),const DeepCollectionEquality().hash(_child),const DeepCollectionEquality().hash(_children));
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'SDUIWidgetModel(type: $type, visible: $visible, data: $data, child: $child, children: $children)';
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract mixin class _$SDUIWidgetModelCopyWith<$Res> implements $SDUIWidgetModelCopyWith<$Res> {
|
||||
factory _$SDUIWidgetModelCopyWith(_SDUIWidgetModel value, $Res Function(_SDUIWidgetModel) _then) = __$SDUIWidgetModelCopyWithImpl;
|
||||
@override @useResult
|
||||
$Res call({
|
||||
String? type, bool? visible, Map<String, dynamic>? data, Map<String, dynamic>? child, List<Map<String, dynamic>>? children
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
/// @nodoc
|
||||
class __$SDUIWidgetModelCopyWithImpl<$Res>
|
||||
implements _$SDUIWidgetModelCopyWith<$Res> {
|
||||
__$SDUIWidgetModelCopyWithImpl(this._self, this._then);
|
||||
|
||||
final _SDUIWidgetModel _self;
|
||||
final $Res Function(_SDUIWidgetModel) _then;
|
||||
|
||||
/// Create a copy of SDUIWidgetModel
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override @pragma('vm:prefer-inline') $Res call({Object? type = freezed,Object? visible = freezed,Object? data = freezed,Object? child = freezed,Object? children = freezed,}) {
|
||||
return _then(_SDUIWidgetModel(
|
||||
type: freezed == type ? _self.type : type // ignore: cast_nullable_to_non_nullable
|
||||
as String?,visible: freezed == visible ? _self.visible : visible // ignore: cast_nullable_to_non_nullable
|
||||
as bool?,data: freezed == data ? _self._data : data // ignore: cast_nullable_to_non_nullable
|
||||
as Map<String, dynamic>?,child: freezed == child ? _self._child : child // ignore: cast_nullable_to_non_nullable
|
||||
as Map<String, dynamic>?,children: freezed == children ? _self._children : children // ignore: cast_nullable_to_non_nullable
|
||||
as List<Map<String, dynamic>>?,
|
||||
));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
// dart format on
|
||||
@@ -0,0 +1,27 @@
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'sdui_widget_model.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// JsonSerializableGenerator
|
||||
// **************************************************************************
|
||||
|
||||
_SDUIWidgetModel _$SDUIWidgetModelFromJson(Map<String, dynamic> json) =>
|
||||
_SDUIWidgetModel(
|
||||
type: json['type'] as String?,
|
||||
visible: json['visible'] as bool?,
|
||||
data: json['data'] as Map<String, dynamic>?,
|
||||
child: json['child'] as Map<String, dynamic>?,
|
||||
children: (json['children'] as List<dynamic>?)
|
||||
?.map((e) => e as Map<String, dynamic>)
|
||||
.toList(),
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$SDUIWidgetModelToJson(_SDUIWidgetModel instance) =>
|
||||
<String, dynamic>{
|
||||
'type': instance.type,
|
||||
'visible': instance.visible,
|
||||
'data': instance.data,
|
||||
'child': instance.child,
|
||||
'children': instance.children,
|
||||
};
|
||||
8
packages/chicken/lib/presentation/widget/sdui/sdui.dart
Normal file
8
packages/chicken/lib/presentation/widget/sdui/sdui.dart
Normal file
@@ -0,0 +1,8 @@
|
||||
// SDUI Export file
|
||||
export 'form/sdui_form_widget.dart';
|
||||
export 'model/sdui_widget_model.dart';
|
||||
export 'widgets/card_label_item/card_label_item_sdui.dart';
|
||||
export 'widgets/card_label_item/model/card_label_item_sdui_model.dart';
|
||||
export 'widgets/text_form_filed/text_form_filed_sdui.dart';
|
||||
export 'widgets/text_form_filed/model/text_form_field_sdui_model.dart';
|
||||
|
||||
@@ -0,0 +1,79 @@
|
||||
{
|
||||
"info": {
|
||||
"type": "column",
|
||||
"visible": true,
|
||||
"data": {
|
||||
"spacing": 10.0,
|
||||
"crossAxisAlignment": "start"
|
||||
},
|
||||
"children": [
|
||||
{
|
||||
"type": "card_label_item",
|
||||
"visible": true,
|
||||
"data": {
|
||||
"title": "اطلاعات پایه واحد",
|
||||
"padding_horizontal": 12.0,
|
||||
"padding_vertical": 11.0
|
||||
},
|
||||
"child": {
|
||||
"type": "column",
|
||||
"visible": true,
|
||||
"data": {
|
||||
"spacing": 10.0
|
||||
},
|
||||
"children": [
|
||||
{
|
||||
"type": "text_form_field",
|
||||
"visible": true,
|
||||
"data": {
|
||||
"key": "unit_name",
|
||||
"label": "نام واحد مرغداری",
|
||||
"keyboard_type": "text"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "text_form_field",
|
||||
"visible": true,
|
||||
"data": {
|
||||
"key": "breeding_unique_id",
|
||||
"label": "(عدد معمولی)کد یکتا / شناسه واحد",
|
||||
"keyboard_type": "number"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "text_form_field",
|
||||
"visible": true,
|
||||
"data": {
|
||||
"key": "health_a",
|
||||
"label": "(سه تایی جداشه)پروانه بهداشتی",
|
||||
"keyboard_type": "number",
|
||||
"comma_sperator": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "text_form_field",
|
||||
"visible": true,
|
||||
"data": {
|
||||
"key": "health_license",
|
||||
"label": "عدد اعشاری ",
|
||||
"keyboard_type": "number",
|
||||
"decimal": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "text_form_field",
|
||||
"visible": true,
|
||||
"data": {
|
||||
"key": "health_q",
|
||||
"label": "عدد اعشاری با 2 رقم اعشار",
|
||||
"keyboard_type": "number",
|
||||
"decimal": true,
|
||||
"decimal_places": 2
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
{
|
||||
"id": 1,
|
||||
"key": "simple-test-form",
|
||||
"create_date": "2025-01-15T10:00:00.000000",
|
||||
"modify_date": "2025-01-15T10:00:00.000000",
|
||||
"trash": false,
|
||||
"info": {
|
||||
"data": {
|
||||
"type": "column",
|
||||
"visible": true,
|
||||
"data": {
|
||||
"spacing": 20.0,
|
||||
"crossAxisAlignment": "start"
|
||||
},
|
||||
"children": [
|
||||
{
|
||||
"type": "card_label_item",
|
||||
"visible": true,
|
||||
"data": {
|
||||
"title": "فرم تست",
|
||||
"padding_horizontal": 12.0,
|
||||
"padding_vertical": 11.0
|
||||
},
|
||||
"child": {
|
||||
"type": "column",
|
||||
"visible": true,
|
||||
"data": {
|
||||
"spacing": 10.0
|
||||
},
|
||||
"children": [
|
||||
{
|
||||
"type": "text_form_field",
|
||||
"visible": true,
|
||||
"data": {
|
||||
"key": "name",
|
||||
"label": "نام",
|
||||
"keyboardType": "text",
|
||||
"enabled": true,
|
||||
"readonly": false,
|
||||
"value": ""
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "text_form_field",
|
||||
"visible": true,
|
||||
"data": {
|
||||
"key": "phone",
|
||||
"label": "شماره تماس",
|
||||
"keyboardType": "text",
|
||||
"enabled": true,
|
||||
"readonly": false,
|
||||
"value": ""
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "text_form_field",
|
||||
"visible": true,
|
||||
"data": {
|
||||
"key": "age",
|
||||
"label": "سن",
|
||||
"keyboardType": "number",
|
||||
"enabled": true,
|
||||
"readonly": false,
|
||||
"commaSperator": true,
|
||||
"value": ""
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"created_by": null,
|
||||
"modified_by": null
|
||||
}
|
||||
|
||||
@@ -3,18 +3,10 @@ import 'package:rasadyar_core/core.dart';
|
||||
import 'model/card_label_item_sdui_model.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
Widget cardLabelItemSDUI({required CardLabelItemSDUI model}) {
|
||||
Widget cardLabelItemSDUI({required CardLabelItemSDUI model, Widget? child}) {
|
||||
return farmInfoWidget(
|
||||
title: model.data?.title ?? '',
|
||||
child: Container(),
|
||||
padding:
|
||||
model.data?.paddingHorizontal != null &&
|
||||
model.data?.paddingVertical != null
|
||||
? EdgeInsets.symmetric(
|
||||
horizontal: model.data?.paddingHorizontal ?? 0,
|
||||
vertical: model.data?.paddingVertical ?? 0,
|
||||
)
|
||||
: null,
|
||||
child: child ?? Container(),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -26,17 +18,19 @@ Widget farmInfoWidget({
|
||||
return Stack(
|
||||
clipBehavior: Clip.none,
|
||||
children: [
|
||||
Positioned.fill(
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
border: Border.all(width: 0.50, color: AppColor.mediumGrey),
|
||||
),
|
||||
|
||||
padding:
|
||||
padding ?? EdgeInsets.symmetric(horizontal: 12.w, vertical: 11.h),
|
||||
child: child,
|
||||
Container(
|
||||
width: double.infinity,
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
border: Border.all(width: 0.50, color: AppColor.mediumGrey),
|
||||
),
|
||||
padding: EdgeInsets.symmetric(horizontal: 12.w, vertical: 11.h),
|
||||
child: Column(
|
||||
children: [
|
||||
SizedBox(height: 8.h),
|
||||
child,
|
||||
],
|
||||
),
|
||||
),
|
||||
Positioned(
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:rasadyar_chicken/features/poultry_science/presentation/widgets/submit_inspection_bottom_sheet/step2_page.dart';
|
||||
import 'package:rasadyar_chicken/presentation/widget/sdui/widgets/chip_selection/model/chip_selection_sdui_model.dart';
|
||||
import 'package:rasadyar_core/core.dart';
|
||||
|
||||
class ChipSelectionSDUI extends StatelessWidget {
|
||||
final ChipSelectionSDUIModel model;
|
||||
final RxMap<String, dynamic>? state;
|
||||
final Function(String key, int index, String? value)? onChanged;
|
||||
|
||||
const ChipSelectionSDUI({
|
||||
super.key,
|
||||
required this.model,
|
||||
this.state,
|
||||
this.onChanged,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final options = model.options ?? [];
|
||||
final spacing = 10.0;
|
||||
|
||||
if (options.isEmpty) {
|
||||
return const SizedBox.shrink();
|
||||
}
|
||||
|
||||
return Obx(() {
|
||||
final selectedIndex =
|
||||
state?[model.key] as int? ?? model.selectedIndex ?? -1;
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
if (model.label != null && model.label!.isNotEmpty) ...[
|
||||
Text(
|
||||
model.label!,
|
||||
style: AppFonts.yekan14Bold.copyWith(color: AppColor.textColor2),
|
||||
),
|
||||
SizedBox(height: 9.h),
|
||||
],
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
spacing: spacing,
|
||||
children: options.asMap().entries.map((entry) {
|
||||
final option = entry.value;
|
||||
final optionIndex = option.index ?? entry.key;
|
||||
return Expanded(
|
||||
child: containerChips(
|
||||
selectedIndex: selectedIndex,
|
||||
index: optionIndex,
|
||||
label: option.label ?? '',
|
||||
onTap: (index) {
|
||||
if (onChanged != null && model.key != null) {
|
||||
onChanged!(model.key!, index, option.value);
|
||||
}
|
||||
},
|
||||
),
|
||||
);
|
||||
}).toList(),
|
||||
),
|
||||
],
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||
|
||||
part 'chip_selection_sdui_model.freezed.dart';
|
||||
part 'chip_selection_sdui_model.g.dart';
|
||||
|
||||
@freezed
|
||||
abstract class ChipSelectionSDUIModel with _$ChipSelectionSDUIModel {
|
||||
const factory ChipSelectionSDUIModel({
|
||||
String? key,
|
||||
String? label,
|
||||
List<ChipOption>? options,
|
||||
int? selectedIndex,
|
||||
}) = _ChipSelectionSDUIModel;
|
||||
|
||||
factory ChipSelectionSDUIModel.fromJson(Map<String, dynamic> json) =>
|
||||
_$ChipSelectionSDUIModelFromJson(json);
|
||||
}
|
||||
|
||||
@freezed
|
||||
abstract class ChipOption with _$ChipOption {
|
||||
const factory ChipOption({
|
||||
int? index,
|
||||
String? label,
|
||||
String? value,
|
||||
}) = _ChipOption;
|
||||
|
||||
factory ChipOption.fromJson(Map<String, dynamic> json) =>
|
||||
_$ChipOptionFromJson(json);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,563 @@
|
||||
// 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 'chip_selection_sdui_model.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// FreezedGenerator
|
||||
// **************************************************************************
|
||||
|
||||
// dart format off
|
||||
T _$identity<T>(T value) => value;
|
||||
|
||||
/// @nodoc
|
||||
mixin _$ChipSelectionSDUIModel {
|
||||
|
||||
String? get key; String? get label; List<ChipOption>? get options; int? get selectedIndex;
|
||||
/// Create a copy of ChipSelectionSDUIModel
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@pragma('vm:prefer-inline')
|
||||
$ChipSelectionSDUIModelCopyWith<ChipSelectionSDUIModel> get copyWith => _$ChipSelectionSDUIModelCopyWithImpl<ChipSelectionSDUIModel>(this as ChipSelectionSDUIModel, _$identity);
|
||||
|
||||
/// Serializes this ChipSelectionSDUIModel to a JSON map.
|
||||
Map<String, dynamic> toJson();
|
||||
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is ChipSelectionSDUIModel&&(identical(other.key, key) || other.key == key)&&(identical(other.label, label) || other.label == label)&&const DeepCollectionEquality().equals(other.options, options)&&(identical(other.selectedIndex, selectedIndex) || other.selectedIndex == selectedIndex));
|
||||
}
|
||||
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType,key,label,const DeepCollectionEquality().hash(options),selectedIndex);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'ChipSelectionSDUIModel(key: $key, label: $label, options: $options, selectedIndex: $selectedIndex)';
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract mixin class $ChipSelectionSDUIModelCopyWith<$Res> {
|
||||
factory $ChipSelectionSDUIModelCopyWith(ChipSelectionSDUIModel value, $Res Function(ChipSelectionSDUIModel) _then) = _$ChipSelectionSDUIModelCopyWithImpl;
|
||||
@useResult
|
||||
$Res call({
|
||||
String? key, String? label, List<ChipOption>? options, int? selectedIndex
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
/// @nodoc
|
||||
class _$ChipSelectionSDUIModelCopyWithImpl<$Res>
|
||||
implements $ChipSelectionSDUIModelCopyWith<$Res> {
|
||||
_$ChipSelectionSDUIModelCopyWithImpl(this._self, this._then);
|
||||
|
||||
final ChipSelectionSDUIModel _self;
|
||||
final $Res Function(ChipSelectionSDUIModel) _then;
|
||||
|
||||
/// Create a copy of ChipSelectionSDUIModel
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@pragma('vm:prefer-inline') @override $Res call({Object? key = freezed,Object? label = freezed,Object? options = freezed,Object? selectedIndex = freezed,}) {
|
||||
return _then(_self.copyWith(
|
||||
key: freezed == key ? _self.key : key // ignore: cast_nullable_to_non_nullable
|
||||
as String?,label: freezed == label ? _self.label : label // ignore: cast_nullable_to_non_nullable
|
||||
as String?,options: freezed == options ? _self.options : options // ignore: cast_nullable_to_non_nullable
|
||||
as List<ChipOption>?,selectedIndex: freezed == selectedIndex ? _self.selectedIndex : selectedIndex // ignore: cast_nullable_to_non_nullable
|
||||
as int?,
|
||||
));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/// Adds pattern-matching-related methods to [ChipSelectionSDUIModel].
|
||||
extension ChipSelectionSDUIModelPatterns on ChipSelectionSDUIModel {
|
||||
/// 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( _ChipSelectionSDUIModel value)? $default,{required TResult orElse(),}){
|
||||
final _that = this;
|
||||
switch (_that) {
|
||||
case _ChipSelectionSDUIModel() 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( _ChipSelectionSDUIModel value) $default,){
|
||||
final _that = this;
|
||||
switch (_that) {
|
||||
case _ChipSelectionSDUIModel():
|
||||
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( _ChipSelectionSDUIModel value)? $default,){
|
||||
final _that = this;
|
||||
switch (_that) {
|
||||
case _ChipSelectionSDUIModel() 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, String? label, List<ChipOption>? options, int? selectedIndex)? $default,{required TResult orElse(),}) {final _that = this;
|
||||
switch (_that) {
|
||||
case _ChipSelectionSDUIModel() when $default != null:
|
||||
return $default(_that.key,_that.label,_that.options,_that.selectedIndex);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, String? label, List<ChipOption>? options, int? selectedIndex) $default,) {final _that = this;
|
||||
switch (_that) {
|
||||
case _ChipSelectionSDUIModel():
|
||||
return $default(_that.key,_that.label,_that.options,_that.selectedIndex);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, String? label, List<ChipOption>? options, int? selectedIndex)? $default,) {final _that = this;
|
||||
switch (_that) {
|
||||
case _ChipSelectionSDUIModel() when $default != null:
|
||||
return $default(_that.key,_that.label,_that.options,_that.selectedIndex);case _:
|
||||
return null;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
@JsonSerializable()
|
||||
|
||||
class _ChipSelectionSDUIModel implements ChipSelectionSDUIModel {
|
||||
const _ChipSelectionSDUIModel({this.key, this.label, final List<ChipOption>? options, this.selectedIndex}): _options = options;
|
||||
factory _ChipSelectionSDUIModel.fromJson(Map<String, dynamic> json) => _$ChipSelectionSDUIModelFromJson(json);
|
||||
|
||||
@override final String? key;
|
||||
@override final String? label;
|
||||
final List<ChipOption>? _options;
|
||||
@override List<ChipOption>? get options {
|
||||
final value = _options;
|
||||
if (value == null) return null;
|
||||
if (_options is EqualUnmodifiableListView) return _options;
|
||||
// ignore: implicit_dynamic_type
|
||||
return EqualUnmodifiableListView(value);
|
||||
}
|
||||
|
||||
@override final int? selectedIndex;
|
||||
|
||||
/// Create a copy of ChipSelectionSDUIModel
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override @JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@pragma('vm:prefer-inline')
|
||||
_$ChipSelectionSDUIModelCopyWith<_ChipSelectionSDUIModel> get copyWith => __$ChipSelectionSDUIModelCopyWithImpl<_ChipSelectionSDUIModel>(this, _$identity);
|
||||
|
||||
@override
|
||||
Map<String, dynamic> toJson() {
|
||||
return _$ChipSelectionSDUIModelToJson(this, );
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is _ChipSelectionSDUIModel&&(identical(other.key, key) || other.key == key)&&(identical(other.label, label) || other.label == label)&&const DeepCollectionEquality().equals(other._options, _options)&&(identical(other.selectedIndex, selectedIndex) || other.selectedIndex == selectedIndex));
|
||||
}
|
||||
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType,key,label,const DeepCollectionEquality().hash(_options),selectedIndex);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'ChipSelectionSDUIModel(key: $key, label: $label, options: $options, selectedIndex: $selectedIndex)';
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract mixin class _$ChipSelectionSDUIModelCopyWith<$Res> implements $ChipSelectionSDUIModelCopyWith<$Res> {
|
||||
factory _$ChipSelectionSDUIModelCopyWith(_ChipSelectionSDUIModel value, $Res Function(_ChipSelectionSDUIModel) _then) = __$ChipSelectionSDUIModelCopyWithImpl;
|
||||
@override @useResult
|
||||
$Res call({
|
||||
String? key, String? label, List<ChipOption>? options, int? selectedIndex
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
/// @nodoc
|
||||
class __$ChipSelectionSDUIModelCopyWithImpl<$Res>
|
||||
implements _$ChipSelectionSDUIModelCopyWith<$Res> {
|
||||
__$ChipSelectionSDUIModelCopyWithImpl(this._self, this._then);
|
||||
|
||||
final _ChipSelectionSDUIModel _self;
|
||||
final $Res Function(_ChipSelectionSDUIModel) _then;
|
||||
|
||||
/// Create a copy of ChipSelectionSDUIModel
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override @pragma('vm:prefer-inline') $Res call({Object? key = freezed,Object? label = freezed,Object? options = freezed,Object? selectedIndex = freezed,}) {
|
||||
return _then(_ChipSelectionSDUIModel(
|
||||
key: freezed == key ? _self.key : key // ignore: cast_nullable_to_non_nullable
|
||||
as String?,label: freezed == label ? _self.label : label // ignore: cast_nullable_to_non_nullable
|
||||
as String?,options: freezed == options ? _self._options : options // ignore: cast_nullable_to_non_nullable
|
||||
as List<ChipOption>?,selectedIndex: freezed == selectedIndex ? _self.selectedIndex : selectedIndex // ignore: cast_nullable_to_non_nullable
|
||||
as int?,
|
||||
));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
/// @nodoc
|
||||
mixin _$ChipOption {
|
||||
|
||||
int? get index; String? get label; String? get value;
|
||||
/// Create a copy of ChipOption
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@pragma('vm:prefer-inline')
|
||||
$ChipOptionCopyWith<ChipOption> get copyWith => _$ChipOptionCopyWithImpl<ChipOption>(this as ChipOption, _$identity);
|
||||
|
||||
/// Serializes this ChipOption to a JSON map.
|
||||
Map<String, dynamic> toJson();
|
||||
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is ChipOption&&(identical(other.index, index) || other.index == index)&&(identical(other.label, label) || other.label == label)&&(identical(other.value, value) || other.value == value));
|
||||
}
|
||||
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType,index,label,value);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'ChipOption(index: $index, label: $label, value: $value)';
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract mixin class $ChipOptionCopyWith<$Res> {
|
||||
factory $ChipOptionCopyWith(ChipOption value, $Res Function(ChipOption) _then) = _$ChipOptionCopyWithImpl;
|
||||
@useResult
|
||||
$Res call({
|
||||
int? index, String? label, String? value
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
/// @nodoc
|
||||
class _$ChipOptionCopyWithImpl<$Res>
|
||||
implements $ChipOptionCopyWith<$Res> {
|
||||
_$ChipOptionCopyWithImpl(this._self, this._then);
|
||||
|
||||
final ChipOption _self;
|
||||
final $Res Function(ChipOption) _then;
|
||||
|
||||
/// Create a copy of ChipOption
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@pragma('vm:prefer-inline') @override $Res call({Object? index = freezed,Object? label = freezed,Object? value = freezed,}) {
|
||||
return _then(_self.copyWith(
|
||||
index: freezed == index ? _self.index : index // ignore: cast_nullable_to_non_nullable
|
||||
as int?,label: freezed == label ? _self.label : label // ignore: cast_nullable_to_non_nullable
|
||||
as String?,value: freezed == value ? _self.value : value // ignore: cast_nullable_to_non_nullable
|
||||
as String?,
|
||||
));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/// Adds pattern-matching-related methods to [ChipOption].
|
||||
extension ChipOptionPatterns on ChipOption {
|
||||
/// 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( _ChipOption value)? $default,{required TResult orElse(),}){
|
||||
final _that = this;
|
||||
switch (_that) {
|
||||
case _ChipOption() 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( _ChipOption value) $default,){
|
||||
final _that = this;
|
||||
switch (_that) {
|
||||
case _ChipOption():
|
||||
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( _ChipOption value)? $default,){
|
||||
final _that = this;
|
||||
switch (_that) {
|
||||
case _ChipOption() 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( int? index, String? label, String? value)? $default,{required TResult orElse(),}) {final _that = this;
|
||||
switch (_that) {
|
||||
case _ChipOption() when $default != null:
|
||||
return $default(_that.index,_that.label,_that.value);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( int? index, String? label, String? value) $default,) {final _that = this;
|
||||
switch (_that) {
|
||||
case _ChipOption():
|
||||
return $default(_that.index,_that.label,_that.value);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( int? index, String? label, String? value)? $default,) {final _that = this;
|
||||
switch (_that) {
|
||||
case _ChipOption() when $default != null:
|
||||
return $default(_that.index,_that.label,_that.value);case _:
|
||||
return null;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
@JsonSerializable()
|
||||
|
||||
class _ChipOption implements ChipOption {
|
||||
const _ChipOption({this.index, this.label, this.value});
|
||||
factory _ChipOption.fromJson(Map<String, dynamic> json) => _$ChipOptionFromJson(json);
|
||||
|
||||
@override final int? index;
|
||||
@override final String? label;
|
||||
@override final String? value;
|
||||
|
||||
/// Create a copy of ChipOption
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override @JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@pragma('vm:prefer-inline')
|
||||
_$ChipOptionCopyWith<_ChipOption> get copyWith => __$ChipOptionCopyWithImpl<_ChipOption>(this, _$identity);
|
||||
|
||||
@override
|
||||
Map<String, dynamic> toJson() {
|
||||
return _$ChipOptionToJson(this, );
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is _ChipOption&&(identical(other.index, index) || other.index == index)&&(identical(other.label, label) || other.label == label)&&(identical(other.value, value) || other.value == value));
|
||||
}
|
||||
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType,index,label,value);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'ChipOption(index: $index, label: $label, value: $value)';
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract mixin class _$ChipOptionCopyWith<$Res> implements $ChipOptionCopyWith<$Res> {
|
||||
factory _$ChipOptionCopyWith(_ChipOption value, $Res Function(_ChipOption) _then) = __$ChipOptionCopyWithImpl;
|
||||
@override @useResult
|
||||
$Res call({
|
||||
int? index, String? label, String? value
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
/// @nodoc
|
||||
class __$ChipOptionCopyWithImpl<$Res>
|
||||
implements _$ChipOptionCopyWith<$Res> {
|
||||
__$ChipOptionCopyWithImpl(this._self, this._then);
|
||||
|
||||
final _ChipOption _self;
|
||||
final $Res Function(_ChipOption) _then;
|
||||
|
||||
/// Create a copy of ChipOption
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override @pragma('vm:prefer-inline') $Res call({Object? index = freezed,Object? label = freezed,Object? value = freezed,}) {
|
||||
return _then(_ChipOption(
|
||||
index: freezed == index ? _self.index : index // ignore: cast_nullable_to_non_nullable
|
||||
as int?,label: freezed == label ? _self.label : label // ignore: cast_nullable_to_non_nullable
|
||||
as String?,value: freezed == value ? _self.value : value // ignore: cast_nullable_to_non_nullable
|
||||
as String?,
|
||||
));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
// dart format on
|
||||
@@ -0,0 +1,40 @@
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'chip_selection_sdui_model.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// JsonSerializableGenerator
|
||||
// **************************************************************************
|
||||
|
||||
_ChipSelectionSDUIModel _$ChipSelectionSDUIModelFromJson(
|
||||
Map<String, dynamic> json,
|
||||
) => _ChipSelectionSDUIModel(
|
||||
key: json['key'] as String?,
|
||||
label: json['label'] as String?,
|
||||
options: (json['options'] as List<dynamic>?)
|
||||
?.map((e) => ChipOption.fromJson(e as Map<String, dynamic>))
|
||||
.toList(),
|
||||
selectedIndex: (json['selected_index'] as num?)?.toInt(),
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$ChipSelectionSDUIModelToJson(
|
||||
_ChipSelectionSDUIModel instance,
|
||||
) => <String, dynamic>{
|
||||
'key': instance.key,
|
||||
'label': instance.label,
|
||||
'options': instance.options,
|
||||
'selected_index': instance.selectedIndex,
|
||||
};
|
||||
|
||||
_ChipOption _$ChipOptionFromJson(Map<String, dynamic> json) => _ChipOption(
|
||||
index: (json['index'] as num?)?.toInt(),
|
||||
label: json['label'] as String?,
|
||||
value: json['value'] as String?,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$ChipOptionToJson(_ChipOption instance) =>
|
||||
<String, dynamic>{
|
||||
'index': instance.index,
|
||||
'label': instance.label,
|
||||
'value': instance.value,
|
||||
};
|
||||
@@ -0,0 +1,43 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:rasadyar_chicken/presentation/widget/sdui/widgets/dropdown/model/dropdown_sdui_model.dart';
|
||||
import 'package:rasadyar_core/core.dart';
|
||||
|
||||
class DropdownSDUI extends StatelessWidget {
|
||||
final DropdownSDUIModel model;
|
||||
final RxMap<String, dynamic>? state;
|
||||
final Function(String key, String value)? onChanged;
|
||||
|
||||
const DropdownSDUI({
|
||||
super.key,
|
||||
required this.model,
|
||||
this.state,
|
||||
this.onChanged,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final items = model.items ?? [];
|
||||
|
||||
if (items.isEmpty) {
|
||||
return const SizedBox.shrink();
|
||||
}
|
||||
|
||||
return Obx(() {
|
||||
final selectedValue = state?[model.key] as String? ?? model.selectedValue;
|
||||
|
||||
return ResourceOverlayDropdown<String>(
|
||||
items: Resource.success(items),
|
||||
selectedItem: selectedValue,
|
||||
onChanged: (item) {
|
||||
if (onChanged != null && model.key != null) {
|
||||
onChanged!(model.key!, item);
|
||||
}
|
||||
},
|
||||
itemBuilder: (item) => Text(item),
|
||||
labelBuilder: (selected) =>
|
||||
Text(selected ?? (model.placeholder ?? model.label ?? '')),
|
||||
isDisabled: model.enabled == false,
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||
|
||||
part 'dropdown_sdui_model.freezed.dart';
|
||||
part 'dropdown_sdui_model.g.dart';
|
||||
|
||||
@freezed
|
||||
abstract class DropdownSDUIModel with _$DropdownSDUIModel {
|
||||
const factory DropdownSDUIModel({
|
||||
String? key,
|
||||
String? label,
|
||||
String? placeholder,
|
||||
List<String>? items,
|
||||
String? selectedValue,
|
||||
bool? enabled,
|
||||
}) = _DropdownSDUIModel;
|
||||
|
||||
factory DropdownSDUIModel.fromJson(Map<String, dynamic> json) =>
|
||||
_$DropdownSDUIModelFromJson(json);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,300 @@
|
||||
// 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 'dropdown_sdui_model.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// FreezedGenerator
|
||||
// **************************************************************************
|
||||
|
||||
// dart format off
|
||||
T _$identity<T>(T value) => value;
|
||||
|
||||
/// @nodoc
|
||||
mixin _$DropdownSDUIModel {
|
||||
|
||||
String? get key; String? get label; String? get placeholder; List<String>? get items; String? get selectedValue; bool? get enabled;
|
||||
/// Create a copy of DropdownSDUIModel
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@pragma('vm:prefer-inline')
|
||||
$DropdownSDUIModelCopyWith<DropdownSDUIModel> get copyWith => _$DropdownSDUIModelCopyWithImpl<DropdownSDUIModel>(this as DropdownSDUIModel, _$identity);
|
||||
|
||||
/// Serializes this DropdownSDUIModel to a JSON map.
|
||||
Map<String, dynamic> toJson();
|
||||
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is DropdownSDUIModel&&(identical(other.key, key) || other.key == key)&&(identical(other.label, label) || other.label == label)&&(identical(other.placeholder, placeholder) || other.placeholder == placeholder)&&const DeepCollectionEquality().equals(other.items, items)&&(identical(other.selectedValue, selectedValue) || other.selectedValue == selectedValue)&&(identical(other.enabled, enabled) || other.enabled == enabled));
|
||||
}
|
||||
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType,key,label,placeholder,const DeepCollectionEquality().hash(items),selectedValue,enabled);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'DropdownSDUIModel(key: $key, label: $label, placeholder: $placeholder, items: $items, selectedValue: $selectedValue, enabled: $enabled)';
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract mixin class $DropdownSDUIModelCopyWith<$Res> {
|
||||
factory $DropdownSDUIModelCopyWith(DropdownSDUIModel value, $Res Function(DropdownSDUIModel) _then) = _$DropdownSDUIModelCopyWithImpl;
|
||||
@useResult
|
||||
$Res call({
|
||||
String? key, String? label, String? placeholder, List<String>? items, String? selectedValue, bool? enabled
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
/// @nodoc
|
||||
class _$DropdownSDUIModelCopyWithImpl<$Res>
|
||||
implements $DropdownSDUIModelCopyWith<$Res> {
|
||||
_$DropdownSDUIModelCopyWithImpl(this._self, this._then);
|
||||
|
||||
final DropdownSDUIModel _self;
|
||||
final $Res Function(DropdownSDUIModel) _then;
|
||||
|
||||
/// Create a copy of DropdownSDUIModel
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@pragma('vm:prefer-inline') @override $Res call({Object? key = freezed,Object? label = freezed,Object? placeholder = freezed,Object? items = freezed,Object? selectedValue = freezed,Object? enabled = freezed,}) {
|
||||
return _then(_self.copyWith(
|
||||
key: freezed == key ? _self.key : key // ignore: cast_nullable_to_non_nullable
|
||||
as String?,label: freezed == label ? _self.label : label // ignore: cast_nullable_to_non_nullable
|
||||
as String?,placeholder: freezed == placeholder ? _self.placeholder : placeholder // ignore: cast_nullable_to_non_nullable
|
||||
as String?,items: freezed == items ? _self.items : items // ignore: cast_nullable_to_non_nullable
|
||||
as List<String>?,selectedValue: freezed == selectedValue ? _self.selectedValue : selectedValue // ignore: cast_nullable_to_non_nullable
|
||||
as String?,enabled: freezed == enabled ? _self.enabled : enabled // ignore: cast_nullable_to_non_nullable
|
||||
as bool?,
|
||||
));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/// Adds pattern-matching-related methods to [DropdownSDUIModel].
|
||||
extension DropdownSDUIModelPatterns on DropdownSDUIModel {
|
||||
/// 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( _DropdownSDUIModel value)? $default,{required TResult orElse(),}){
|
||||
final _that = this;
|
||||
switch (_that) {
|
||||
case _DropdownSDUIModel() 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( _DropdownSDUIModel value) $default,){
|
||||
final _that = this;
|
||||
switch (_that) {
|
||||
case _DropdownSDUIModel():
|
||||
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( _DropdownSDUIModel value)? $default,){
|
||||
final _that = this;
|
||||
switch (_that) {
|
||||
case _DropdownSDUIModel() 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, String? label, String? placeholder, List<String>? items, String? selectedValue, bool? enabled)? $default,{required TResult orElse(),}) {final _that = this;
|
||||
switch (_that) {
|
||||
case _DropdownSDUIModel() when $default != null:
|
||||
return $default(_that.key,_that.label,_that.placeholder,_that.items,_that.selectedValue,_that.enabled);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, String? label, String? placeholder, List<String>? items, String? selectedValue, bool? enabled) $default,) {final _that = this;
|
||||
switch (_that) {
|
||||
case _DropdownSDUIModel():
|
||||
return $default(_that.key,_that.label,_that.placeholder,_that.items,_that.selectedValue,_that.enabled);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, String? label, String? placeholder, List<String>? items, String? selectedValue, bool? enabled)? $default,) {final _that = this;
|
||||
switch (_that) {
|
||||
case _DropdownSDUIModel() when $default != null:
|
||||
return $default(_that.key,_that.label,_that.placeholder,_that.items,_that.selectedValue,_that.enabled);case _:
|
||||
return null;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
@JsonSerializable()
|
||||
|
||||
class _DropdownSDUIModel implements DropdownSDUIModel {
|
||||
const _DropdownSDUIModel({this.key, this.label, this.placeholder, final List<String>? items, this.selectedValue, this.enabled}): _items = items;
|
||||
factory _DropdownSDUIModel.fromJson(Map<String, dynamic> json) => _$DropdownSDUIModelFromJson(json);
|
||||
|
||||
@override final String? key;
|
||||
@override final String? label;
|
||||
@override final String? placeholder;
|
||||
final List<String>? _items;
|
||||
@override List<String>? get items {
|
||||
final value = _items;
|
||||
if (value == null) return null;
|
||||
if (_items is EqualUnmodifiableListView) return _items;
|
||||
// ignore: implicit_dynamic_type
|
||||
return EqualUnmodifiableListView(value);
|
||||
}
|
||||
|
||||
@override final String? selectedValue;
|
||||
@override final bool? enabled;
|
||||
|
||||
/// Create a copy of DropdownSDUIModel
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override @JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@pragma('vm:prefer-inline')
|
||||
_$DropdownSDUIModelCopyWith<_DropdownSDUIModel> get copyWith => __$DropdownSDUIModelCopyWithImpl<_DropdownSDUIModel>(this, _$identity);
|
||||
|
||||
@override
|
||||
Map<String, dynamic> toJson() {
|
||||
return _$DropdownSDUIModelToJson(this, );
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is _DropdownSDUIModel&&(identical(other.key, key) || other.key == key)&&(identical(other.label, label) || other.label == label)&&(identical(other.placeholder, placeholder) || other.placeholder == placeholder)&&const DeepCollectionEquality().equals(other._items, _items)&&(identical(other.selectedValue, selectedValue) || other.selectedValue == selectedValue)&&(identical(other.enabled, enabled) || other.enabled == enabled));
|
||||
}
|
||||
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType,key,label,placeholder,const DeepCollectionEquality().hash(_items),selectedValue,enabled);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'DropdownSDUIModel(key: $key, label: $label, placeholder: $placeholder, items: $items, selectedValue: $selectedValue, enabled: $enabled)';
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract mixin class _$DropdownSDUIModelCopyWith<$Res> implements $DropdownSDUIModelCopyWith<$Res> {
|
||||
factory _$DropdownSDUIModelCopyWith(_DropdownSDUIModel value, $Res Function(_DropdownSDUIModel) _then) = __$DropdownSDUIModelCopyWithImpl;
|
||||
@override @useResult
|
||||
$Res call({
|
||||
String? key, String? label, String? placeholder, List<String>? items, String? selectedValue, bool? enabled
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
/// @nodoc
|
||||
class __$DropdownSDUIModelCopyWithImpl<$Res>
|
||||
implements _$DropdownSDUIModelCopyWith<$Res> {
|
||||
__$DropdownSDUIModelCopyWithImpl(this._self, this._then);
|
||||
|
||||
final _DropdownSDUIModel _self;
|
||||
final $Res Function(_DropdownSDUIModel) _then;
|
||||
|
||||
/// Create a copy of DropdownSDUIModel
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override @pragma('vm:prefer-inline') $Res call({Object? key = freezed,Object? label = freezed,Object? placeholder = freezed,Object? items = freezed,Object? selectedValue = freezed,Object? enabled = freezed,}) {
|
||||
return _then(_DropdownSDUIModel(
|
||||
key: freezed == key ? _self.key : key // ignore: cast_nullable_to_non_nullable
|
||||
as String?,label: freezed == label ? _self.label : label // ignore: cast_nullable_to_non_nullable
|
||||
as String?,placeholder: freezed == placeholder ? _self.placeholder : placeholder // ignore: cast_nullable_to_non_nullable
|
||||
as String?,items: freezed == items ? _self._items : items // ignore: cast_nullable_to_non_nullable
|
||||
as List<String>?,selectedValue: freezed == selectedValue ? _self.selectedValue : selectedValue // ignore: cast_nullable_to_non_nullable
|
||||
as String?,enabled: freezed == enabled ? _self.enabled : enabled // ignore: cast_nullable_to_non_nullable
|
||||
as bool?,
|
||||
));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
// dart format on
|
||||
@@ -0,0 +1,29 @@
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'dropdown_sdui_model.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// JsonSerializableGenerator
|
||||
// **************************************************************************
|
||||
|
||||
_DropdownSDUIModel _$DropdownSDUIModelFromJson(Map<String, dynamic> json) =>
|
||||
_DropdownSDUIModel(
|
||||
key: json['key'] as String?,
|
||||
label: json['label'] as String?,
|
||||
placeholder: json['placeholder'] as String?,
|
||||
items: (json['items'] as List<dynamic>?)
|
||||
?.map((e) => e as String)
|
||||
.toList(),
|
||||
selectedValue: json['selected_value'] as String?,
|
||||
enabled: json['enabled'] as bool?,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$DropdownSDUIModelToJson(_DropdownSDUIModel instance) =>
|
||||
<String, dynamic>{
|
||||
'key': instance.key,
|
||||
'label': instance.label,
|
||||
'placeholder': instance.placeholder,
|
||||
'items': instance.items,
|
||||
'selected_value': instance.selectedValue,
|
||||
'enabled': instance.enabled,
|
||||
};
|
||||
@@ -0,0 +1,251 @@
|
||||
import 'dart:io';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:rasadyar_chicken/presentation/widget/sdui/widgets/image_picker/model/image_picker_sdui_model.dart';
|
||||
import 'package:rasadyar_core/core.dart';
|
||||
|
||||
class ImagePickerSDUI extends StatefulWidget {
|
||||
final ImagePickerSDUIModel model;
|
||||
final Map<String, RxList<XFile>>? images;
|
||||
final Function(String key, RxList<XFile> images)? onImagesChanged;
|
||||
|
||||
const ImagePickerSDUI({
|
||||
super.key,
|
||||
required this.model,
|
||||
|
||||
this.images,
|
||||
this.onImagesChanged,
|
||||
});
|
||||
|
||||
@override
|
||||
State<ImagePickerSDUI> createState() => _ImagePickerSDUIState();
|
||||
}
|
||||
|
||||
class _ImagePickerSDUIState extends State<ImagePickerSDUI> {
|
||||
late RImagePickerController imagePickerController;
|
||||
RxList<XFile>? imageList;
|
||||
Set<String> _addedImagePaths = {}; // برای track کردن عکسهای اضافه شده
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
imagePickerController = RImagePickerController();
|
||||
|
||||
final key = widget.model.key ?? '';
|
||||
if (key.isNotEmpty) {
|
||||
// Get or create the images list for this key
|
||||
if (widget.images != null && widget.images!.containsKey(key)) {
|
||||
imageList = widget.images![key]!;
|
||||
// اضافه کردن path های عکسهای موجود به set
|
||||
_addedImagePaths = imageList!.map((img) => img.path).toSet();
|
||||
} else {
|
||||
imageList = RxList<XFile>();
|
||||
if (widget.images != null) {
|
||||
widget.images![key] = imageList!;
|
||||
}
|
||||
_addedImagePaths = {};
|
||||
}
|
||||
|
||||
imagePickerController.capturedImages.clear();
|
||||
|
||||
// Listen to controller changes
|
||||
imagePickerController.addListener(() {
|
||||
if (imagePickerController.capturedImages.isNotEmpty &&
|
||||
imageList != null) {
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||
final maxImages = widget.model.maxImages;
|
||||
final allCapturedImages = imagePickerController.capturedImages;
|
||||
|
||||
// فقط عکسهای جدید را پیدا میکنیم (عکسهایی که قبلاً اضافه نشدهاند)
|
||||
final newImages = allCapturedImages
|
||||
.where((img) => !_addedImagePaths.contains(img.path))
|
||||
.toList();
|
||||
|
||||
if (newImages.isNotEmpty) {
|
||||
if (maxImages != null) {
|
||||
// اگر محدودیت وجود دارد، فقط تا maxImages عکس اضافه میکنیم
|
||||
final currentCount = imageList!.length;
|
||||
final remainingSlots = maxImages - currentCount;
|
||||
|
||||
if (remainingSlots > 0) {
|
||||
final imagesToAdd = newImages.take(remainingSlots).toList();
|
||||
imageList!.addAll(imagesToAdd);
|
||||
// اضافه کردن path های عکسهای جدید به set
|
||||
_addedImagePaths.addAll(imagesToAdd.map((img) => img.path));
|
||||
}
|
||||
} else {
|
||||
// اگر محدودیت وجود ندارد، همه عکسهای جدید را اضافه میکنیم
|
||||
imageList!.addAll(newImages);
|
||||
// اضافه کردن path های عکسهای جدید به set
|
||||
_addedImagePaths.addAll(newImages.map((img) => img.path));
|
||||
}
|
||||
}
|
||||
|
||||
if (widget.onImagesChanged != null) {
|
||||
widget.onImagesChanged!(key, imageList!);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
imagePickerController.disposeCameraController();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final key = widget.model.key ?? '';
|
||||
if (key.isEmpty || imageList == null) {
|
||||
return const SizedBox.shrink();
|
||||
}
|
||||
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
SizedBox(height: 10.h),
|
||||
Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: Obx(() {
|
||||
final maxImages = widget.model.maxImages;
|
||||
final currentImageCount = imageList!.length;
|
||||
final canAddMore =
|
||||
maxImages == null || currentImageCount < maxImages;
|
||||
|
||||
return SingleChildScrollView(
|
||||
scrollDirection: Axis.horizontal,
|
||||
physics: BouncingScrollPhysics(),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
spacing: 8,
|
||||
children: [
|
||||
...imageList!.map(
|
||||
(entry) => Stack(
|
||||
children: [
|
||||
Container(
|
||||
height: 80.h,
|
||||
width: 80.w,
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
border: Border.all(
|
||||
width: 1,
|
||||
color: AppColor.blackLightHover,
|
||||
),
|
||||
),
|
||||
child: ClipRRect(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
child: Image.file(
|
||||
File(entry.path),
|
||||
fit: BoxFit.cover,
|
||||
),
|
||||
),
|
||||
),
|
||||
// Delete button
|
||||
Positioned(
|
||||
top: 4,
|
||||
left: 4,
|
||||
child: GestureDetector(
|
||||
onTap: () {
|
||||
imageList!.removeWhere(
|
||||
(element) => element.path == entry.path,
|
||||
);
|
||||
// حذف path از set
|
||||
_addedImagePaths.remove(entry.path);
|
||||
if (widget.onImagesChanged != null) {
|
||||
widget.onImagesChanged!(key, imageList!);
|
||||
}
|
||||
},
|
||||
child: Container(
|
||||
width: 24,
|
||||
height: 24,
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.red,
|
||||
shape: BoxShape.circle,
|
||||
),
|
||||
child: Icon(
|
||||
Icons.close,
|
||||
color: Colors.white,
|
||||
size: 16,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
// Add image button - only show if we can add more
|
||||
if (canAddMore)
|
||||
GestureDetector(
|
||||
onTap: () {
|
||||
imagePickerController.capturedImages.clear();
|
||||
|
||||
final existingPaths = imageList!
|
||||
.map((img) => img.path)
|
||||
.toSet();
|
||||
_addedImagePaths = existingPaths;
|
||||
|
||||
Get.to(
|
||||
() => RImagePicker(
|
||||
controller: imagePickerController,
|
||||
maxImages: maxImages != null
|
||||
? maxImages - currentImageCount
|
||||
: null,
|
||||
),
|
||||
fullscreenDialog: true,
|
||||
transition: Transition.fade,
|
||||
duration: Duration(milliseconds: 300),
|
||||
);
|
||||
},
|
||||
child: Container(
|
||||
height: 80.h,
|
||||
width: 80.w,
|
||||
padding: EdgeInsets.all(22),
|
||||
decoration: BoxDecoration(
|
||||
color: Color(0xFFE9E9E9),
|
||||
border: Border.all(
|
||||
width: 1,
|
||||
color: AppColor.blackLightHover,
|
||||
),
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
child: Assets.vec.galleryAddSvg.svg(
|
||||
width: 36,
|
||||
height: 36,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}),
|
||||
),
|
||||
],
|
||||
),
|
||||
if (widget.model.label != null && widget.model.label!.isNotEmpty) ...[
|
||||
SizedBox(height: 9.h),
|
||||
RichText(
|
||||
text: TextSpan(
|
||||
children: [
|
||||
TextSpan(
|
||||
text: widget.model.label!,
|
||||
style: AppFonts.yekan14.copyWith(
|
||||
color: AppColor.textColorLight,
|
||||
),
|
||||
),
|
||||
if (widget.model.required == true)
|
||||
TextSpan(
|
||||
text: ' *',
|
||||
style: AppFonts.yekan14.copyWith(color: Colors.red),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||
|
||||
part 'image_picker_sdui_model.freezed.dart';
|
||||
part 'image_picker_sdui_model.g.dart';
|
||||
|
||||
@freezed
|
||||
abstract class ImagePickerSDUIModel with _$ImagePickerSDUIModel {
|
||||
const factory ImagePickerSDUIModel({
|
||||
String? key,
|
||||
String? label,
|
||||
bool? required,
|
||||
int? maxImages,
|
||||
}) = _ImagePickerSDUIModel;
|
||||
|
||||
factory ImagePickerSDUIModel.fromJson(Map<String, dynamic> json) =>
|
||||
_$ImagePickerSDUIModelFromJson(json);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,286 @@
|
||||
// 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 'image_picker_sdui_model.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// FreezedGenerator
|
||||
// **************************************************************************
|
||||
|
||||
// dart format off
|
||||
T _$identity<T>(T value) => value;
|
||||
|
||||
/// @nodoc
|
||||
mixin _$ImagePickerSDUIModel {
|
||||
|
||||
String? get key; String? get label; bool? get required; int? get maxImages;
|
||||
/// Create a copy of ImagePickerSDUIModel
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@pragma('vm:prefer-inline')
|
||||
$ImagePickerSDUIModelCopyWith<ImagePickerSDUIModel> get copyWith => _$ImagePickerSDUIModelCopyWithImpl<ImagePickerSDUIModel>(this as ImagePickerSDUIModel, _$identity);
|
||||
|
||||
/// Serializes this ImagePickerSDUIModel to a JSON map.
|
||||
Map<String, dynamic> toJson();
|
||||
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is ImagePickerSDUIModel&&(identical(other.key, key) || other.key == key)&&(identical(other.label, label) || other.label == label)&&(identical(other.required, required) || other.required == required)&&(identical(other.maxImages, maxImages) || other.maxImages == maxImages));
|
||||
}
|
||||
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType,key,label,required,maxImages);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'ImagePickerSDUIModel(key: $key, label: $label, required: $required, maxImages: $maxImages)';
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract mixin class $ImagePickerSDUIModelCopyWith<$Res> {
|
||||
factory $ImagePickerSDUIModelCopyWith(ImagePickerSDUIModel value, $Res Function(ImagePickerSDUIModel) _then) = _$ImagePickerSDUIModelCopyWithImpl;
|
||||
@useResult
|
||||
$Res call({
|
||||
String? key, String? label, bool? required, int? maxImages
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
/// @nodoc
|
||||
class _$ImagePickerSDUIModelCopyWithImpl<$Res>
|
||||
implements $ImagePickerSDUIModelCopyWith<$Res> {
|
||||
_$ImagePickerSDUIModelCopyWithImpl(this._self, this._then);
|
||||
|
||||
final ImagePickerSDUIModel _self;
|
||||
final $Res Function(ImagePickerSDUIModel) _then;
|
||||
|
||||
/// Create a copy of ImagePickerSDUIModel
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@pragma('vm:prefer-inline') @override $Res call({Object? key = freezed,Object? label = freezed,Object? required = freezed,Object? maxImages = freezed,}) {
|
||||
return _then(_self.copyWith(
|
||||
key: freezed == key ? _self.key : key // ignore: cast_nullable_to_non_nullable
|
||||
as String?,label: freezed == label ? _self.label : label // ignore: cast_nullable_to_non_nullable
|
||||
as String?,required: freezed == required ? _self.required : required // ignore: cast_nullable_to_non_nullable
|
||||
as bool?,maxImages: freezed == maxImages ? _self.maxImages : maxImages // ignore: cast_nullable_to_non_nullable
|
||||
as int?,
|
||||
));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/// Adds pattern-matching-related methods to [ImagePickerSDUIModel].
|
||||
extension ImagePickerSDUIModelPatterns on ImagePickerSDUIModel {
|
||||
/// 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( _ImagePickerSDUIModel value)? $default,{required TResult orElse(),}){
|
||||
final _that = this;
|
||||
switch (_that) {
|
||||
case _ImagePickerSDUIModel() 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( _ImagePickerSDUIModel value) $default,){
|
||||
final _that = this;
|
||||
switch (_that) {
|
||||
case _ImagePickerSDUIModel():
|
||||
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( _ImagePickerSDUIModel value)? $default,){
|
||||
final _that = this;
|
||||
switch (_that) {
|
||||
case _ImagePickerSDUIModel() 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, String? label, bool? required, int? maxImages)? $default,{required TResult orElse(),}) {final _that = this;
|
||||
switch (_that) {
|
||||
case _ImagePickerSDUIModel() when $default != null:
|
||||
return $default(_that.key,_that.label,_that.required,_that.maxImages);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, String? label, bool? required, int? maxImages) $default,) {final _that = this;
|
||||
switch (_that) {
|
||||
case _ImagePickerSDUIModel():
|
||||
return $default(_that.key,_that.label,_that.required,_that.maxImages);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, String? label, bool? required, int? maxImages)? $default,) {final _that = this;
|
||||
switch (_that) {
|
||||
case _ImagePickerSDUIModel() when $default != null:
|
||||
return $default(_that.key,_that.label,_that.required,_that.maxImages);case _:
|
||||
return null;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
@JsonSerializable()
|
||||
|
||||
class _ImagePickerSDUIModel implements ImagePickerSDUIModel {
|
||||
const _ImagePickerSDUIModel({this.key, this.label, this.required, this.maxImages});
|
||||
factory _ImagePickerSDUIModel.fromJson(Map<String, dynamic> json) => _$ImagePickerSDUIModelFromJson(json);
|
||||
|
||||
@override final String? key;
|
||||
@override final String? label;
|
||||
@override final bool? required;
|
||||
@override final int? maxImages;
|
||||
|
||||
/// Create a copy of ImagePickerSDUIModel
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override @JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@pragma('vm:prefer-inline')
|
||||
_$ImagePickerSDUIModelCopyWith<_ImagePickerSDUIModel> get copyWith => __$ImagePickerSDUIModelCopyWithImpl<_ImagePickerSDUIModel>(this, _$identity);
|
||||
|
||||
@override
|
||||
Map<String, dynamic> toJson() {
|
||||
return _$ImagePickerSDUIModelToJson(this, );
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is _ImagePickerSDUIModel&&(identical(other.key, key) || other.key == key)&&(identical(other.label, label) || other.label == label)&&(identical(other.required, required) || other.required == required)&&(identical(other.maxImages, maxImages) || other.maxImages == maxImages));
|
||||
}
|
||||
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType,key,label,required,maxImages);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'ImagePickerSDUIModel(key: $key, label: $label, required: $required, maxImages: $maxImages)';
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract mixin class _$ImagePickerSDUIModelCopyWith<$Res> implements $ImagePickerSDUIModelCopyWith<$Res> {
|
||||
factory _$ImagePickerSDUIModelCopyWith(_ImagePickerSDUIModel value, $Res Function(_ImagePickerSDUIModel) _then) = __$ImagePickerSDUIModelCopyWithImpl;
|
||||
@override @useResult
|
||||
$Res call({
|
||||
String? key, String? label, bool? required, int? maxImages
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
/// @nodoc
|
||||
class __$ImagePickerSDUIModelCopyWithImpl<$Res>
|
||||
implements _$ImagePickerSDUIModelCopyWith<$Res> {
|
||||
__$ImagePickerSDUIModelCopyWithImpl(this._self, this._then);
|
||||
|
||||
final _ImagePickerSDUIModel _self;
|
||||
final $Res Function(_ImagePickerSDUIModel) _then;
|
||||
|
||||
/// Create a copy of ImagePickerSDUIModel
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override @pragma('vm:prefer-inline') $Res call({Object? key = freezed,Object? label = freezed,Object? required = freezed,Object? maxImages = freezed,}) {
|
||||
return _then(_ImagePickerSDUIModel(
|
||||
key: freezed == key ? _self.key : key // ignore: cast_nullable_to_non_nullable
|
||||
as String?,label: freezed == label ? _self.label : label // ignore: cast_nullable_to_non_nullable
|
||||
as String?,required: freezed == required ? _self.required : required // ignore: cast_nullable_to_non_nullable
|
||||
as bool?,maxImages: freezed == maxImages ? _self.maxImages : maxImages // ignore: cast_nullable_to_non_nullable
|
||||
as int?,
|
||||
));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
// dart format on
|
||||
@@ -0,0 +1,25 @@
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'image_picker_sdui_model.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// JsonSerializableGenerator
|
||||
// **************************************************************************
|
||||
|
||||
_ImagePickerSDUIModel _$ImagePickerSDUIModelFromJson(
|
||||
Map<String, dynamic> json,
|
||||
) => _ImagePickerSDUIModel(
|
||||
key: json['key'] as String?,
|
||||
label: json['label'] as String?,
|
||||
required: json['required'] as bool?,
|
||||
maxImages: (json['max_images'] as num?)?.toInt(),
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$ImagePickerSDUIModelToJson(
|
||||
_ImagePickerSDUIModel instance,
|
||||
) => <String, dynamic>{
|
||||
'key': instance.key,
|
||||
'label': instance.label,
|
||||
'required': instance.required,
|
||||
'max_images': instance.maxImages,
|
||||
};
|
||||
@@ -4,26 +4,81 @@ import 'package:rasadyar_core/core.dart';
|
||||
|
||||
import 'model/text_form_field_sdui_model.dart';
|
||||
|
||||
Widget textFormFiledSDUI({required TextFormFieldSDUIModel model}) {
|
||||
Widget textFormFiledSDUI({
|
||||
required TextFormFieldSDUIModel model,
|
||||
TextEditingController? controller,
|
||||
}) {
|
||||
List<TextInputFormatter>? inputFormatters = [];
|
||||
TextInputType? keyboardType;
|
||||
VoidCallback? onTap;
|
||||
bool isReadonly = model.readonly ?? false;
|
||||
|
||||
if (model.keyboardType == 'text') {
|
||||
keyboardType = TextInputType.text;
|
||||
} else if (model.keyboardType == 'number') {
|
||||
keyboardType = TextInputType.numberWithOptions(
|
||||
decimal: model.decimal ?? false,
|
||||
);
|
||||
final textController = controller ?? TextEditingController(text: model.value);
|
||||
|
||||
inputFormatters.add(FilteringTextInputFormatter.digitsOnly);
|
||||
}
|
||||
if (model.type == 'date_picker') {
|
||||
// برای date picker، readonly میکنیم و onTap اضافه میکنیم
|
||||
isReadonly = true;
|
||||
|
||||
if (model.commaSperator ?? false) {
|
||||
inputFormatters.add(SeparatorInputFormatter());
|
||||
onTap = () {
|
||||
// پارس کردن تاریخ فعلی اگر وجود دارد
|
||||
Jalali? initialDate;
|
||||
if (textController.text.isNotEmpty) {
|
||||
try {
|
||||
// فرض میکنیم تاریخ به فرمت '1404/01/01' یا '1404-01-01' است
|
||||
final dateStr = textController.text.replaceAll('-', '/');
|
||||
final parts = dateStr.split('/');
|
||||
if (parts.length == 3) {
|
||||
final year = int.tryParse(parts[0]);
|
||||
final month = int.tryParse(parts[1]);
|
||||
final day = int.tryParse(parts[2]);
|
||||
if (year != null && month != null && day != null) {
|
||||
initialDate = Jalali(year, month, day);
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
iLog('Error parsing date: $e');
|
||||
}
|
||||
}
|
||||
|
||||
// اگر نتوانستیم parse کنیم، از تاریخ امروز استفاده میکنیم
|
||||
initialDate ??= Jalali.now();
|
||||
|
||||
// نمایش date picker
|
||||
Get.bottomSheet(
|
||||
modalDatePicker(
|
||||
initialDate: initialDate,
|
||||
onDateSelected: (selectedDate) {
|
||||
// فرمت کردن تاریخ و قرار دادن در controller
|
||||
textController.text = selectedDate.formatCompactDate();
|
||||
},
|
||||
),
|
||||
isScrollControlled: true,
|
||||
);
|
||||
};
|
||||
} else {
|
||||
if (model.keyboardType == 'text') {
|
||||
keyboardType = TextInputType.text;
|
||||
} else if (model.keyboardType == 'number') {
|
||||
final isDecimal = model.decimal ?? false;
|
||||
keyboardType = TextInputType.numberWithOptions(decimal: isDecimal);
|
||||
|
||||
if (!isDecimal) {
|
||||
inputFormatters.add(FilteringTextInputFormatter.digitsOnly);
|
||||
}
|
||||
}
|
||||
|
||||
if ((model.commaSperator ?? false) &&
|
||||
(model.decimal == null || model.decimal == false)) {
|
||||
inputFormatters.add(SeparatorInputFormatter());
|
||||
}
|
||||
}
|
||||
|
||||
return RTextField(
|
||||
controller: TextEditingController(text: model.value),
|
||||
controller: textController,
|
||||
onChanged: (data) {
|
||||
iLog(data);
|
||||
},
|
||||
onTap: onTap,
|
||||
label: model.label,
|
||||
filled: true,
|
||||
filledColor: AppColor.bgLight,
|
||||
@@ -32,8 +87,8 @@ Widget textFormFiledSDUI({required TextFormFieldSDUIModel model}) {
|
||||
maxLength: model.maxLength,
|
||||
minLines: model.minLine,
|
||||
maxLines: model.maxLine,
|
||||
enabled: model.enabled ?? false,
|
||||
enabled: model.enabled ?? true,
|
||||
inputFormatters: inputFormatters,
|
||||
readonly: model.readonly ?? false,
|
||||
readonly: isReadonly,
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user