diff --git a/.vscode/settings.json b/.vscode/settings.json
new file mode 100644
index 0000000..c169a71
--- /dev/null
+++ b/.vscode/settings.json
@@ -0,0 +1,5 @@
+{
+ "cSpell.words": [
+ "Scheduleapp"
+ ]
+}
\ No newline at end of file
diff --git a/assets/icons/closed_garage_door.svg b/assets/icons/closed_garage_door.svg
new file mode 100644
index 0000000..464aa07
--- /dev/null
+++ b/assets/icons/closed_garage_door.svg
@@ -0,0 +1,148 @@
+
diff --git a/assets/icons/garage_countdown.svg b/assets/icons/garage_countdown.svg
new file mode 100644
index 0000000..b2a3ead
--- /dev/null
+++ b/assets/icons/garage_countdown.svg
@@ -0,0 +1,29 @@
+
diff --git a/assets/icons/garage_preferences_icon.svg b/assets/icons/garage_preferences_icon.svg
new file mode 100644
index 0000000..d0883b0
--- /dev/null
+++ b/assets/icons/garage_preferences_icon.svg
@@ -0,0 +1,11 @@
+
diff --git a/assets/icons/garage_schedule.svg b/assets/icons/garage_schedule.svg
new file mode 100644
index 0000000..04e7763
--- /dev/null
+++ b/assets/icons/garage_schedule.svg
@@ -0,0 +1,28 @@
+
diff --git a/assets/icons/open_garage_door.svg b/assets/icons/open_garage_door.svg
new file mode 100644
index 0000000..d55a690
--- /dev/null
+++ b/assets/icons/open_garage_door.svg
@@ -0,0 +1,117 @@
+
diff --git a/lib/features/devices/bloc/garage_door_bloc/garage_door_bloc.dart b/lib/features/devices/bloc/garage_door_bloc/garage_door_bloc.dart
new file mode 100644
index 0000000..f6c3d4f
--- /dev/null
+++ b/lib/features/devices/bloc/garage_door_bloc/garage_door_bloc.dart
@@ -0,0 +1,411 @@
+import 'dart:async';
+import 'package:dio/dio.dart';
+import 'package:firebase_database/firebase_database.dart';
+import 'package:flutter_bloc/flutter_bloc.dart';
+import 'package:syncrow_app/features/devices/bloc/garage_door_bloc/garage_door_event.dart';
+import 'package:syncrow_app/features/devices/bloc/garage_door_bloc/garage_door_state.dart';
+import 'package:syncrow_app/features/devices/model/device_control_model.dart';
+import 'package:syncrow_app/features/devices/model/device_report_model.dart';
+import 'package:syncrow_app/features/devices/model/garage_door_model.dart';
+import 'package:syncrow_app/features/devices/model/schedule_model.dart';
+import 'package:syncrow_app/features/devices/model/status_model.dart';
+import 'package:syncrow_app/services/api/devices_api.dart';
+import 'package:syncrow_app/utils/helpers/snack_bar.dart';
+
+class GarageDoorBloc extends Bloc {
+ final String GDId;
+ GarageDoorBloc({
+ required this.GDId,
+ }) : super(const GarageDoorSensorState()) {
+ on(_fetchStatus);
+ on(fetchLogsForLastMonth);
+ on(_toggleClosingReminder);
+ on(_toggleDoorAlarm);
+ on(toggleDaySelection);
+ on(saveSchedule);
+ on(getSchedule);
+ on(toggleChange);
+ on(toggleCreateSchedule);
+ on(_onClose);
+ on(selectSeconds);
+ on(openCloseGarageDoor);
+ on(_getCounterValue);
+ on(_setCounterValue);
+ on(_onTickTimer);
+ }
+ void _onClose(OnClose event, Emitter emit) {
+ _timer?.cancel();
+ }
+
+ Timer? _timer;
+ bool lowBattery = false;
+ bool closingReminder = false;
+ bool doorAlarm = false;
+
+ GarageDoorModel deviceStatus = GarageDoorModel(
+ tr_timecon: 0,
+ countdown1: 0,
+ countdownAlarm: 0,
+ doorContactState: false,
+ doorControl1: '',
+ doorState1: '',
+ switch1: false,
+ voiceControl1: false,
+ batteryPercentage: 0,
+ );
+
+ void _fetchStatus(
+ GarageDoorInitial event, Emitter emit) async {
+ emit(GarageDoorLoadingState());
+ try {
+ var response = await DevicesAPI.getDeviceStatus(GDId);
+ List statusModelList = [];
+ for (var status in response['status']) {
+ statusModelList.add(StatusModel.fromJson(status));
+ }
+ deviceStatus = GarageDoorModel.fromJson(
+ statusModelList,
+ );
+ secondSelected = deviceStatus.tr_timecon;
+ toggleDoor = deviceStatus.switch1;
+ emit(UpdateState(garageSensor: deviceStatus));
+ Future.delayed(const Duration(milliseconds: 500));
+ _listenToChanges();
+ } catch (e) {
+ emit(GarageDoorFailedState(errorMessage: e.toString()));
+ return;
+ }
+ }
+
+ void _toggleClosingReminder(ToggleClosingReminderEvent event,
+ Emitter emit) async {
+ emit(LoadingNewSate(doorSensor: deviceStatus));
+ try {
+ closingReminder = event.isClosingReminderEnabled;
+ emit(UpdateState(garageSensor: deviceStatus));
+ await DevicesAPI.controlDevice(
+ DeviceControlModel(
+ deviceId: GDId,
+ code: 'closing_reminder',
+ value: closingReminder,
+ ),
+ GDId,
+ );
+ } catch (e) {
+ emit(GarageDoorFailedState(errorMessage: e.toString()));
+ }
+ }
+
+ void _toggleDoorAlarm(
+ ToggleDoorAlarmEvent event, Emitter emit) async {
+ emit(LoadingNewSate(doorSensor: deviceStatus));
+ try {
+ doorAlarm = event.isDoorAlarmEnabled;
+ emit(UpdateState(garageSensor: deviceStatus));
+ await DevicesAPI.controlDevice(
+ DeviceControlModel(
+ deviceId: GDId,
+ code: 'door_alarm',
+ value: doorAlarm,
+ ),
+ GDId,
+ );
+ } catch (e) {
+ emit(GarageDoorFailedState(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(GarageDoorLoadingState());
+ var response = await DevicesAPI.getReportLogs(
+ startTime: startTime.toString(),
+ endTime: endTime.toString(),
+ deviceUuid: GDId,
+ code: 'doorcontact_state',
+ );
+ recordGroups = response;
+ emit(UpdateState(garageSensor: deviceStatus));
+ } on DioException catch (e) {
+ final errorData = e.response!.data;
+ String errorMessage = errorData['message'];
+ emit(GarageDoorFailedState(errorMessage: errorMessage));
+ }
+ }
+
+ _listenToChanges() {
+ try {
+ DatabaseReference ref =
+ FirebaseDatabase.instance.ref('device-status/$GDId');
+ 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 = GarageDoorModel.fromJson(statusList);
+ if (!isClosed) {
+ // add(
+ // DoorSensorSwitch(switchD: deviceStatus.doorContactState),
+ // );
+ }
+ });
+ } catch (_) {}
+ }
+
+ List