diff --git a/lib/pages/routiens/bloc/routine_bloc/routine_bloc.dart b/lib/pages/routiens/bloc/routine_bloc/routine_bloc.dart index 9a780be8..dd76e01a 100644 --- a/lib/pages/routiens/bloc/routine_bloc/routine_bloc.dart +++ b/lib/pages/routiens/bloc/routine_bloc/routine_bloc.dart @@ -38,7 +38,8 @@ class RoutineBloc extends Bloc { final updatedIfItems = List>.from(state.ifItems); // Find the index of the item in teh current itemsList - int index = updatedIfItems.indexWhere((map) => map['uniqueCustomId'] == event.item['uniqueCustomId']); + int index = + updatedIfItems.indexWhere((map) => map['uniqueCustomId'] == event.item['uniqueCustomId']); // Replace the map if the index is valid if (index != -1) { updatedIfItems[index] = event.item; @@ -57,7 +58,8 @@ class RoutineBloc extends Bloc { final currentItems = List>.from(state.thenItems); // Find the index of the item in teh current itemsList - int index = currentItems.indexWhere((map) => map['uniqueCustomId'] == event.item['uniqueCustomId']); + int index = + currentItems.indexWhere((map) => map['uniqueCustomId'] == event.item['uniqueCustomId']); // Replace the map if the index is valid if (index != -1) { currentItems[index] = event.item; @@ -96,7 +98,8 @@ class RoutineBloc extends Bloc { selectedFunction.removeWhere((code) => code.functionCode == functionCode[i]); } - currentSelectedFunctions[event.uniqueCustomId] = List.from(currentFunctions)..addAll(selectedFunction); + currentSelectedFunctions[event.uniqueCustomId] = List.from(currentFunctions) + ..addAll(selectedFunction); } else { currentSelectedFunctions[event.uniqueCustomId] = List.from(event.functions); } @@ -131,10 +134,19 @@ class RoutineBloc extends Bloc { try { final automations = await SceneApi.getAutomationByUnitId(event.unitId); - emit(state.copyWith( - automations: automations, - isLoading: false, - )); + if (automations.isNotEmpty) { + emit(state.copyWith( + automations: automations, + isLoading: false, + )); + } else { + emit(state.copyWith( + isLoading: false, + loadAutomationErrorMessage: 'Failed to load automations', + errorMessage: '', + loadScenesErrorMessage: '', + )); + } } catch (e) { emit(state.copyWith( isLoading: false, @@ -148,6 +160,7 @@ class RoutineBloc extends Bloc { FutureOr _onSearchRoutines(SearchRoutines event, Emitter emit) async { emit(state.copyWith(isLoading: true, errorMessage: null)); await Future.delayed(const Duration(seconds: 1)); + emit(state.copyWith(isLoading: false, errorMessage: null)); emit(state.copyWith(searchText: event.query)); } diff --git a/lib/pages/routiens/widgets/routine_search_and_buttons.dart b/lib/pages/routiens/widgets/routine_search_and_buttons.dart index 73bc403d..6696225f 100644 --- a/lib/pages/routiens/widgets/routine_search_and_buttons.dart +++ b/lib/pages/routiens/widgets/routine_search_and_buttons.dart @@ -1,12 +1,12 @@ import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:syncrow_web/pages/common/buttons/default_button.dart'; -import 'package:syncrow_web/pages/common/text_field/custom_text_field.dart'; import 'package:syncrow_web/pages/routiens/bloc/routine_bloc/routine_bloc.dart'; import 'package:syncrow_web/pages/routiens/helper/save_routine_helper.dart'; import 'package:syncrow_web/pages/routiens/widgets/routine_dialogs/discard_dialog.dart'; import 'package:syncrow_web/pages/routiens/widgets/routine_dialogs/setting_dialog.dart'; import 'package:syncrow_web/utils/color_manager.dart'; +import 'package:syncrow_web/utils/extension/build_context_x.dart'; import 'package:syncrow_web/utils/style.dart'; class RoutineSearchAndButtons extends StatelessWidget { @@ -34,24 +34,73 @@ class RoutineSearchAndButtons extends StatelessWidget { children: [ ConstrainedBox( constraints: BoxConstraints( - maxWidth: constraints.maxWidth > 700 - ? 450 - : constraints.maxWidth - 32), - child: StatefulTextField( - title: 'Routine Name', - height: 40, - controller: TextEditingController(), - hintText: 'Please enter the name', - boxDecoration: containerWhiteDecoration, - elevation: 0, - borderRadius: 15, - isRequired: true, - width: 450, - onChanged: (value) { - context - .read() - .add(SetRoutineName(value)); - }, + maxWidth: + constraints.maxWidth > 700 ? 450 : constraints.maxWidth - 32), + // child: StatefulTextField( + // title: 'Routine Name', + // initialValue: state.routineName ?? '', + // height: 40, + // // controller: TextEditingController(), + // hintText: 'Please enter the name', + // boxDecoration: containerWhiteDecoration, + // elevation: 0, + // borderRadius: 15, + // isRequired: true, + // width: 450, + // onSubmitted: (value) { + // // context.read().add(SetRoutineName(value)); + // }, + // onChanged: (value) { + // context.read().add(SetRoutineName(value)); + // }, + // ), + child: Column( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + children: [ + Text('* ', + style: context.textTheme.bodyMedium! + .copyWith(color: ColorsManager.red, fontSize: 13)), + Text( + 'Routine Name', + style: context.textTheme.bodyMedium!.copyWith( + fontSize: 13, + fontWeight: FontWeight.w600, + color: ColorsManager.blackColor, + ), + ), + ], + ), + Container( + width: 450, + height: 40, + decoration: containerWhiteDecoration, + child: TextFormField( + style: context.textTheme.bodyMedium! + .copyWith(color: ColorsManager.blackColor), + initialValue: state.routineName, + decoration: InputDecoration( + hintText: 'Please enter the name', + hintStyle: context.textTheme.bodyMedium! + .copyWith(fontSize: 12, color: ColorsManager.grayColor), + contentPadding: + const EdgeInsets.symmetric(horizontal: 12, vertical: 10), + border: InputBorder.none, + ), + onChanged: (value) { + context.read().add(SetRoutineName(value)); + }, + validator: (value) { + if (value == null || value.isEmpty) { + return 'This field is required'; + } + return null; + }, + ), + ), + ], ), ), (constraints.maxWidth <= 1000) @@ -61,16 +110,15 @@ class RoutineSearchAndButtons extends StatelessWidget { width: 200, child: Center( child: DefaultButton( - onPressed: state.isAutomation || - state.isTabToRun + onPressed: state.isAutomation || state.isTabToRun ? () async { - final result = await SettingHelper - .showSettingDialog( + final result = await SettingHelper.showSettingDialog( context: context, ); if (result != null) { - context.read().add( - AddSelectedIcon(result)); + context + .read() + .add(AddSelectedIcon(result)); } } : null, @@ -126,8 +174,40 @@ class RoutineSearchAndButtons extends StatelessWidget { child: Center( child: DefaultButton( onPressed: () { - SaveRoutineHelper.showSaveRoutineDialog( - context); + if (state.routineName == null || state.routineName!.isEmpty) { + ScaffoldMessenger.of(context).showSnackBar( + SnackBar( + content: const Text('Please enter the routine name'), + duration: const Duration(seconds: 2), + backgroundColor: ColorsManager.red, + action: SnackBarAction( + label: 'Dismiss', + onPressed: () { + // Optional action on Snackbar + }, + ), + ), + ); + return; + } + + if (state.ifItems.isEmpty || state.thenItems.isEmpty) { + ScaffoldMessenger.of(context).showSnackBar( + SnackBar( + content: const Text('Please add if and then condition'), + duration: const Duration(seconds: 2), + backgroundColor: ColorsManager.red, + action: SnackBarAction( + label: 'Dismiss', + onPressed: () { + // Optional action on Snackbar + }, + ), + ), + ); + return; + } + SaveRoutineHelper.showSaveRoutineDialog(context); }, borderRadius: 15, elevation: 0, @@ -158,14 +238,11 @@ class RoutineSearchAndButtons extends StatelessWidget { child: DefaultButton( onPressed: state.isAutomation || state.isTabToRun ? () async { - final result = - await SettingHelper.showSettingDialog( + final result = await SettingHelper.showSettingDialog( context: context, ); if (result != null) { - context - .read() - .add(AddSelectedIcon(result)); + context.read().add(AddSelectedIcon(result)); } } : null, @@ -215,6 +292,39 @@ class RoutineSearchAndButtons extends StatelessWidget { child: Center( child: DefaultButton( onPressed: () { + if (state.routineName == null || state.routineName!.isEmpty) { + ScaffoldMessenger.of(context).showSnackBar( + SnackBar( + content: const Text('Please enter the routine name'), + duration: const Duration(seconds: 2), + backgroundColor: ColorsManager.red, + action: SnackBarAction( + label: 'Dismiss', + onPressed: () { + // Optional action on Snackbar + }, + ), + ), + ); + return; + } + + if (state.ifItems.isEmpty || state.thenItems.isEmpty) { + ScaffoldMessenger.of(context).showSnackBar( + SnackBar( + content: const Text('Please add if and then condition'), + duration: const Duration(seconds: 2), + backgroundColor: ColorsManager.red, + action: SnackBarAction( + label: 'Dismiss', + onPressed: () { + // Optional action on Snackbar + }, + ), + ), + ); + return; + } SaveRoutineHelper.showSaveRoutineDialog(context); }, borderRadius: 15, diff --git a/lib/pages/routiens/widgets/scenes_and_automations.dart b/lib/pages/routiens/widgets/scenes_and_automations.dart index 746795af..36ee7db2 100644 --- a/lib/pages/routiens/widgets/scenes_and_automations.dart +++ b/lib/pages/routiens/widgets/scenes_and_automations.dart @@ -26,7 +26,7 @@ class _ScenesAndAutomationsState extends State { Widget build(BuildContext context) { return BlocBuilder( builder: (context, state) { - if (state.scenes.isNotEmpty || state.automations.isNotEmpty) { + if (!state.isLoading) { var scenes = [...state.scenes, ...state.automations]; return Wrap( spacing: 10,