import 'package:dio/dio.dart'; import 'package:flutter/material.dart'; import 'package:flutter_fast_forms/flutter_fast_forms.dart'; import 'package:get/get.dart'; import 'package:styled_widget/styled_widget.dart'; import 'package:tuuli_app/api_controller.dart'; import 'package:tuuli_app/models/table_column_definition.dart'; const typeToNameMatcher = { SerialPrimaryColumnDefinition: "Serial ID", TextColumnDefinition: "Текст", BooleanColumnDefinition: "Логическое значение", TimestampColumnDefinition: "Дата/Время", DoubleColumnDefinition: "Число с плавающей точкой", IntegerColumnDefinition: "Целое число", UserRefColumnDefinition: "Ссылка на пользователя", AssetRefColumnDefinition: "Ссылка на ресурс", }; class CreateTableController extends GetxController { final _tableName = "".obs; String get tableName => _tableName.value; set tableName(String value) => _tableName.value = value; final _columnsDefinition = [].obs; List get columnsDefinition => _columnsDefinition; Future createTable() async { try { final resp = await ApiController.to.apiClient.createTable( tableName: tableName, columnsDefinition: _columnsDefinition.map((e) => e.def).toList(growable: false), ); final respData = resp.data; if (respData == null) { throw Exception("В ответе нет данных"); } Get.back(result: true); } on DioError catch (e) { final respData = e.response?.data; if (respData != null) { Get.snackbar( "Ошибка обновления доступа к таблице", "${respData['error']}", ); } else { Get.snackbar( "Ошибка обновления доступа к таблице", "$e", ); } } catch (e) { Get.snackbar( "Ошибка обновления доступа к таблице", "$e", ); } } Future createNewColumn() async { final columnName = "".obs; final columnType = "".obs; final columnIsUnique = false.obs; final confirm = await Get.dialog( AlertDialog( title: const Text("Создать новую колонку"), content: Wrap( runSpacing: 16, children: [ FastTextField( name: "ColumnName", decoration: const InputDecoration( labelText: "Название", border: OutlineInputBorder(), ), initialValue: columnName.value, onChanged: (value) => columnName.value = value ?? "", ), FastDropdown( name: "ColumnTypes", hint: const Text("Тип"), items: typeToNameMatcher.keys.toList(growable: false), itemsBuilder: (items, field) => items .map( (e) => DropdownMenuItem( value: e, child: Text(typeToNameMatcher[e]!), ), ) .toList(), onChanged: (value) => columnType.value = typeToNameMatcher[value] ?? "", ), FastCheckbox( name: "ColumnIsUnique", titleText: "Уникальное значение?", initialValue: false, onChanged: (value) => columnIsUnique.value = value!, ), ], ), actions: [ TextButton( onPressed: () { Get.back(result: false); }, child: const Text("Отменить"), ), TextButton( onPressed: () { Get.back(result: true); }, child: const Text("Создать"), ), ], ), ); if (confirm != true) return; TableColumnDefinition? ct; switch (columnType.value) { case "Serial ID": ct = SerialPrimaryColumnDefinition( columnName: columnName.value, ); break; case "Текст": ct = TextColumnDefinition( columnName: columnName.value, isUnique: columnIsUnique.value, ); break; case "Логическое значение": ct = BooleanColumnDefinition( columnName: columnName.value, isUnique: columnIsUnique.value, ); break; case "Дата/Время": ct = TimestampColumnDefinition( columnName: columnName.value, isUnique: columnIsUnique.value, ); break; case "Число с плавающей точкой": ct = DoubleColumnDefinition( columnName: columnName.value, isUnique: columnIsUnique.value, ); break; case "Целое число": ct = IntegerColumnDefinition( columnName: columnName.value, isUnique: columnIsUnique.value, ); break; case "Ссылка на пользователя": ct = UserRefColumnDefinition( columnName: columnName.value, ); break; case "Ссылка на ресурс": ct = AssetRefColumnDefinition( columnName: columnName.value, ); break; } if (ct == null) return; _columnsDefinition.add(ct); } void removeColumn(TableColumnDefinition e) { _columnsDefinition.remove(e); } } class CreateTableDialog extends GetView { const CreateTableDialog({Key? key}) : super(key: key); @override Widget build(BuildContext context) { return AlertDialog( title: const Text("Создать новую таблицу"), content: Column( children: [ TextField( decoration: const InputDecoration( labelText: "Название", border: OutlineInputBorder(), ), onChanged: (value) => controller.tableName = value, ), const Divider(), Obx( () => ListView( children: controller.columnsDefinition .map( (e) => ListTile( title: Text(e.columnName), subtitle: Text(e.def), trailing: IconButton( onPressed: () => controller.removeColumn(e), icon: const Icon(Icons.delete), ), ), ) .toList(), ).expanded(), ), const Divider(), [ ElevatedButton( onPressed: () => controller.createNewColumn(), child: const Text("Создать колонку"), ).expanded() ].toRow(), ], ).constrained(width: Get.width * 0.9, height: Get.height * 0.9), actions: [ TextButton( onPressed: () { Get.back(); }, child: const Text("Закрыть"), ), Obx( () => TextButton( onPressed: controller.columnsDefinition.isEmpty ? null : () => controller.createTable(), child: const Text("Создать"), ), ), ], ); } static Future show() async { Get.lazyPut(() => CreateTableController()); return Get.dialog( const CreateTableDialog(), barrierDismissible: false, ); } }