Added routines search field functionlity

This commit is contained in:
Abdullah Alassaf
2024-11-25 01:47:17 +03:00
parent 0c555cda83
commit 30db9cfc2a
6 changed files with 138 additions and 109 deletions

View File

@ -32,8 +32,7 @@ class RoutineBloc extends Bloc<RoutineEvent, RoutineState> {
} }
void _onAddToIfContainer(AddToIfContainer event, Emitter<RoutineState> emit) { void _onAddToIfContainer(AddToIfContainer event, Emitter<RoutineState> emit) {
final updatedIfItems = List<Map<String, dynamic>>.from(state.ifItems) final updatedIfItems = List<Map<String, dynamic>>.from(state.ifItems)..add(event.item);
..add(event.item);
if (event.isTabToRun) { if (event.isTabToRun) {
isTabToRun = true; isTabToRun = true;
isAutomation = false; isAutomation = false;
@ -44,15 +43,12 @@ class RoutineBloc extends Bloc<RoutineEvent, RoutineState> {
emit(state.copyWith(ifItems: updatedIfItems)); emit(state.copyWith(ifItems: updatedIfItems));
} }
void _onAddToThenContainer( void _onAddToThenContainer(AddToThenContainer event, Emitter<RoutineState> emit) {
AddToThenContainer event, Emitter<RoutineState> emit) { final updatedThenItems = List<Map<String, dynamic>>.from(state.thenItems)..add(event.item);
final updatedThenItems = List<Map<String, dynamic>>.from(state.thenItems)
..add(event.item);
emit(state.copyWith(thenItems: updatedThenItems)); emit(state.copyWith(thenItems: updatedThenItems));
} }
void _onAddFunctionsToRoutine( void _onAddFunctionsToRoutine(AddFunctionToRoutine event, Emitter<RoutineState> emit) {
AddFunctionToRoutine event, Emitter<RoutineState> emit) {
try { try {
if (event.functions.isEmpty) return; if (event.functions.isEmpty) return;
@ -61,11 +57,9 @@ class RoutineBloc extends Bloc<RoutineEvent, RoutineState> {
if (currentSelectedFunctions.containsKey(event.uniqueCustomId)) { if (currentSelectedFunctions.containsKey(event.uniqueCustomId)) {
currentSelectedFunctions[event.uniqueCustomId] = currentSelectedFunctions[event.uniqueCustomId] =
List.from(currentSelectedFunctions[event.uniqueCustomId]!) List.from(currentSelectedFunctions[event.uniqueCustomId]!)..addAll(event.functions);
..addAll(event.functions);
} else { } else {
currentSelectedFunctions[event.uniqueCustomId] = currentSelectedFunctions[event.uniqueCustomId] = List.from(event.functions);
List.from(event.functions);
} }
emit(state.copyWith(selectedFunctions: currentSelectedFunctions)); emit(state.copyWith(selectedFunctions: currentSelectedFunctions));
@ -74,8 +68,7 @@ class RoutineBloc extends Bloc<RoutineEvent, RoutineState> {
} }
} }
Future<void> _onLoadScenes( Future<void> _onLoadScenes(LoadScenes event, Emitter<RoutineState> emit) async {
LoadScenes event, Emitter<RoutineState> emit) async {
emit(state.copyWith(isLoading: true, errorMessage: null)); emit(state.copyWith(isLoading: true, errorMessage: null));
try { try {
@ -94,8 +87,7 @@ class RoutineBloc extends Bloc<RoutineEvent, RoutineState> {
} }
} }
Future<void> _onLoadAutomation( Future<void> _onLoadAutomation(LoadAutomation event, Emitter<RoutineState> emit) async {
LoadAutomation event, Emitter<RoutineState> emit) async {
emit(state.copyWith(isLoading: true, errorMessage: null)); emit(state.copyWith(isLoading: true, errorMessage: null));
try { try {
@ -114,13 +106,13 @@ class RoutineBloc extends Bloc<RoutineEvent, RoutineState> {
} }
} }
FutureOr<void> _onSearchRoutines( FutureOr<void> _onSearchRoutines(SearchRoutines event, Emitter<RoutineState> emit) async {
SearchRoutines event, Emitter<RoutineState> emit) { emit(state.copyWith(isLoading: true, errorMessage: null));
emit(state.copyWith(routineName: event.query)); await Future.delayed(const Duration(seconds: 1));
emit(state.copyWith(searchText: event.query));
} }
FutureOr<void> _onAddSelectedIcon( FutureOr<void> _onAddSelectedIcon(AddSelectedIcon event, Emitter<RoutineState> emit) {
AddSelectedIcon event, Emitter<RoutineState> emit) {
emit(state.copyWith(selectedIcon: event.icon)); emit(state.copyWith(selectedIcon: event.icon));
} }
@ -129,8 +121,7 @@ class RoutineBloc extends Bloc<RoutineEvent, RoutineState> {
return actions.first['deviceId'] == 'delay'; return actions.first['deviceId'] == 'delay';
} }
Future<void> _onCreateScene( Future<void> _onCreateScene(CreateSceneEvent event, Emitter<RoutineState> emit) async {
CreateSceneEvent event, Emitter<RoutineState> emit) async {
try { try {
// Check if first action is delay // Check if first action is delay
if (_isFirstActionDelay(state.thenItems)) { if (_isFirstActionDelay(state.thenItems)) {
@ -145,8 +136,7 @@ class RoutineBloc extends Bloc<RoutineEvent, RoutineState> {
final actions = state.thenItems final actions = state.thenItems
.map((item) { .map((item) {
final functions = final functions = state.selectedFunctions[item['uniqueCustomId']] ?? [];
state.selectedFunctions[item['uniqueCustomId']] ?? [];
if (functions.isEmpty) return null; if (functions.isEmpty) return null;
final function = functions.first; final function = functions.first;
@ -201,8 +191,7 @@ class RoutineBloc extends Bloc<RoutineEvent, RoutineState> {
} }
} }
FutureOr<void> _onRemoveDragCard( FutureOr<void> _onRemoveDragCard(RemoveDragCard event, Emitter<RoutineState> emit) {
RemoveDragCard event, Emitter<RoutineState> emit) {
if (event.isFromThen) { if (event.isFromThen) {
/// remove element from thenItems at specific index /// remove element from thenItems at specific index
final thenItems = List<Map<String, dynamic>>.from(state.thenItems); final thenItems = List<Map<String, dynamic>>.from(state.thenItems);

View File

@ -13,50 +13,49 @@ class RoutineState extends Equatable {
final String? loadAutomationErrorMessage; final String? loadAutomationErrorMessage;
final String? routineName; final String? routineName;
final String? selectedIcon; final String? selectedIcon;
final String? searchText;
const RoutineState({ const RoutineState(
this.ifItems = const [], {this.ifItems = const [],
this.thenItems = const [], this.thenItems = const [],
this.availableCards = const [], this.availableCards = const [],
this.scenes = const [], this.scenes = const [],
this.automations = const [], this.automations = const [],
this.selectedFunctions = const {}, this.selectedFunctions = const {},
this.isLoading = false, this.isLoading = false,
this.errorMessage, this.errorMessage,
this.routineName, this.routineName,
this.selectedIcon, this.selectedIcon,
this.loadScenesErrorMessage, this.loadScenesErrorMessage,
this.loadAutomationErrorMessage, this.loadAutomationErrorMessage,
}); this.searchText});
RoutineState copyWith({ RoutineState copyWith(
List<Map<String, dynamic>>? ifItems, {List<Map<String, dynamic>>? ifItems,
List<Map<String, dynamic>>? thenItems, List<Map<String, dynamic>>? thenItems,
List<ScenesModel>? scenes, List<ScenesModel>? scenes,
List<ScenesModel>? automations, List<ScenesModel>? automations,
Map<String, List<DeviceFunctionData>>? selectedFunctions, Map<String, List<DeviceFunctionData>>? selectedFunctions,
bool? isLoading, bool? isLoading,
String? errorMessage, String? errorMessage,
String? routineName, String? routineName,
String? selectedIcon, String? selectedIcon,
String? loadAutomationErrorMessage, String? loadAutomationErrorMessage,
String? loadScenesErrorMessage, String? loadScenesErrorMessage,
}) { String? searchText}) {
return RoutineState( return RoutineState(
ifItems: ifItems ?? this.ifItems, ifItems: ifItems ?? this.ifItems,
thenItems: thenItems ?? this.thenItems, thenItems: thenItems ?? this.thenItems,
scenes: scenes ?? this.scenes, scenes: scenes ?? this.scenes,
automations: automations ?? this.automations, automations: automations ?? this.automations,
selectedFunctions: selectedFunctions ?? this.selectedFunctions, selectedFunctions: selectedFunctions ?? this.selectedFunctions,
isLoading: isLoading ?? this.isLoading, isLoading: isLoading ?? this.isLoading,
errorMessage: errorMessage ?? this.errorMessage, errorMessage: errorMessage ?? this.errorMessage,
routineName: routineName ?? this.routineName, routineName: routineName ?? this.routineName,
selectedIcon: selectedIcon ?? this.selectedIcon, selectedIcon: selectedIcon ?? this.selectedIcon,
loadScenesErrorMessage: loadScenesErrorMessage: loadScenesErrorMessage ?? this.loadScenesErrorMessage,
loadScenesErrorMessage ?? this.loadScenesErrorMessage, loadAutomationErrorMessage: loadAutomationErrorMessage ?? this.loadAutomationErrorMessage,
loadAutomationErrorMessage: searchText: searchText ?? this.searchText);
loadAutomationErrorMessage ?? this.loadAutomationErrorMessage,
);
} }
@override @override
@ -72,5 +71,6 @@ class RoutineState extends Equatable {
selectedIcon, selectedIcon,
loadScenesErrorMessage, loadScenesErrorMessage,
loadAutomationErrorMessage, loadAutomationErrorMessage,
searchText
]; ];
} }

View File

@ -1,6 +1,7 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:syncrow_web/pages/device_managment/all_devices/bloc/device_mgmt_bloc/device_managment_bloc.dart'; import 'package:syncrow_web/pages/device_managment/all_devices/bloc/device_mgmt_bloc/device_managment_bloc.dart';
import 'package:syncrow_web/pages/device_managment/all_devices/models/devices_model.dart';
import 'package:syncrow_web/pages/routiens/bloc/routine_bloc/routine_bloc.dart'; import 'package:syncrow_web/pages/routiens/bloc/routine_bloc/routine_bloc.dart';
import 'package:syncrow_web/pages/routiens/widgets/dragable_card.dart'; import 'package:syncrow_web/pages/routiens/widgets/dragable_card.dart';
@ -14,7 +15,7 @@ class RoutineDevices extends StatelessWidget {
child: BlocBuilder<DeviceManagementBloc, DeviceManagementState>( child: BlocBuilder<DeviceManagementBloc, DeviceManagementState>(
builder: (context, state) { builder: (context, state) {
if (state is DeviceManagementLoaded) { if (state is DeviceManagementLoaded) {
final deviceList = state.devices List<AllDevicesModel> deviceList = state.devices
.where((device) => .where((device) =>
device.productType == 'AC' || device.productType == 'AC' ||
device.productType == '1G' || device.productType == '1G' ||
@ -30,19 +31,39 @@ class RoutineDevices extends StatelessWidget {
runSpacing: 10, runSpacing: 10,
children: deviceList.asMap().entries.map((entry) { children: deviceList.asMap().entries.map((entry) {
final device = entry.value; final device = entry.value;
return DraggableCard( if (routineState.searchText != null && routineState.searchText!.isNotEmpty) {
imagePath: device.getDefaultIcon(device.productType), return device.name!
title: device.name ?? '', .toLowerCase()
deviceData: { .contains(routineState.searchText!.toLowerCase())
'device': device, ? DraggableCard(
'imagePath': device.getDefaultIcon(device.productType), imagePath: device.getDefaultIcon(device.productType),
'title': device.name ?? '', title: device.name ?? '',
'deviceId': device.uuid, deviceData: {
'productType': device.productType, 'device': device,
'functions': device.functions, 'imagePath': device.getDefaultIcon(device.productType),
'uniqueCustomId': '', 'title': device.name ?? '',
}, 'deviceId': device.uuid,
); 'productType': device.productType,
'functions': device.functions,
'uniqueCustomId': '',
},
)
: Container();
} else {
return DraggableCard(
imagePath: device.getDefaultIcon(device.productType),
title: device.name ?? '',
deviceData: {
'device': device,
'imagePath': device.getDefaultIcon(device.productType),
'title': device.name ?? '',
'deviceId': device.uuid,
'productType': device.productType,
'functions': device.functions,
'uniqueCustomId': '',
},
);
}
}).toList(), }).toList(),
); );
}, },

View File

@ -1,6 +1,5 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:syncrow_web/main.dart';
import 'package:syncrow_web/pages/common/buttons/default_button.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/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/bloc/routine_bloc/routine_bloc.dart';
@ -32,9 +31,7 @@ class RoutineSearchAndButtons extends StatelessWidget {
children: [ children: [
ConstrainedBox( ConstrainedBox(
constraints: BoxConstraints( constraints: BoxConstraints(
maxWidth: constraints.maxWidth > 700 maxWidth: constraints.maxWidth > 700 ? 450 : constraints.maxWidth - 32),
? 450
: constraints.maxWidth - 32),
child: StatefulTextField( child: StatefulTextField(
title: 'Routine Name', title: 'Routine Name',
height: 40, height: 40,
@ -46,9 +43,7 @@ class RoutineSearchAndButtons extends StatelessWidget {
isRequired: true, isRequired: true,
width: 450, width: 450,
onChanged: (value) { onChanged: (value) {
context // context.read<RoutineBloc>().add(SearchRoutines(value));
.read<RoutineBloc>()
.add(SearchRoutines(value));
}, },
), ),
), ),
@ -60,14 +55,11 @@ class RoutineSearchAndButtons extends StatelessWidget {
child: Center( child: Center(
child: DefaultButton( child: DefaultButton(
onPressed: () async { onPressed: () async {
final result = final result = await SettingHelper.showSettingDialog(
await SettingHelper.showSettingDialog(
context: context, context: context,
); );
if (result != null) { if (result != null) {
context context.read<RoutineBloc>().add(AddSelectedIcon(result));
.read<RoutineBloc>()
.add(AddSelectedIcon(result));
} }
}, },
borderRadius: 15, borderRadius: 15,

View File

@ -33,17 +33,33 @@ class _ScenesAndAutomationsState extends State<ScenesAndAutomations> {
runSpacing: 10, runSpacing: 10,
children: scenes.asMap().entries.map((entry) { children: scenes.asMap().entries.map((entry) {
final scene = entry.value; final scene = entry.value;
return DraggableCard( if (state.searchText != null && state.searchText!.isNotEmpty) {
imagePath: Assets.logo, return scene.name.toLowerCase().contains(state.searchText!.toLowerCase())
title: scene.name, ? DraggableCard(
deviceData: { imagePath: Assets.logo,
'deviceId': scene.id, title: scene.name,
'name': scene.name, deviceData: {
'status': scene.status, 'deviceId': scene.id,
'type': scene.type, 'name': scene.name,
'icon': scene.icon, 'status': scene.status,
}, 'type': scene.type,
); 'icon': scene.icon,
},
)
: Container();
} else {
return DraggableCard(
imagePath: Assets.logo,
title: scene.name,
deviceData: {
'deviceId': scene.id,
'name': scene.name,
'status': scene.status,
'type': scene.type,
'icon': scene.icon,
},
);
}
}).toList(), }).toList(),
); );
} }

View File

@ -1,11 +1,12 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:syncrow_web/pages/common/text_field/custom_text_field.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/widgets/routines_title_widget.dart'; import 'package:syncrow_web/pages/routiens/widgets/routines_title_widget.dart';
import 'package:syncrow_web/utils/color_manager.dart'; import 'package:syncrow_web/utils/color_manager.dart';
import 'package:syncrow_web/utils/helpers/responsice_layout_helper/responsive_layout_helper.dart'; import 'package:syncrow_web/utils/helpers/responsice_layout_helper/responsive_layout_helper.dart';
class ConditionTitleAndSearchBar extends StatelessWidget class ConditionTitleAndSearchBar extends StatelessWidget with HelperResponsiveLayout {
with HelperResponsiveLayout {
const ConditionTitleAndSearchBar({ const ConditionTitleAndSearchBar({
super.key, super.key,
}); });
@ -34,7 +35,12 @@ class ConditionTitleAndSearchBar extends StatelessWidget
borderRadius: BorderRadius.circular(15), borderRadius: BorderRadius.circular(15),
), ),
controller: TextEditingController(), controller: TextEditingController(),
onChanged: (value) {}, // onSubmitted: (value) {
// context.read<RoutineBloc>().add(SearchRoutines(value));
// },
onChanged: (value) {
context.read<RoutineBloc>().add(SearchRoutines(value));
},
), ),
], ],
) )
@ -57,7 +63,12 @@ class ConditionTitleAndSearchBar extends StatelessWidget
borderRadius: BorderRadius.circular(15), borderRadius: BorderRadius.circular(15),
), ),
controller: TextEditingController(), controller: TextEditingController(),
onChanged: (value) {}, // onSubmitted: (value) {
// context.read<RoutineBloc>().add(SearchRoutines(value));
// },
onChanged: (value) {
context.read<RoutineBloc>().add(SearchRoutines(value));
},
), ),
], ],
); );