From 0fc709a5b16e54d105e5dfd78ac7cb2e3d8d613f Mon Sep 17 00:00:00 2001 From: ashrafzarkanisala Date: Thu, 31 Oct 2024 11:32:34 +0300 Subject: [PATCH] push sos basic device implementation --- assets/icons/sos.svg | 23 +++ assets/icons/sos_normal.svg | 23 +++ .../helper/route_controls_based_code.dart | 93 ++++-------- .../sos/bloc/sos_device_bloc.dart | 74 ++++++++++ .../sos/bloc/sos_device_event.dart | 39 +++++ .../sos/bloc/sos_device_state.dart | 82 +++++++++++ .../sos/models/sos_status_model.dart | 34 +++++ .../sos/view/sos_batch_control_view.dart | 15 ++ .../sos/view/sos_device_control_view.dart | 137 ++++++++++++++++++ lib/utils/constants/assets.dart | 24 +-- 10 files changed, 464 insertions(+), 80 deletions(-) create mode 100644 assets/icons/sos.svg create mode 100644 assets/icons/sos_normal.svg create mode 100644 lib/pages/device_managment/sos/bloc/sos_device_bloc.dart create mode 100644 lib/pages/device_managment/sos/bloc/sos_device_event.dart create mode 100644 lib/pages/device_managment/sos/bloc/sos_device_state.dart create mode 100644 lib/pages/device_managment/sos/models/sos_status_model.dart create mode 100644 lib/pages/device_managment/sos/view/sos_batch_control_view.dart create mode 100644 lib/pages/device_managment/sos/view/sos_device_control_view.dart diff --git a/assets/icons/sos.svg b/assets/icons/sos.svg new file mode 100644 index 00000000..887e9f19 --- /dev/null +++ b/assets/icons/sos.svg @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/icons/sos_normal.svg b/assets/icons/sos_normal.svg new file mode 100644 index 00000000..ea795024 --- /dev/null +++ b/assets/icons/sos_normal.svg @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/lib/pages/device_managment/all_devices/helper/route_controls_based_code.dart b/lib/pages/device_managment/all_devices/helper/route_controls_based_code.dart index 8edb0a1e..85ecf7b6 100644 --- a/lib/pages/device_managment/all_devices/helper/route_controls_based_code.dart +++ b/lib/pages/device_managment/all_devices/helper/route_controls_based_code.dart @@ -20,6 +20,8 @@ import 'package:syncrow_web/pages/device_managment/one_gang_switch/view/wall_lig import 'package:syncrow_web/pages/device_managment/one_gang_switch/view/wall_light_device_control.dart'; import 'package:syncrow_web/pages/device_managment/power_clamp/view/power_clamp_batch_control_view.dart'; import 'package:syncrow_web/pages/device_managment/power_clamp/view/smart_power_device_control.dart'; +import 'package:syncrow_web/pages/device_managment/sos/view/sos_batch_control_view.dart'; +import 'package:syncrow_web/pages/device_managment/sos/view/sos_device_control_view.dart'; import 'package:syncrow_web/pages/device_managment/three_g_glass_switch/view/three_gang_glass_switch_batch_control_view.dart'; import 'package:syncrow_web/pages/device_managment/three_g_glass_switch/view/three_gang_glass_switch_control_view.dart'; import 'package:syncrow_web/pages/device_managment/three_gang_switch/view/living_room_batch_controls.dart'; @@ -100,6 +102,8 @@ mixin RouteControlsBasedCode { return SmartPowerDeviceControl( deviceId: device.uuid!, ); + case 'SOS': + return SosDeviceControlsView(device: device); default: return const SizedBox(); } @@ -123,119 +127,72 @@ mixin RouteControlsBasedCode { switch (devices.first.productType) { case '1G': return WallLightBatchControlView( - deviceIds: devices - .where((e) => (e.productType == '1G')) - .map((e) => e.uuid!) - .toList(), + deviceIds: devices.where((e) => (e.productType == '1G')).map((e) => e.uuid!).toList(), ); case '2G': return TwoGangBatchControlView( - deviceIds: devices - .where((e) => (e.productType == '2G')) - .map((e) => e.uuid!) - .toList(), + deviceIds: devices.where((e) => (e.productType == '2G')).map((e) => e.uuid!).toList(), ); case '3G': return LivingRoomBatchControlsView( - deviceIds: devices - .where((e) => (e.productType == '3G')) - .map((e) => e.uuid!) - .toList(), + deviceIds: devices.where((e) => (e.productType == '3G')).map((e) => e.uuid!).toList(), ); case '1GT': return OneGangGlassSwitchBatchControlView( - deviceIds: devices - .where((e) => (e.productType == '1GT')) - .map((e) => e.uuid!) - .toList(), + deviceIds: devices.where((e) => (e.productType == '1GT')).map((e) => e.uuid!).toList(), ); case '2GT': return TwoGangGlassSwitchBatchControlView( - deviceIds: devices - .where((e) => (e.productType == '2GT')) - .map((e) => e.uuid!) - .toList(), + deviceIds: devices.where((e) => (e.productType == '2GT')).map((e) => e.uuid!).toList(), ); case '3GT': return ThreeGangGlassSwitchBatchControlView( - deviceIds: devices - .where((e) => (e.productType == '3GT')) - .map((e) => e.uuid!) - .toList(), + deviceIds: devices.where((e) => (e.productType == '3GT')).map((e) => e.uuid!).toList(), ); case 'GW': return GatewayBatchControlView( - gatewayIds: devices - .where((e) => (e.productType == 'GW')) - .map((e) => e.uuid!) - .toList(), + gatewayIds: devices.where((e) => (e.productType == 'GW')).map((e) => e.uuid!).toList(), ); case 'DL': return DoorLockBatchControlView( - devicesIds: devices - .where((e) => (e.productType == 'DL')) - .map((e) => e.uuid!) - .toList()); + devicesIds: devices.where((e) => (e.productType == 'DL')).map((e) => e.uuid!).toList()); case 'WPS': return WallSensorBatchControlView( - devicesIds: devices - .where((e) => (e.productType == 'WPS')) - .map((e) => e.uuid!) - .toList()); + devicesIds: devices.where((e) => (e.productType == 'WPS')).map((e) => e.uuid!).toList()); case 'CPS': return CeilingSensorBatchControlView( - devicesIds: devices - .where((e) => (e.productType == 'CPS')) - .map((e) => e.uuid!) - .toList(), + devicesIds: devices.where((e) => (e.productType == 'CPS')).map((e) => e.uuid!).toList(), ); case 'CUR': return CurtainBatchStatusView( - devicesIds: devices - .where((e) => (e.productType == 'CUR')) - .map((e) => e.uuid!) - .toList(), + devicesIds: devices.where((e) => (e.productType == 'CUR')).map((e) => e.uuid!).toList(), ); case 'AC': return AcDeviceBatchControlView( - devicesIds: devices - .where((e) => (e.productType == 'AC')) - .map((e) => e.uuid!) - .toList()); + devicesIds: devices.where((e) => (e.productType == 'AC')).map((e) => e.uuid!).toList()); case 'WH': return WaterHEaterBatchControlView( - deviceIds: devices - .where((e) => (e.productType == 'WH')) - .map((e) => e.uuid!) - .toList(), + deviceIds: devices.where((e) => (e.productType == 'WH')).map((e) => e.uuid!).toList(), ); case 'DS': return MainDoorSensorBatchView( - devicesIds: devices - .where((e) => (e.productType == 'DS')) - .map((e) => e.uuid!) - .toList(), + devicesIds: devices.where((e) => (e.productType == 'DS')).map((e) => e.uuid!).toList(), ); case 'GD': return GarageDoorBatchControlView( - deviceIds: devices - .where((e) => (e.productType == 'GD')) - .map((e) => e.uuid!) - .toList(), + deviceIds: devices.where((e) => (e.productType == 'GD')).map((e) => e.uuid!).toList(), ); case 'WL': return WaterLeakBatchControlView( - deviceIds: devices - .where((e) => (e.productType == 'WL')) - .map((e) => e.uuid!) - .toList(), + deviceIds: devices.where((e) => (e.productType == 'WL')).map((e) => e.uuid!).toList(), ); case 'PC': return PowerClampBatchControlView( - deviceIds: devices - .where((e) => (e.productType == 'PC')) - .map((e) => e.uuid!) - .toList(), + deviceIds: devices.where((e) => (e.productType == 'PC')).map((e) => e.uuid!).toList(), + ); + case 'SOS': + return SOSBatchControlView( + deviceIds: devices.where((e) => (e.productType == 'sos')).map((e) => e.uuid!).toList(), ); default: return const SizedBox(); diff --git a/lib/pages/device_managment/sos/bloc/sos_device_bloc.dart b/lib/pages/device_managment/sos/bloc/sos_device_bloc.dart new file mode 100644 index 00000000..e9ed6899 --- /dev/null +++ b/lib/pages/device_managment/sos/bloc/sos_device_bloc.dart @@ -0,0 +1,74 @@ +import 'dart:async'; + +import 'package:bloc/bloc.dart'; +import 'package:equatable/equatable.dart'; +import 'package:syncrow_web/pages/device_managment/all_devices/models/device_reports.dart'; +import 'package:syncrow_web/pages/device_managment/sos/models/sos_status_model.dart'; +import 'package:syncrow_web/services/devices_mang_api.dart'; + +part 'sos_device_event.dart'; +part 'sos_device_state.dart'; + +class SosDeviceBloc extends Bloc { + SosDeviceBloc() : super(SosDeviceInitial()) { + on(_getDeviceStatus); + on(_getBatchStatus); + on(_getDeviceRecords); + on(_getDeviceAutomationRecords); + on(_backToSosStatusView); + } + + late SosStatusModel deviceStatus; + + FutureOr _getDeviceStatus(GetDeviceStatus event, Emitter emit) async { + emit(SosDeviceLoadingState()); + try { + final status = await DevicesManagementApi().getDeviceStatus(event.uuid); + deviceStatus = SosStatusModel.fromJson(event.uuid, status.status); + emit(SosDeviceLoadedState(deviceStatus)); + } catch (e) { + emit(SosDeviceErrorState(e.toString())); + } + } + + FutureOr _getBatchStatus(GetBatchStatus event, Emitter emit) async { + emit(SosDeviceLoadingState()); + try { + final status = await DevicesManagementApi().getBatchStatus(event.uuids); + deviceStatus = SosStatusModel.fromJson(event.uuids.first, status.status); + emit(SosDeviceLoadedState(deviceStatus)); + } catch (e) { + emit(SosDeviceErrorState(e.toString())); + } + } + + FutureOr _getDeviceRecords(GetDeviceRecords event, Emitter emit) async { + emit(SosReportLoadingState()); + try { + final from = DateTime.now().subtract(const Duration(days: 30)).millisecondsSinceEpoch; + final to = DateTime.now().millisecondsSinceEpoch; + final DeviceReport records = + await DevicesManagementApi.getDeviceReportsByDate(event.uuid, 'sos', from.toString(), to.toString()); + emit(SosReportLoadedState(records)); + } catch (e) { + emit(SosReportErrorState(e.toString())); + } + } + + FutureOr _getDeviceAutomationRecords(GetDeviceAutomationRecords event, Emitter emit) async { + emit(SosAutomationReportLoadingState()); + try { + final from = DateTime.now().subtract(const Duration(days: 30)).millisecondsSinceEpoch; + final to = DateTime.now().millisecondsSinceEpoch; + final DeviceReport records = await DevicesManagementApi.getDeviceReportsByDate( + event.uuid, 'sos_automation', from.toString(), to.toString()); + emit(SosAutomationReportLoadedState(records)); + } catch (e) { + emit(SosAutomationReportErrorState(e.toString())); + } + } + + FutureOr _backToSosStatusView(BackToSosStatusView event, Emitter emit) { + emit(SosDeviceLoadedState(deviceStatus)); + } +} diff --git a/lib/pages/device_managment/sos/bloc/sos_device_event.dart b/lib/pages/device_managment/sos/bloc/sos_device_event.dart new file mode 100644 index 00000000..c8bb28aa --- /dev/null +++ b/lib/pages/device_managment/sos/bloc/sos_device_event.dart @@ -0,0 +1,39 @@ +part of 'sos_device_bloc.dart'; + +sealed class SosDeviceEvent extends Equatable { + const SosDeviceEvent(); +} + +class GetDeviceStatus extends SosDeviceEvent { + final String uuid; + const GetDeviceStatus(this.uuid); + @override + List get props => [uuid]; +} + +class GetBatchStatus extends SosDeviceEvent { + final List uuids; + const GetBatchStatus(this.uuids); + @override + List get props => [uuids]; +} + +class GetDeviceRecords extends SosDeviceEvent { + final String uuid; + + const GetDeviceRecords(this.uuid); + @override + List get props => [uuid]; +} + +class GetDeviceAutomationRecords extends SosDeviceEvent { + final String uuid; + const GetDeviceAutomationRecords(this.uuid); + @override + List get props => [uuid]; +} + +class BackToSosStatusView extends SosDeviceEvent { + @override + List get props => []; +} diff --git a/lib/pages/device_managment/sos/bloc/sos_device_state.dart b/lib/pages/device_managment/sos/bloc/sos_device_state.dart new file mode 100644 index 00000000..b6a1eeec --- /dev/null +++ b/lib/pages/device_managment/sos/bloc/sos_device_state.dart @@ -0,0 +1,82 @@ +part of 'sos_device_bloc.dart'; + +sealed class SosDeviceState extends Equatable { + const SosDeviceState(); +} + +final class SosDeviceInitial extends SosDeviceState { + @override + List get props => []; +} + +final class SosDeviceLoadingState extends SosDeviceState { + @override + List get props => []; +} + +final class SosDeviceLoadedState extends SosDeviceState { + final SosStatusModel sosStatusModel; + + const SosDeviceLoadedState(this.sosStatusModel); + + @override + List get props => [sosStatusModel]; +} + +final class SosDeviceErrorState extends SosDeviceState { + final String message; + + const SosDeviceErrorState(this.message); + + @override + List get props => [message]; +} + +/// report state +final class SosReportLoadingState extends SosDeviceState { + @override + List get props => []; +} + +final class SosReportLoadedState extends SosDeviceState { + final DeviceReport sosReport; + + const SosReportLoadedState(this.sosReport); + + @override + List get props => [sosReport]; +} + +final class SosReportErrorState extends SosDeviceState { + final String message; + + const SosReportErrorState(this.message); + + @override + List get props => [message]; +} + +/// automation reports + +final class SosAutomationReportLoadingState extends SosDeviceState { + @override + List get props => []; +} + +final class SosAutomationReportLoadedState extends SosDeviceState { + final DeviceReport automationReport; + + const SosAutomationReportLoadedState(this.automationReport); + + @override + List get props => [automationReport]; +} + +final class SosAutomationReportErrorState extends SosDeviceState { + final String message; + + const SosAutomationReportErrorState(this.message); + + @override + List get props => [message]; +} diff --git a/lib/pages/device_managment/sos/models/sos_status_model.dart b/lib/pages/device_managment/sos/models/sos_status_model.dart new file mode 100644 index 00000000..ac0de3b0 --- /dev/null +++ b/lib/pages/device_managment/sos/models/sos_status_model.dart @@ -0,0 +1,34 @@ +import 'package:syncrow_web/pages/device_managment/all_devices/models/device_status.dart'; + +class SosStatusModel { + final int batteryLevel; + final String sosStatus; + final String deviceId; + + SosStatusModel({ + required this.batteryLevel, + required this.sosStatus, + required this.deviceId, + }); + + factory SosStatusModel.fromJson(String deviceId, List statuses) { + late int batteryLevel; + late String sosStatus; + + for (var status in statuses) { + switch (status.code) { + case 'battery_percentage': + batteryLevel = status.value; + break; + case 'sos': + sosStatus = status.value; + break; + } + } + return SosStatusModel( + deviceId: deviceId, + batteryLevel: batteryLevel, + sosStatus: sosStatus, + ); + } +} diff --git a/lib/pages/device_managment/sos/view/sos_batch_control_view.dart b/lib/pages/device_managment/sos/view/sos_batch_control_view.dart new file mode 100644 index 00000000..dd378b06 --- /dev/null +++ b/lib/pages/device_managment/sos/view/sos_batch_control_view.dart @@ -0,0 +1,15 @@ +import 'package:flutter/material.dart'; + +class SOSBatchControlView extends StatelessWidget { + const SOSBatchControlView({ + super.key, + required this.deviceIds, + }); + + final List deviceIds; + + @override + Widget build(BuildContext context) { + return const Placeholder(); + } +} diff --git a/lib/pages/device_managment/sos/view/sos_device_control_view.dart b/lib/pages/device_managment/sos/view/sos_device_control_view.dart new file mode 100644 index 00000000..0461f4cf --- /dev/null +++ b/lib/pages/device_managment/sos/view/sos_device_control_view.dart @@ -0,0 +1,137 @@ +// sos device control view + +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:syncrow_web/pages/device_managment/all_devices/models/devices_model.dart'; +import 'package:syncrow_web/pages/device_managment/main_door_sensor/view/main_door_control_view.dart'; +import 'package:syncrow_web/pages/device_managment/shared/table/report_table.dart'; +import 'package:syncrow_web/pages/device_managment/sos/bloc/sos_device_bloc.dart'; +import 'package:syncrow_web/utils/color_manager.dart'; +import 'package:syncrow_web/utils/constants/assets.dart'; +import 'package:syncrow_web/utils/helpers/responsice_layout_helper/responsive_layout_helper.dart'; + +import '../models/sos_status_model.dart'; + +class SosDeviceControlsView extends StatelessWidget with HelperResponsiveLayout { + const SosDeviceControlsView({ + super.key, + required this.device, + }); + + final AllDevicesModel device; + + @override + Widget build(BuildContext context) { + return BlocProvider( + create: (context) => SosDeviceBloc()..add(GetDeviceStatus(device.uuid!)), + child: BlocBuilder( + builder: (context, state) { + if (state is SosDeviceLoadingState) { + return const Center(child: CircularProgressIndicator()); + } else if (state is SosDeviceLoadedState) { + return _buildStatusControls(context, state.sosStatusModel); + } else if (state is SosReportLoadedState) { + return ReportsTable( + report: state.sosReport, + hideValueShowDescription: true, + garageDoorSensor: true, + onRowTap: (index) {}, + onClose: () { + context.read().add(BackToSosStatusView()); + }, + ); + } else if (state is SosAutomationReportLoadedState) { + return ReportsTable( + report: state.automationReport, + hideValueShowDescription: true, + garageDoorSensor: true, + onRowTap: (index) {}, + onClose: () { + context.read().add(BackToSosStatusView()); + }, + ); + } else if (state is SosDeviceErrorState) { + return const Center(child: Text('Error fetching status')); + } else if (state is SosAutomationReportErrorState) { + return Center(child: Text('Error: ${state.message.toString()}')); + } else if (state is SosReportErrorState) { + return Center(child: Text('Error: ${state.message.toString()}')); + } + return const Center(child: CircularProgressIndicator()); + }, + )); + } + + Widget _buildStatusControls(BuildContext context, SosStatusModel deviceStatus) { + final isExtraLarge = isExtraLargeScreenSize(context); + final isLarge = isLargeScreenSize(context); + final isMedium = isMediumScreenSize(context); + return GridView( + padding: const EdgeInsets.symmetric(horizontal: 50), + shrinkWrap: true, + physics: const NeverScrollableScrollPhysics(), + gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( + crossAxisCount: isLarge || isExtraLarge + ? 3 + : isMedium + ? 2 + : 1, + mainAxisExtent: 140, + crossAxisSpacing: 12, + mainAxisSpacing: 12, + ), + children: [ + IconNameStatusContainer( + isFullIcon: false, + name: deviceStatus.sosStatus == 'sos' ? 'SOS' : 'normal', + icon: deviceStatus.sosStatus == 'sos' ? Assets.sos : Assets.sosNormal, + onTap: () {}, + status: false, + textColor: ColorsManager.blackColor, + ), + IconNameStatusContainer( + isFullIcon: false, + name: 'SOS Records', + icon: Assets.records, + onTap: () { + context.read().add( + GetDeviceRecords( + device.uuid!, + ), + ); + }, + status: false, + textColor: ColorsManager.blackColor, + ), + IconNameStatusContainer( + isFullIcon: false, + name: 'Automation Record', + icon: Assets.automationRecords, + onTap: () { + context.read().add( + GetDeviceAutomationRecords( + device.uuid!, + ), + ); + }, + status: false, + textColor: ColorsManager.blackColor, + ), + IconNameStatusContainer( + isFullIcon: false, + name: 'Alarm Settings', + icon: Assets.mainDoorNotifi, + onTap: () { + // showDialog( + // context: context, + // builder: (context) => const NotificationDialog(), + // ); + }, + status: false, + textColor: ColorsManager.blackColor, + paddingAmount: 14, + ), + ], + ); + } +} diff --git a/lib/utils/constants/assets.dart b/lib/utils/constants/assets.dart index 168d8f43..dad9b261 100644 --- a/lib/utils/constants/assets.dart +++ b/lib/utils/constants/assets.dart @@ -60,29 +60,23 @@ class Assets { static const String nobodyTime = "assets/icons/nobody_time.svg"; // Automation functions - static const String tempPasswordUnlock = - "assets/icons/automation_functions/temp_password_unlock.svg"; - static const String doorlockNormalOpen = - "assets/icons/automation_functions/doorlock_normal_open.svg"; + static const String tempPasswordUnlock = "assets/icons/automation_functions/temp_password_unlock.svg"; + static const String doorlockNormalOpen = "assets/icons/automation_functions/doorlock_normal_open.svg"; static const String doorbell = "assets/icons/automation_functions/doorbell.svg"; - static const String remoteUnlockViaApp = - "assets/icons/automation_functions/remote_unlock_via_app.svg"; + static const String remoteUnlockViaApp = "assets/icons/automation_functions/remote_unlock_via_app.svg"; static const String doubleLock = "assets/icons/automation_functions/double_lock.svg"; static const String selfTestResult = "assets/icons/automation_functions/self_test_result.svg"; static const String lockAlarm = "assets/icons/automation_functions/lock_alarm.svg"; static const String presenceState = "assets/icons/automation_functions/presence_state.svg"; static const String currentTemp = "assets/icons/automation_functions/current_temp.svg"; static const String presence = "assets/icons/automation_functions/presence.svg"; - static const String residualElectricity = - "assets/icons/automation_functions/residual_electricity.svg"; + static const String residualElectricity = "assets/icons/automation_functions/residual_electricity.svg"; static const String hijackAlarm = "assets/icons/automation_functions/hijack_alarm.svg"; static const String passwordUnlock = "assets/icons/automation_functions/password_unlock.svg"; - static const String remoteUnlockRequest = - "assets/icons/automation_functions/remote_unlock_req.svg"; + static const String remoteUnlockRequest = "assets/icons/automation_functions/remote_unlock_req.svg"; static const String cardUnlock = "assets/icons/automation_functions/card_unlock.svg"; static const String motion = "assets/icons/automation_functions/motion.svg"; - static const String fingerprintUnlock = - "assets/icons/automation_functions/fingerprint_unlock.svg"; + static const String fingerprintUnlock = "assets/icons/automation_functions/fingerprint_unlock.svg"; // Presence Sensor Assets static const String sensorMotionIcon = "assets/icons/sensor_motion_ic.svg"; @@ -192,4 +186,10 @@ class Assets { //assets/icons/logo_grey.svg static const String logoGrey = 'assets/icons/logo-grey.svg'; + + //assets/icons/sos.svg + static const String sos = 'assets/icons/sos.svg'; + + //assets/icons/sos_normal.svg + static const String sosNormal = 'assets/icons/sos_normal.svg'; }