diff --git a/assets/icons/check_update_icon.svg b/assets/icons/check_update_icon.svg
new file mode 100644
index 0000000..46527d3
--- /dev/null
+++ b/assets/icons/check_update_icon.svg
@@ -0,0 +1,22 @@
+
+
+
\ No newline at end of file
diff --git a/assets/icons/edit_sos_icon.svg b/assets/icons/edit_sos_icon.svg
new file mode 100644
index 0000000..c9e6a9e
--- /dev/null
+++ b/assets/icons/edit_sos_icon.svg
@@ -0,0 +1,4 @@
+
diff --git a/assets/icons/empty_log.svg b/assets/icons/empty_log.svg
new file mode 100644
index 0000000..8e847ac
--- /dev/null
+++ b/assets/icons/empty_log.svg
@@ -0,0 +1,16 @@
+
diff --git a/assets/icons/empty_update_icon.svg b/assets/icons/empty_update_icon.svg
new file mode 100644
index 0000000..3cf26c9
--- /dev/null
+++ b/assets/icons/empty_update_icon.svg
@@ -0,0 +1,9 @@
+
diff --git a/assets/icons/faq_icon.svg b/assets/icons/faq_icon.svg
new file mode 100644
index 0000000..394f26c
--- /dev/null
+++ b/assets/icons/faq_icon.svg
@@ -0,0 +1,3 @@
+
diff --git a/assets/icons/green_sos.svg b/assets/icons/green_sos.svg
new file mode 100644
index 0000000..da225aa
--- /dev/null
+++ b/assets/icons/green_sos.svg
@@ -0,0 +1,38 @@
+
diff --git a/assets/icons/info.svg b/assets/icons/info.svg
new file mode 100644
index 0000000..8aafa02
--- /dev/null
+++ b/assets/icons/info.svg
@@ -0,0 +1,10 @@
+
diff --git a/assets/icons/notification_icon.svg b/assets/icons/notification_icon.svg
new file mode 100644
index 0000000..ed3d9d0
--- /dev/null
+++ b/assets/icons/notification_icon.svg
@@ -0,0 +1,3 @@
+
diff --git a/assets/icons/red_sos.svg b/assets/icons/red_sos.svg
new file mode 100644
index 0000000..c2f6966
--- /dev/null
+++ b/assets/icons/red_sos.svg
@@ -0,0 +1,38 @@
+
diff --git a/assets/icons/share_icon.svg b/assets/icons/share_icon.svg
new file mode 100644
index 0000000..a4b908f
--- /dev/null
+++ b/assets/icons/share_icon.svg
@@ -0,0 +1,3 @@
+
diff --git a/assets/icons/sos_profile_icon.svg b/assets/icons/sos_profile_icon.svg
new file mode 100644
index 0000000..f99ec5b
--- /dev/null
+++ b/assets/icons/sos_profile_icon.svg
@@ -0,0 +1,6 @@
+
diff --git a/assets/icons/thumb_down.svg b/assets/icons/thumb_down.svg
new file mode 100644
index 0000000..4d22f00
--- /dev/null
+++ b/assets/icons/thumb_down.svg
@@ -0,0 +1,10 @@
+
diff --git a/assets/icons/thumb_up.svg b/assets/icons/thumb_up.svg
new file mode 100644
index 0000000..5670b79
--- /dev/null
+++ b/assets/icons/thumb_up.svg
@@ -0,0 +1,10 @@
+
diff --git a/assets/icons/update_icon.svg b/assets/icons/update_icon.svg
new file mode 100644
index 0000000..cf3e305
--- /dev/null
+++ b/assets/icons/update_icon.svg
@@ -0,0 +1,3 @@
+
diff --git a/lib/features/devices/bloc/sos_bloc/sos_bloc.dart b/lib/features/devices/bloc/sos_bloc/sos_bloc.dart
new file mode 100644
index 0000000..17c782a
--- /dev/null
+++ b/lib/features/devices/bloc/sos_bloc/sos_bloc.dart
@@ -0,0 +1,259 @@
+import 'dart:async';
+import 'package:dio/dio.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter_bloc/flutter_bloc.dart';
+import 'package:syncrow_app/features/devices/bloc/sos_bloc/sos_event.dart';
+import 'package:syncrow_app/features/devices/bloc/sos_bloc/sos_state.dart';
+import 'package:syncrow_app/features/devices/model/device_control_model.dart';
+import 'package:syncrow_app/features/devices/model/device_model.dart';
+import 'package:syncrow_app/features/devices/model/device_report_model.dart';
+import 'package:syncrow_app/features/devices/model/question_model.dart';
+import 'package:syncrow_app/features/devices/model/sos_model.dart';
+import 'package:syncrow_app/features/devices/model/status_model.dart';
+import 'package:syncrow_app/features/devices/model/subspace_model.dart';
+import 'package:syncrow_app/services/api/devices_api.dart';
+import 'package:syncrow_app/services/api/spaces_api.dart';
+
+class SosBloc extends Bloc {
+ final String sosId;
+ SosBloc({
+ required this.sosId,
+ }) : super(const SosState()) {
+ on(_fetchStatus);
+ on(fetchLogsForLastMonth);
+ on(_toggleLowBattery);
+ on(_toggleClosingReminder);
+ on(_changeName);
+ on(_onSearchFaq);
+ on(_onSosInitial);
+ on(_fetchRoomsAndDevices);
+ on(_onOptionSelected);
+ on(_onSaveSelection);
+ // on(_toggleWaterLeakAlarm);
+ }
+
+ final TextEditingController nameController =
+ TextEditingController(text: '${'firstName'}');
+ bool isSaving = false;
+ bool editName = false;
+ final FocusNode focusNode = FocusNode();
+ Timer? _timer;
+ bool enableAlarm = false;
+ bool closingReminder = false;
+ bool waterAlarm = false;
+ SosModel deviceStatus =
+ SosModel(waterContactState: 'normal', batteryPercentage: 0);
+
+ void _fetchStatus(SosInitial event, Emitter emit) async {
+ emit(SosLoadingState());
+ try {
+ var response = await DevicesAPI.getDeviceStatus(sosId);
+ List statusModelList = [];
+ for (var status in response['status']) {
+ statusModelList.add(StatusModel.fromJson(status));
+ }
+ deviceStatus = SosModel.fromJson(
+ statusModelList,
+ );
+ emit(UpdateState(sensor: deviceStatus));
+
+ Future.delayed(const Duration(milliseconds: 500));
+ // _listenToChanges();
+ } catch (e) {
+ emit(SosFailedState(errorMessage: e.toString()));
+ return;
+ }
+ }
+
+ void _onSearchFaq(SearchFaqEvent event, Emitter emit) {
+ emit(SosLoadingState());
+ List _faqQuestions = faqQuestions.where((question) {
+ return question.question
+ .toLowerCase()
+ .contains(event.query.toLowerCase());
+ }).toList();
+ emit(FaqSearchState(filteredFaqQuestions: _faqQuestions));
+ }
+
+ void _changeName(ChangeNameEvent event, Emitter emit) {
+ emit(SosLoadingState());
+ editName = event.value!;
+ if (editName) {
+ Future.delayed(const Duration(milliseconds: 500), () {
+ focusNode.requestFocus();
+ });
+ } else {
+ focusNode.unfocus();
+ }
+ emit(NameEditingState(editName: editName));
+ }
+
+ void _toggleLowBattery(
+ ToggleEnableAlarmEvent event, Emitter emit) async {
+ emit(LoadingNewSate(sosSensor: deviceStatus));
+ try {
+ enableAlarm = event.isLowBatteryEnabled;
+ emit(UpdateState(sensor: deviceStatus));
+ await DevicesAPI.controlDevice(
+ DeviceControlModel(
+ deviceId: sosId,
+ code: 'low_battery',
+ value: enableAlarm,
+ ),
+ sosId,
+ );
+ } catch (e) {
+ emit(SosFailedState(errorMessage: e.toString()));
+ }
+ }
+
+ void _toggleClosingReminder(
+ ToggleClosingReminderEvent event, Emitter emit) async {
+ emit(LoadingNewSate(sosSensor: deviceStatus));
+ try {
+ closingReminder = event.isClosingReminderEnabled;
+ emit(UpdateState(sensor: deviceStatus));
+
+ // API call to update the state, if necessary
+ // await DevicesAPI.controlDevice(
+ // DeviceControlModel(
+ // deviceId: sosId,
+ // code: 'closing_reminder',
+ // value: closingReminder,
+ // ),
+ // sosId,
+ // );
+ } catch (e) {
+ emit(SosFailedState(errorMessage: e.toString()));
+ }
+ }
+
+ DeviceReport recordGroups =
+ DeviceReport(startTime: '0', endTime: '0', data: []);
+
+ Future fetchLogsForLastMonth(
+ ReportLogsInitial event, Emitter emit) async {
+ DateTime now = DateTime.now();
+ DateTime lastMonth = DateTime(now.year, now.month - 1, now.day);
+ int startTime = lastMonth.millisecondsSinceEpoch;
+ int endTime = now.millisecondsSinceEpoch;
+ try {
+ emit(SosLoadingState());
+ var response = await DevicesAPI.getReportLogs(
+ startTime: startTime.toString(),
+ endTime: endTime.toString(),
+ deviceUuid: sosId,
+ code: 'sossensor_state',
+ );
+ recordGroups = response;
+ emit(UpdateState(sensor: deviceStatus));
+ } on DioException catch (e) {
+ final errorData = e.response!.data;
+ String errorMessage = errorData['message'];
+ emit(SosFailedState(errorMessage: e.toString()));
+ }
+ }
+
+ // _listenToChanges() {
+ // try {
+ // DatabaseReference ref =
+ // FirebaseDatabase.instance.ref('device-status/$WLId');
+ // Stream stream = ref.onValue;
+
+ // stream.listen((DatabaseEvent event) async {
+ // if (_timer != null) {
+ // await Future.delayed(const Duration(seconds: 2));
+ // }
+ // Map usersMap =
+ // event.snapshot.value as Map;
+ // List statusList = [];
+
+ // usersMap['status'].forEach((element) {
+ // statusList.add(StatusModel(code: element['code'], value: true));
+ // });
+
+ // deviceStatus = WaterLeakModel.fromJson(statusList);
+ // if (!isClosed) {
+ // add(
+ // WaterLeakSwitch(switchD: deviceStatus.waterContactState),
+ // );
+ // }
+ // });
+ // } catch (_) {}
+ // }
+
+ // Demo list of FAQ questions using the QuestionModel class
+ final List faqQuestions = [
+ QuestionModel(
+ id: 1,
+ question: 'How does an SOS emergency button work?',
+ answer:
+ 'The SOS emergency button sends an alert to your contacts when pressed.',
+ ),
+ QuestionModel(
+ id: 2,
+ question: 'How long will an SOS alarm persist?',
+ answer:
+ 'The SOS alarm will persist until it is manually turned off or after a set time.',
+ ),
+ QuestionModel(
+ id: 3,
+ question: 'What should I do if the SOS button is unresponsive?',
+ answer: 'Try restarting the device. If it persists, contact support.',
+ ),
+ QuestionModel(
+ id: 4,
+ question: 'Can I use the SOS feature without a network connection?',
+ answer:
+ 'No, a network connection is required to send the alert to your contacts.',
+ ),
+ QuestionModel(
+ id: 5,
+ question: 'How often should I check the SOS battery?',
+ answer:
+ 'Check the SOS battery at least once a month to ensure it is operational.',
+ ),
+ ];
+ Future _onSosInitial(
+ SosInitialQuestion event, Emitter emit) async {
+ emit(SosLoadingState());
+ // SosModel sosModel = await fetchSosData(sosId); // Define this function as needed
+ emit(FaqLoadedState(filteredFaqQuestions: faqQuestions));
+ }
+
+ List allDevices = [];
+ List roomsList = [];
+
+ void _fetchRoomsAndDevices(
+ FetchRoomsEvent event, Emitter emit) async {
+ try {
+ emit(SosLoadingState());
+ roomsList = await SpacesAPI.getSubSpaceBySpaceId(
+ event.unit.community.uuid, event.unit.id);
+ emit(FetchRoomsState(devicesList: allDevices, roomsList: roomsList));
+ } catch (e) {
+ emit(const SosFailedState(errorMessage: 'Something went wrong'));
+ return;
+ }
+ }
+
+ String _selectedOption = '';
+ bool _hasSelectionChanged = false;
+
+ void _onOptionSelected(SelectOptionEvent event, Emitter emit) {
+ emit(SosLoadingState());
+ _selectedOption = event.selectedOption;
+ _hasSelectionChanged = true;
+ emit(OptionSelectedState(
+ selectedOption: _selectedOption,
+ hasSelectionChanged: _hasSelectionChanged));
+ }
+
+ void _onSaveSelection(SaveSelectionEvent event, Emitter emit) {
+ if (_hasSelectionChanged) {
+ print('Save button clicked with selected option: $_selectedOption');
+ _hasSelectionChanged = false;
+ emit(SaveSelectionSuccessState());
+ }
+ }
+}
diff --git a/lib/features/devices/bloc/sos_bloc/sos_event.dart b/lib/features/devices/bloc/sos_bloc/sos_event.dart
new file mode 100644
index 0000000..62d83c3
--- /dev/null
+++ b/lib/features/devices/bloc/sos_bloc/sos_event.dart
@@ -0,0 +1,129 @@
+import 'package:equatable/equatable.dart';
+import 'package:syncrow_app/features/app_layout/model/space_model.dart';
+
+abstract class SosEvent extends Equatable {
+ const SosEvent();
+
+ @override
+ List