diff --git a/assets/icons/noValidPasswords.svg b/assets/icons/noValidPasswords.svg
new file mode 100644
index 0000000..1a660df
--- /dev/null
+++ b/assets/icons/noValidPasswords.svg
@@ -0,0 +1,5 @@
+
diff --git a/assets/icons/oneTimePassword.svg b/assets/icons/oneTimePassword.svg
new file mode 100644
index 0000000..06bd9b5
--- /dev/null
+++ b/assets/icons/oneTimePassword.svg
@@ -0,0 +1,5 @@
+
diff --git a/assets/icons/timeLimitedPassword.svg b/assets/icons/timeLimitedPassword.svg
new file mode 100644
index 0000000..be4fdbc
--- /dev/null
+++ b/assets/icons/timeLimitedPassword.svg
@@ -0,0 +1,5 @@
+
diff --git a/assets/icons/timeLimitedPasswordIcon.svg b/assets/icons/timeLimitedPasswordIcon.svg
new file mode 100644
index 0000000..60cc3d6
--- /dev/null
+++ b/assets/icons/timeLimitedPasswordIcon.svg
@@ -0,0 +1,12 @@
+
diff --git a/lib/features/devices/bloc/smart_door_bloc/smart_door_bloc.dart b/lib/features/devices/bloc/smart_door_bloc/smart_door_bloc.dart
index de0b4c7..0259855 100644
--- a/lib/features/devices/bloc/smart_door_bloc/smart_door_bloc.dart
+++ b/lib/features/devices/bloc/smart_door_bloc/smart_door_bloc.dart
@@ -1,23 +1,39 @@
+import 'dart:math';
+import 'package:day_picker/model/day_in_week.dart';
+import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
+import 'package:intl/intl.dart';
import 'package:syncrow_app/features/devices/bloc/smart_door_bloc/smart_door_event.dart';
import 'package:syncrow_app/features/devices/bloc/smart_door_bloc/smart_door_state.dart';
import 'package:syncrow_app/features/devices/model/device_control_model.dart';
import 'package:syncrow_app/features/devices/model/smart_door_model.dart';
import 'package:syncrow_app/features/devices/model/status_model.dart';
+import 'package:syncrow_app/features/devices/model/create_temporary_password_model.dart';
+import 'package:syncrow_app/features/devices/model/temporary_password_model.dart';
import 'package:syncrow_app/services/api/devices_api.dart';
+import 'package:syncrow_app/utils/helpers/snack_bar.dart';
class SmartDoorBloc extends Bloc {
final String deviceId;
late SmartDoorModel deviceStatus;
+ static String pageType = '';
SmartDoorBloc({required this.deviceId}) : super(InitialState()) {
on(_fetchSmartDoorStatus);
+ on(getTemporaryPasswords);
on(_updateLock);
+ on(savePassword);
+ on(toggleRepeat);
+ on(setStartEndTime);
+ on(changeTime);
+ on(generate7DigitNumber);
+ on(selectTime);
+ on(deletePassword);
}
-
- void _fetchSmartDoorStatus(InitialEvent event, Emitter emit) async {
- emit(LoadingInitialState());
+ void _fetchSmartDoorStatus(
+ InitialEvent event, Emitter emit) async {
try {
+ emit(LoadingInitialState());
var response = await DevicesAPI.getDeviceStatus(deviceId);
List statusModelList = [];
for (var status in response['status']) {
@@ -31,11 +47,76 @@ class SmartDoorBloc extends Bloc {
}
}
+ void getTemporaryPasswords(
+ InitialPasswordsPage event, Emitter emit) async {
+ try {
+ emit(LoadingInitialState());
+ pageType = event.type!;
+ var response = await DevicesAPI.getTemporaryPasswords(deviceId, pageType);
+ if (response is List) {
+ temporaryPasswords =
+ response.map((item) => TemporaryPassword.fromJson(item)).toList();
+ } else if (response is Map && response.containsKey('data')) {
+ temporaryPasswords = (response['data'] as List)
+ .map((item) => TemporaryPassword.fromJson(item))
+ .toList();
+ } else {
+ throw Exception("Unexpected response format");
+ }
+ emit(TemporaryPasswordsLoadedState(
+ temporaryPassword: temporaryPasswords!));
+ } catch (e) {
+ emit(FailedState(errorMessage: e.toString()));
+ }
+ }
+
+ TextEditingController passwordController = TextEditingController();
+ TextEditingController passwordNameController = TextEditingController();
+ String effectiveTime = 'Select Time';
+ int? effectiveTimeTimeStamp;
+ String expirationTime = 'Select Time';
+ int? expirationTimeTimeStamp;
+ bool repeat = false;
+ bool isStartEndTime = true;
+ List? selectedDay;
+ DateTime? startTime;
+ DateTime? endTime;
+ List? temporaryPasswords = [];
+ List? oneTimePasswords = [];
+
+ changeTime(ChangeTimeEvent event, Emitter emit) {
+ emit(LoadingInitialState());
+ if (event.isStartEndTime == true) {
+ startTime = event.val;
+ } else {
+ endTime = event.val;
+ }
+ emit(changeTimeState());
+ }
+
+ bool toggleRepeat(ToggleRepeatEvent event, Emitter emit) {
+ emit(LoadingInitialState());
+ repeat = !repeat;
+ emit(IsRepeatState());
+ return repeat;
+ }
+
+
+ bool setStartEndTime(SetStartEndTimeEvent event, Emitter emit) {
+ emit(LoadingInitialState());
+ isStartEndTime = event.val;
+ emit(IsStartEndState());
+ return isStartEndTime;
+ }
+
void _updateLock(UpdateLockEvent event, Emitter emit) async {
emit(LoadingNewSate(smartDoorModel: deviceStatus));
try {
final response = await DevicesAPI.controlDevice(
- DeviceControlModel(deviceId: deviceId, code: 'normal_open_switch', value: !event.value),
+ DeviceControlModel(
+ deviceId: deviceId,
+ code: 'normal_open_switch',
+ value: !event.value),
deviceId);
if (response['success'] ?? false) {
@@ -44,4 +125,146 @@ class SmartDoorBloc extends Bloc {
} catch (_) {}
emit(UpdateState(smartDoorModel: deviceStatus));
}
+
+ void generate7DigitNumber(GeneratePasswordEvent event, Emitter emit) async {
+ emit(LoadingInitialState());
+ passwordController.clear();
+ Random random = Random();
+ int min = 1000000;
+ int max = 9999999;
+ passwordController.text = (min + random.nextInt(max - min + 1)).toString();
+ emit(GeneratePasswordState());
+ }
+
+ Future selectTime(SelectTimeEvent event, Emitter emit) async {
+ final DateTime? picked = await showDatePicker(
+ context: event.context,
+ initialDate: DateTime.now(),
+ firstDate: DateTime(2015, 8),
+ lastDate: DateTime(2101),
+ );
+ if (picked != null) {
+ final TimeOfDay? timePicked = await showTimePicker(
+ context: event.context,
+ initialTime: TimeOfDay.now(),
+ );
+ if (timePicked != null) {
+ final selectedDateTime = DateTime(
+ picked.year,
+ picked.month,
+ picked.day,
+ timePicked.hour,
+ timePicked.minute,
+ );
+ if (event.isEffective) {
+ if (expirationTimeTimeStamp != null &&
+ selectedDateTime.millisecondsSinceEpoch >
+ expirationTimeTimeStamp!) {
+ CustomSnackBar.displaySnackBar('Effective Time cannot be later than Expiration Time.');
+ } else {
+ effectiveTime = selectedDateTime.toString();
+ effectiveTimeTimeStamp = selectedDateTime.millisecondsSinceEpoch;
+ }
+ } else {
+ if (effectiveTimeTimeStamp != null &&
+ selectedDateTime.millisecondsSinceEpoch <
+ effectiveTimeTimeStamp!) {
+ CustomSnackBar.displaySnackBar('Expiration Time cannot be earlier than Effective Time.');
+ } else {
+ expirationTime = selectedDateTime.toString();
+ expirationTimeTimeStamp = selectedDateTime.millisecondsSinceEpoch;
+ }
+ }
+ emit(TimeSelectedState());
+ }
+ }
+ }
+
+ Future savePassword(SavePasswordEvent event, Emitter emit) async {
+ if (_validateInputs()) return;
+ try {
+ emit(LoadingSaveState());
+ var res = await DevicesAPI.createPassword(
+ pageType: pageType,
+ deviceId: deviceId,
+ effectiveTime: effectiveTimeTimeStamp.toString(),
+ invalidTime: expirationTimeTimeStamp.toString(),
+ name: passwordNameController.text,
+ password: passwordController.text,
+ scheduleList: [
+ if (repeat)
+ Schedule(
+ effectiveTime: getTimeOnly(startTime),
+ invalidTime: getTimeOnly(endTime).toString(),
+ workingDay: selectedDay!,
+ ),
+ ],
+ );
+ Navigator.of(event.context).pop(true);
+ CustomSnackBar.displaySnackBar('Save Successfully');
+ emit(SaveState());
+
+ } catch (_) {
+ }
+ }
+
+ Future deletePassword(DeletePasswordEvent event, Emitter emit) async {
+ try {
+ emit(LoadingInitialState());
+ var response = await DevicesAPI.deletePassword(
+ deviceId: deviceId, passwordId: event.passwordId)
+ .then((value) async {
+ add(InitialPasswordsPage(type: pageType));
+ });
+ } catch (e) {
+ emit(FailedState(errorMessage: e.toString()));
+ }
+ }
+
+ bool _validateInputs() {
+ if (passwordController.text.length<7) {
+ CustomSnackBar.displaySnackBar('Password less than 7');
+ return true;
+ }
+ if (passwordController.text.isEmpty) {
+ CustomSnackBar.displaySnackBar('Password required');
+ return true;
+ }
+ if (passwordNameController.text.isEmpty) {
+ CustomSnackBar.displaySnackBar('Password name required');
+ return true;
+ }
+ if (effectiveTime == 'Select Time' || effectiveTimeTimeStamp == null) {
+ CustomSnackBar.displaySnackBar('Select effective time');
+ return true;
+ }
+ if (expirationTime == 'Select Time' || expirationTimeTimeStamp == null) {
+ CustomSnackBar.displaySnackBar('Select expiration time');
+ return true;
+ }
+ if (repeat == true &&
+ (endTime == null || startTime == null || selectedDay == null)) {
+ CustomSnackBar.displaySnackBar('Start Time and End time and the days required ');
+ return true;
+ }
+ return false;
+ }
+
+
+
+ List days = [
+ DayInWeek("S", dayKey: 'Sun'),
+ DayInWeek("M", dayKey: 'Mon'),
+ DayInWeek("T", dayKey: 'Tue'),
+ DayInWeek("W", dayKey: 'Wed'),
+ DayInWeek("T", dayKey: 'Thu'),
+ DayInWeek("F", dayKey: 'Fri'),
+ DayInWeek("S", dayKey: 'Sat'),
+ ];
+
+ String getTimeOnly(DateTime? dateTime) {
+ if (dateTime == null) return '';
+ return DateFormat('HH:mm').format(dateTime);
+ }
+
}
diff --git a/lib/features/devices/bloc/smart_door_bloc/smart_door_event.dart b/lib/features/devices/bloc/smart_door_bloc/smart_door_event.dart
index a266390..df138ae 100644
--- a/lib/features/devices/bloc/smart_door_bloc/smart_door_event.dart
+++ b/lib/features/devices/bloc/smart_door_bloc/smart_door_event.dart
@@ -1,4 +1,5 @@
import 'package:equatable/equatable.dart';
+import 'package:flutter/cupertino.dart';
abstract class SmartDoorEvent extends Equatable {
const SmartDoorEvent();
@@ -8,6 +9,11 @@ abstract class SmartDoorEvent extends Equatable {
}
class InitialEvent extends SmartDoorEvent {}
+class InitialPasswordsPage extends SmartDoorEvent {
+ final String? type;
+ const InitialPasswordsPage({ this.type});
+}
+class InitialOneTimePassword extends SmartDoorEvent {}
class UpdateLockEvent extends SmartDoorEvent {
final bool value;
@@ -15,3 +21,47 @@ class UpdateLockEvent extends SmartDoorEvent {
@override
List