diff --git a/assets/icons/functions_icons/factory_reset.svg b/assets/icons/functions_icons/factory_reset.svg new file mode 100644 index 0000000..7a47f24 --- /dev/null +++ b/assets/icons/functions_icons/factory_reset.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/assets/icons/functions_icons/far_detection.svg b/assets/icons/functions_icons/far_detection.svg new file mode 100644 index 0000000..2827d94 --- /dev/null +++ b/assets/icons/functions_icons/far_detection.svg @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/assets/icons/functions_icons/far_detection_function.svg b/assets/icons/functions_icons/far_detection_function.svg new file mode 100644 index 0000000..894b84e --- /dev/null +++ b/assets/icons/functions_icons/far_detection_function.svg @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/assets/icons/functions_icons/indicator.svg b/assets/icons/functions_icons/indicator.svg new file mode 100644 index 0000000..b58a976 --- /dev/null +++ b/assets/icons/functions_icons/indicator.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/assets/icons/functions_icons/master_state.svg b/assets/icons/functions_icons/master_state.svg new file mode 100644 index 0000000..0aafae1 --- /dev/null +++ b/assets/icons/functions_icons/master_state.svg @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + diff --git a/assets/icons/functions_icons/motion_detection.svg b/assets/icons/functions_icons/motion_detection.svg new file mode 100644 index 0000000..a9b2d68 --- /dev/null +++ b/assets/icons/functions_icons/motion_detection.svg @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/icons/functions_icons/motionless_detection.svg b/assets/icons/functions_icons/motionless_detection.svg new file mode 100644 index 0000000..25a767c --- /dev/null +++ b/assets/icons/functions_icons/motionless_detection.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/assets/icons/functions_icons/nobody_time.svg b/assets/icons/functions_icons/nobody_time.svg new file mode 100644 index 0000000..df80b51 --- /dev/null +++ b/assets/icons/functions_icons/nobody_time.svg @@ -0,0 +1,4 @@ + + + + diff --git a/assets/icons/functions_icons/reset_off.svg b/assets/icons/functions_icons/reset_off.svg new file mode 100644 index 0000000..eac88f2 --- /dev/null +++ b/assets/icons/functions_icons/reset_off.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/assets/icons/functions_icons/switch_alarm_sound.svg b/assets/icons/functions_icons/switch_alarm_sound.svg new file mode 100644 index 0000000..db64533 --- /dev/null +++ b/assets/icons/functions_icons/switch_alarm_sound.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/lib/features/scene/bloc/scene_bloc/scene_bloc.dart b/lib/features/scene/bloc/scene_bloc/scene_bloc.dart index 81d04d3..d573d0a 100644 --- a/lib/features/scene/bloc/scene_bloc/scene_bloc.dart +++ b/lib/features/scene/bloc/scene_bloc/scene_bloc.dart @@ -11,38 +11,37 @@ part 'scene_state.dart'; class SceneBloc extends Bloc { SceneBloc() : super(SceneInitial()) { on(_onLoadScenes); - on(_sceneTrigger); + on(_onSceneTrigger); } - FutureOr _onLoadScenes( - LoadScenes event, Emitter emit) async { + Future _onLoadScenes(LoadScenes event, Emitter emit) async { emit(SceneLoading()); try { final scenes = await SceneApi.getScenesByUnitId(event.unitId); - if (scenes.isNotEmpty) { - emit(SceneLoaded(scenes)); - } else { - emit(SceneTriggerError(message: 'Something went wrong')); - } + emit(SceneLoaded(scenes)); } catch (e) { emit(SceneError(message: e.toString())); } } - FutureOr _sceneTrigger( + Future _onSceneTrigger( SceneTrigger event, Emitter emit) async { - emit(SceneTriggerLoading()); + final currentState = state; + if (currentState is SceneLoaded) { + emit(SceneLoaded(currentState.scenes, loadingSceneId: event.sceneId)); - try { - final success = await SceneApi.triggerScene(event.sceneId); - if (success) { - emit(SceneTriggerState(success: true)); - } else { - emit(SceneTriggerError(message: 'Something went wrong')); + try { + final success = await SceneApi.triggerScene(event.sceneId); + if (success) { + emit(SceneTriggerSuccess(event.name)); + emit(SceneLoaded(currentState.scenes)); + } else { + emit(const SceneError(message: 'Something went wrong')); + } + } catch (e) { + emit(SceneError(message: e.toString())); } - } catch (e) { - emit(SceneTriggerError(message: e.toString())); } } } diff --git a/lib/features/scene/bloc/scene_bloc/scene_event.dart b/lib/features/scene/bloc/scene_bloc/scene_event.dart index 8c05921..7412afc 100644 --- a/lib/features/scene/bloc/scene_bloc/scene_event.dart +++ b/lib/features/scene/bloc/scene_bloc/scene_event.dart @@ -1,6 +1,8 @@ import 'package:equatable/equatable.dart'; abstract class SceneEvent extends Equatable { + const SceneEvent(); + @override List get props => []; } @@ -8,7 +10,7 @@ abstract class SceneEvent extends Equatable { class LoadScenes extends SceneEvent { final String unitId; - LoadScenes(this.unitId); + const LoadScenes(this.unitId); @override List get props => [unitId]; @@ -16,8 +18,9 @@ class LoadScenes extends SceneEvent { class SceneTrigger extends SceneEvent { final String sceneId; + final String name; - SceneTrigger(this.sceneId); + const SceneTrigger(this.sceneId, this.name); @override List get props => [sceneId]; diff --git a/lib/features/scene/bloc/scene_bloc/scene_state.dart b/lib/features/scene/bloc/scene_bloc/scene_state.dart index 136c7ba..2f3fdc8 100644 --- a/lib/features/scene/bloc/scene_bloc/scene_state.dart +++ b/lib/features/scene/bloc/scene_bloc/scene_state.dart @@ -1,8 +1,10 @@ part of 'scene_bloc.dart'; abstract class SceneState extends Equatable { + const SceneState(); + @override - List get props => []; + List get props => []; } class SceneInitial extends SceneState {} @@ -11,38 +13,28 @@ class SceneLoading extends SceneState {} class SceneLoaded extends SceneState { final List scenes; + final String? loadingSceneId; - SceneLoaded(this.scenes); + const SceneLoaded(this.scenes, {this.loadingSceneId}); @override - List get props => [scenes]; + List get props => [scenes, loadingSceneId]; } class SceneError extends SceneState { final String message; - SceneError({required this.message}); + const SceneError({required this.message}); @override List get props => [message]; } -class SceneTriggerState extends SceneState { - final bool success; +class SceneTriggerSuccess extends SceneState { + final String sceneName; - SceneTriggerState({required this.success}); + const SceneTriggerSuccess(this.sceneName); @override - List get props => [success]; -} - -class SceneTriggerLoading extends SceneState {} - -class SceneTriggerError extends SceneState { - final String message; - - SceneTriggerError({required this.message}); - - @override - List get props => [message]; + List get props => [sceneName]; } diff --git a/lib/features/scene/helper/scene_operations_data_helper.dart b/lib/features/scene/helper/scene_operations_data_helper.dart index a123ca0..dc4026c 100644 --- a/lib/features/scene/helper/scene_operations_data_helper.dart +++ b/lib/features/scene/helper/scene_operations_data_helper.dart @@ -145,14 +145,182 @@ List doorLockFunctions( {required List functions, required String deviceId, required String deviceName}) { - return []; + return [ + SceneStaticFunction( + deviceId: deviceId, + deviceName: deviceName, + icon: Assets.assetsIconsDoorLock, + operationName: 'Set Door lock Normal Open', + code: 'normal_open_switch', + operationalValues: [ + SceneOperationalValue( + icon: Assets.assetsAcPower, description: "ON", value: true), + SceneOperationalValue( + icon: Assets.assetsAcPowerOFF, description: "OFF", value: false), + ], + ), + ]; } List wallSensorFunctions( {required List functions, required String deviceId, required String deviceName}) { - return []; + return [ + SceneStaticFunction( + deviceId: deviceId, + deviceName: deviceName, + icon: Assets.assetsFarDetection, + operationName: 'Far Detection', + code: 'far_detection', + operationalValues: [ + SceneOperationalValue( + icon: Assets.assetsFarDetectionFunction, + value: 75, + description: '75cm', + iconValue: '75', + ), + SceneOperationalValue( + icon: Assets.assetsFarDetectionFunction, + value: 150, + description: '150cm', + iconValue: '150', + ), + SceneOperationalValue( + icon: Assets.assetsFarDetectionFunction, + value: 225, + description: '225cm', + iconValue: '225', + ), + SceneOperationalValue( + icon: Assets.assetsFarDetectionFunction, + value: 300, + description: '300cm', + iconValue: '300', + ), + SceneOperationalValue( + icon: Assets.assetsFarDetectionFunction, + value: 375, + description: '375cm', + iconValue: '375', + ), + SceneOperationalValue( + icon: Assets.assetsFarDetectionFunction, + value: 450, + description: '450cm', + iconValue: '450', + ), + SceneOperationalValue( + icon: Assets.assetsFarDetectionFunction, + value: 525, + description: '525cm', + iconValue: '525', + ), + SceneOperationalValue( + icon: Assets.assetsFarDetectionFunction, + value: 600, + description: '600cm', + iconValue: '600', + ), + ], + ), + SceneStaticFunction( + deviceId: deviceId, + deviceName: deviceName, + icon: Assets.assetsMotionDetection, + operationName: 'Motion Detection Sensitivity', + code: 'motion_sensitivity_value', + operationalValues: [ + SceneOperationalValue( + icon: Assets.assetsSensitivityOperationIcon, + value: 1, + description: 1.toString(), + ), + SceneOperationalValue( + icon: Assets.assetsSensitivityOperationIcon, + value: 2, + description: 2.toString(), + ), + SceneOperationalValue( + icon: Assets.assetsSensitivityOperationIcon, + value: 3, + description: 3.toString(), + ), + SceneOperationalValue( + icon: Assets.assetsSensitivityOperationIcon, + value: 4, + description: 4.toString(), + ), + SceneOperationalValue( + icon: Assets.assetsSensitivityOperationIcon, + value: 5, + description: 5.toString(), + ), + ], + ), + SceneStaticFunction( + deviceId: deviceId, + deviceName: deviceName, + icon: Assets.assetsMotionlessDetection, + operationName: 'Motionless Detection Sensitivity', + code: 'motionless_sensitivity', + operationalValues: [ + SceneOperationalValue( + iconValue: '1', + icon: Assets.assetsFarDetectionFunction, + value: 1, + description: '1', + ), + SceneOperationalValue( + icon: Assets.assetsFarDetectionFunction, + value: 2, + description: '2', + iconValue: '2', + ), + SceneOperationalValue( + icon: Assets.assetsFarDetectionFunction, + value: 3, + description: '3', + iconValue: '3', + ), + SceneOperationalValue( + icon: Assets.assetsFarDetectionFunction, + value: 4, + description: '4', + iconValue: '4', + ), + SceneOperationalValue( + icon: Assets.assetsFarDetectionFunction, + value: 5, + description: '5', + iconValue: '5', + ), + ], + ), + SceneStaticFunction( + deviceId: deviceId, + deviceName: deviceName, + icon: Assets.assetsIndicator, + operationName: 'Indicator', + code: 'indicator', + operationalValues: [ + SceneOperationalValue( + icon: Assets.assetsAcPower, description: "ON", value: true), + SceneOperationalValue( + icon: Assets.assetsAcPowerOFF, description: "OFF", value: false), + ], + ), + SceneStaticFunction( + deviceId: deviceId, + deviceName: deviceName, + icon: Assets.assetsNobodyTime, + operationName: 'Nobody Time', + code: 'presence_time', + operationalValues: [ + SceneOperationalValue(icon: '', value: 0), + ], + ), + ]; } List lightBulbFunctions( @@ -166,7 +334,53 @@ List gatewayFunctions( {required List functions, required String deviceId, required String deviceName}) { - return []; + return [ + SceneStaticFunction( + deviceId: deviceId, + deviceName: deviceName, + icon: Assets.assetsSwitchAlarmSound, + operationName: 'Switch Alarm Sound', + code: 'switch_alarm_sound', + operationalValues: [ + SceneOperationalValue( + icon: Assets.assetsAcPower, description: "ON", value: true), + SceneOperationalValue( + icon: Assets.assetsAcPowerOFF, description: "OFF", value: false), + ], + ), + SceneStaticFunction( + deviceId: deviceId, + deviceName: deviceName, + icon: Assets.assetsMasterState, + operationName: 'Master State', + code: 'master_state', + operationalValues: [ + SceneOperationalValue( + icon: Assets.assetsAcPower, + description: "Alarm", + value: 'alarm', + ), + SceneOperationalValue( + icon: Assets.assetsAcPowerOFF, + description: "Normal", + value: 'normal', + ), + ], + ), + SceneStaticFunction( + deviceId: deviceId, + deviceName: deviceName, + icon: Assets.assetsFactoryReset, + operationName: 'Factory Reset', + code: 'factory_reset', + operationalValues: [ + SceneOperationalValue( + icon: Assets.assetsSceneRefresh, description: "ON", value: true), + SceneOperationalValue( + icon: Assets.assetsResetOff, description: "OFF", value: false), + ], + ), + ]; } List threeGangFunctions( diff --git a/lib/features/scene/model/scene_static_function.dart b/lib/features/scene/model/scene_static_function.dart index 5b1e6dd..5a46da9 100644 --- a/lib/features/scene/model/scene_static_function.dart +++ b/lib/features/scene/model/scene_static_function.dart @@ -101,27 +101,36 @@ class SceneOperationalValue { final String icon; final dynamic value; final String? description; + final String? iconValue; SceneOperationalValue({ required this.icon, required this.value, this.description, + this.iconValue, }); SceneOperationalValue copyWith({ String? icon, dynamic value, String? description, + String? iconValue, }) { return SceneOperationalValue( icon: icon ?? this.icon, value: value ?? this.value, description: description ?? this.description, + iconValue: iconValue ?? this.iconValue, ); } Map toMap() { - return {'icon': icon, 'value': value, 'description': description}; + return { + 'icon': icon, + 'value': value, + 'description': description, + 'iconValue': iconValue + }; } factory SceneOperationalValue.fromMap(Map map) { @@ -129,6 +138,7 @@ class SceneOperationalValue { icon: map['icon'] ?? '', value: map['value'], description: map['description'], + iconValue: map['iconValue'] ?? '', ); } @@ -139,7 +149,7 @@ class SceneOperationalValue { @override String toString() => - 'StaticFunctionOperationHelper(icon: $icon, value: $value, description: $description)'; + 'StaticFunctionOperationHelper(icon: $icon, value: $value, description: $description, iconValue: $iconValue)'; @override bool operator ==(Object other) { @@ -148,9 +158,15 @@ class SceneOperationalValue { return other is SceneOperationalValue && other.icon == icon && other.description == description && + other.iconValue == iconValue && other.value == value; } @override - int get hashCode => icon.hashCode ^ value.hashCode ^ description.hashCode; + int get hashCode => + icon.hashCode ^ + value.hashCode ^ + description.hashCode ^ + iconValue.hashCode ^ + description.hashCode; } diff --git a/lib/features/scene/view/device_functions_view.dart b/lib/features/scene/view/device_functions_view.dart index 94d7f13..9a46756 100644 --- a/lib/features/scene/view/device_functions_view.dart +++ b/lib/features/scene/view/device_functions_view.dart @@ -97,7 +97,7 @@ class DeviceFunctionsView extends StatelessWidget BlocBuilder( builder: (context, state) { return SceneListTile( - iconsSize: 32, + iconsSize: 22, minLeadingWidth: 20, assetPath: functions[index].icon, titleString: functions[index].operationName, @@ -118,7 +118,12 @@ class DeviceFunctionsView extends StatelessWidget alertBody: functions[index].code == 'temp_set' ? AlertDialogTemperatureBody( index: index, functions: functions) - : functions[index].code.contains('countdown') + : (functions[index] + .code + .contains('countdown') || + functions[index] + .code + .contains('presence_time')) ? AlertDialogCountdown( durationValue: functions[index] .operationalValues diff --git a/lib/features/scene/view/scene_view.dart b/lib/features/scene/view/scene_view.dart index 56492bf..711c753 100644 --- a/lib/features/scene/view/scene_view.dart +++ b/lib/features/scene/view/scene_view.dart @@ -3,14 +3,11 @@ import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:syncrow_app/features/app_layout/bloc/home_cubit.dart'; import 'package:syncrow_app/features/scene/bloc/scene_bloc/scene_bloc.dart'; import 'package:syncrow_app/features/scene/bloc/scene_bloc/scene_event.dart'; +import 'package:syncrow_app/features/scene/widgets/scene_view_widget/scene_grid_view.dart'; +import 'package:syncrow_app/features/scene/widgets/scene_view_widget/scene_header.dart'; import 'package:syncrow_app/features/shared_widgets/create_unit.dart'; -import 'package:syncrow_app/features/shared_widgets/default_container.dart'; -import 'package:syncrow_app/features/shared_widgets/text_widgets/body_medium.dart'; -import 'package:syncrow_app/features/shared_widgets/text_widgets/body_small.dart'; -import 'package:syncrow_app/features/shared_widgets/text_widgets/title_medium.dart'; -import 'package:syncrow_app/generated/assets.dart'; -import 'package:syncrow_app/utils/resource_manager/color_manager.dart'; -import 'package:syncrow_app/utils/resource_manager/strings_manager.dart'; + +import 'package:syncrow_app/utils/context_extension.dart'; class SceneView extends StatelessWidget { const SceneView({super.key}); @@ -20,113 +17,48 @@ class SceneView extends StatelessWidget { return BlocProvider( create: (BuildContext context) => SceneBloc() ..add(LoadScenes(HomeCubit.getInstance().selectedSpace!.id!)), - child: HomeCubit.getInstance().spaces?.isEmpty ?? true - ? const CreateUnitWidget() - : Column( - mainAxisAlignment: MainAxisAlignment.start, - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - const TitleMedium( - text: StringsManager.routine, - style: TextStyle( - fontSize: 32, - fontWeight: FontWeight.bold, - ), - ), - const SizedBox(height: 20), - const BodySmall( - text: StringsManager.tapToRunRoutine, - ), - const SizedBox(height: 8), - BlocBuilder( - builder: (context, state) { - if (state is SceneLoading) { - return const Center( - child: CircularProgressIndicator(), - ); - } - if (state is SceneError) { - return Center( - child: Text(state.message), - ); - } - if (state is SceneLoaded) { - return Expanded( - child: GridView.builder( - shrinkWrap: true, - gridDelegate: - const SliverGridDelegateWithFixedCrossAxisCount( - crossAxisCount: 2, - mainAxisSpacing: 12, - crossAxisSpacing: 12, - childAspectRatio: 1.5, + child: BlocListener( + listener: (context, state) { + if (state is SceneTriggerSuccess) { + context.showCustomSnackbar( + message: 'Scene ${state.sceneName} triggered successfully!'); + } + }, + child: HomeCubit.getInstance().spaces?.isEmpty ?? true + ? const CreateUnitWidget() + : Column( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + const SceneHeader(), + const SizedBox(height: 8), + BlocBuilder( + builder: (context, state) { + if (state is SceneLoading) { + return const Center( + child: CircularProgressIndicator(), + ); + } + if (state is SceneError) { + return Center( + child: Text(state.message), + ); + } + if (state is SceneLoaded) { + return Expanded( + child: SceneGrid( + scenes: state.scenes, + loadingSceneId: state.loadingSceneId, ), - itemCount: state.scenes.length, - itemBuilder: (context, index) { - final scene = state.scenes[index]; - return DefaultContainer( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - crossAxisAlignment: - CrossAxisAlignment.center, - mainAxisAlignment: - MainAxisAlignment.spaceBetween, - children: [ - Image.asset( - height: 32, - width: 32, - Assets.assetsIconsLogo, - fit: BoxFit.fill, - ), - BlocBuilder( - builder: (context, state) { - return IconButton( - padding: EdgeInsets.zero, - onPressed: () { - // context - // .read() - // .add(SceneTrigger(scene.id)); - }, - icon: state is SceneTriggerLoading - ? const Center( - child: - CircularProgressIndicator()) - : const Icon( - Icons.play_circle, - size: 40, - color: - ColorsManager.greyColor, - ), - ); - }, - ) - ], - ), - const SizedBox( - height: 10, - ), - BodyMedium( - text: scene.name, - maxLines: 1, - overflow: TextOverflow.fade, - fontWeight: FontWeight.bold, - fontSize: 16, - ) - ], - ), - ); - }, - ), - ); - } + ); + } - return const SizedBox(); - }, - ), - ], - ), + return const SizedBox(); + }, + ), + ], + ), + ), ); } } diff --git a/lib/features/scene/widgets/alert_dialogs/alert_dialog_functions_body.dart b/lib/features/scene/widgets/alert_dialogs/alert_dialog_functions_body.dart index 07e1809..400dab1 100644 --- a/lib/features/scene/widgets/alert_dialogs/alert_dialog_functions_body.dart +++ b/lib/features/scene/widgets/alert_dialogs/alert_dialog_functions_body.dart @@ -36,6 +36,7 @@ class _AlertDialogFunctionsOperationsBodyState minLeadingWidth: 15, padding: const EdgeInsets.symmetric(horizontal: 16), assetPath: operation.icon, + assetHeaderValue: operation.iconValue, titleString: operation.description.toString(), textAlign: TextAlign.start, trailingWidget: Radio( diff --git a/lib/features/scene/widgets/scene_list_tile.dart b/lib/features/scene/widgets/scene_list_tile.dart index ea940aa..b97c977 100644 --- a/lib/features/scene/widgets/scene_list_tile.dart +++ b/lib/features/scene/widgets/scene_list_tile.dart @@ -22,6 +22,7 @@ class SceneListTile extends StatelessWidget { this.subtitleString, this.subtitleWidget, this.iconsSize, + this.assetHeaderValue, }); final String? assetPath; final String? titleString; @@ -36,6 +37,7 @@ class SceneListTile extends StatelessWidget { final double? minLeadingWidth; final Widget? titleWidget; final double? iconsSize; + final String? assetHeaderValue; @override Widget build(BuildContext context) { @@ -50,7 +52,7 @@ class SceneListTile extends StatelessWidget { width: iconsSize, height: assetHeight ?? 35, alignment: Alignment.center, - fit: BoxFit.contain, + fit: BoxFit.fitWidth, ), ) : null), diff --git a/lib/features/scene/widgets/scene_view_widget/scene_grid_view.dart b/lib/features/scene/widgets/scene_view_widget/scene_grid_view.dart new file mode 100644 index 0000000..00b3f5f --- /dev/null +++ b/lib/features/scene/widgets/scene_view_widget/scene_grid_view.dart @@ -0,0 +1,35 @@ +import 'package:flutter/material.dart'; + +import 'package:syncrow_app/features/scene/model/scene_model.dart'; +import 'package:syncrow_app/features/scene/widgets/scene_view_widget/scene_item.dart'; + +class SceneGrid extends StatelessWidget { + final List scenes; + final String? loadingSceneId; + + const SceneGrid({ + required this.scenes, + required this.loadingSceneId, + super.key, + }); + + @override + Widget build(BuildContext context) { + return GridView.builder( + shrinkWrap: true, + gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount( + crossAxisCount: 2, + mainAxisSpacing: 12, + crossAxisSpacing: 12, + childAspectRatio: 1.5, + ), + itemCount: scenes.length, + itemBuilder: (context, index) { + final scene = scenes[index]; + final isLoading = loadingSceneId == scene.id; + + return SceneItem(scene: scene, isLoading: isLoading); + }, + ); + } +} diff --git a/lib/features/scene/widgets/scene_view_widget/scene_header.dart b/lib/features/scene/widgets/scene_view_widget/scene_header.dart new file mode 100644 index 0000000..788c4c1 --- /dev/null +++ b/lib/features/scene/widgets/scene_view_widget/scene_header.dart @@ -0,0 +1,30 @@ +import 'package:flutter/material.dart'; + +import 'package:syncrow_app/features/shared_widgets/text_widgets/body_small.dart'; +import 'package:syncrow_app/features/shared_widgets/text_widgets/title_medium.dart'; + +import 'package:syncrow_app/utils/resource_manager/strings_manager.dart'; + +class SceneHeader extends StatelessWidget { + const SceneHeader({super.key}); + + @override + Widget build(BuildContext context) { + return const Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + TitleMedium( + text: StringsManager.routine, + style: TextStyle( + fontSize: 32, + fontWeight: FontWeight.bold, + ), + ), + SizedBox(height: 20), + BodySmall( + text: StringsManager.tapToRunRoutine, + ), + ], + ); + } +} diff --git a/lib/features/scene/widgets/scene_view_widget/scene_item.dart b/lib/features/scene/widgets/scene_view_widget/scene_item.dart new file mode 100644 index 0000000..861ddd9 --- /dev/null +++ b/lib/features/scene/widgets/scene_view_widget/scene_item.dart @@ -0,0 +1,69 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:syncrow_app/features/scene/bloc/scene_bloc/scene_bloc.dart'; +import 'package:syncrow_app/features/scene/bloc/scene_bloc/scene_event.dart'; +import 'package:syncrow_app/features/scene/model/scene_model.dart'; +import 'package:syncrow_app/features/shared_widgets/default_container.dart'; +import 'package:syncrow_app/features/shared_widgets/text_widgets/body_medium.dart'; + +import 'package:syncrow_app/generated/assets.dart'; +import 'package:syncrow_app/utils/resource_manager/color_manager.dart'; + +class SceneItem extends StatelessWidget { + final SceneModel scene; + final bool isLoading; + + const SceneItem({ + required this.scene, + required this.isLoading, + super.key, + }); + + @override + Widget build(BuildContext context) { + return DefaultContainer( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Image.asset( + height: 32, + width: 32, + Assets.assetsIconsLogo, + fit: BoxFit.fill, + ), + IconButton( + padding: EdgeInsets.zero, + onPressed: () { + context + .read() + .add(SceneTrigger(scene.id, scene.name)); + }, + icon: isLoading + ? const Center( + child: CircularProgressIndicator(), + ) + : const Icon( + Icons.play_circle, + size: 40, + color: ColorsManager.greyColor, + ), + ), + ], + ), + const SizedBox(height: 10), + BodyMedium( + text: scene.name, + maxLines: 1, + overflow: TextOverflow.fade, + fontWeight: FontWeight.bold, + fontSize: 16, + ), + ], + ), + ); + } +} diff --git a/lib/generated/assets.dart b/lib/generated/assets.dart index 7040c17..4f56667 100644 --- a/lib/generated/assets.dart +++ b/lib/generated/assets.dart @@ -853,8 +853,58 @@ class Assets { static const String assetsSceneRefresh = "assets/icons/functions_icons/scene_refresh.svg"; - //assets/icons/functions_icons/light_countdown.svg + //assets/icons/functions_icons/light_countdown.svg static const String assetsLightCountdown = "assets/icons/functions_icons/light_countdown.svg"; + + //assets/icons/functions_icons/far_detection.svg + + static const String assetsFarDetection = + "assets/icons/functions_icons/far_detection.svg"; + + //assets/icons/functions_icons/far_detection_function.svg + + static const String assetsFarDetectionFunction = + "assets/icons/functions_icons/far_detection_function.svg"; + + //assets/icons/functions_icons/indicator.svg + + static const String assetsIndicator = + "assets/icons/functions_icons/indicator.svg"; + + //assets/icons/functions_icons/motion_detection.svg + + static const String assetsMotionDetection = + "assets/icons/functions_icons/motion_detection.svg"; + + //assets/icons/functions_icons/motionless_detection.svg + + static const String assetsMotionlessDetection = + "assets/icons/functions_icons/motionless_detection.svg"; + + //assets/icons/functions_icons/nobody_time.svg + + static const String assetsNobodyTime = + "assets/icons/functions_icons/nobody_time.svg"; + + //assets/icons/functions_icons/factory_reset.svg + + static const String assetsFactoryReset = + "assets/icons/functions_icons/factory_reset.svg"; + + //assets/icons/functions_icons/master_state.svg + + static const String assetsMasterState = + "assets/icons/functions_icons/master_state.svg"; + + //assets/icons/functions_icons/switch_alarm_sound.svg + + static const String assetsSwitchAlarmSound = + "assets/icons/functions_icons/switch_alarm_sound.svg"; + + //assets/icons/functions_icons/reset_off.svg + + static const String assetsResetOff = + "assets/icons/functions_icons/reset_off.svg"; } diff --git a/lib/services/api/scene_api.dart b/lib/services/api/scene_api.dart index 1bf7b34..a97a744 100644 --- a/lib/services/api/scene_api.dart +++ b/lib/services/api/scene_api.dart @@ -45,7 +45,7 @@ class SceneApi { static Future triggerScene(String sceneId) async { try { final response = await _httpService.post( - path: ApiEndpoints.triggerScene.replaceAll('{sceneUuid}', sceneId), + path: ApiEndpoints.triggerScene.replaceAll('{sceneId}', sceneId), showServerMessage: false, expectedResponseModel: (json) => json['success'], );