mirror of
https://github.com/SyncrowIOT/syncrow-app.git
synced 2025-07-15 09:45:22 +00:00
door lock password update
This commit is contained in:
@ -1,11 +1,13 @@
|
|||||||
import 'dart:math';
|
import 'dart:math';
|
||||||
import 'package:day_picker/model/day_in_week.dart';
|
import 'package:flutter/cupertino.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:intl/intl.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_event.dart';
|
||||||
import 'package:syncrow_app/features/devices/bloc/smart_door_bloc/smart_door_state.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/device_control_model.dart';
|
||||||
|
import 'package:syncrow_app/features/devices/model/offline_password_model.dart';
|
||||||
|
import 'package:syncrow_app/features/devices/model/offline_temporary_password.dart';
|
||||||
import 'package:syncrow_app/features/devices/model/smart_door_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/status_model.dart';
|
||||||
import 'package:syncrow_app/features/devices/model/create_temporary_password_model.dart';
|
import 'package:syncrow_app/features/devices/model/create_temporary_password_model.dart';
|
||||||
@ -17,12 +19,13 @@ import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
|
|||||||
class SmartDoorBloc extends Bloc<SmartDoorEvent, SmartDoorState> {
|
class SmartDoorBloc extends Bloc<SmartDoorEvent, SmartDoorState> {
|
||||||
final String deviceId;
|
final String deviceId;
|
||||||
late SmartDoorModel deviceStatus;
|
late SmartDoorModel deviceStatus;
|
||||||
static String pageType = '';
|
|
||||||
bool isSavingPassword = false;
|
bool isSavingPassword = false;
|
||||||
|
|
||||||
SmartDoorBloc({required this.deviceId}) : super(InitialState()) {
|
SmartDoorBloc({required this.deviceId}) : super(InitialState()) {
|
||||||
on<InitialEvent>(_fetchSmartDoorStatus);
|
on<InitialEvent>(_fetchSmartDoorStatus);
|
||||||
on<InitialPasswordsPage>(getTemporaryPasswords);
|
on<InitialPasswordsPage>(getTemporaryPasswords);
|
||||||
|
on<InitialOneTimePassword>(getOneTimePasswords);
|
||||||
|
on<InitialTimeLimitPassword>(getTimeLimitPasswords);
|
||||||
on<UpdateLockEvent>(_updateLock);
|
on<UpdateLockEvent>(_updateLock);
|
||||||
on<SavePasswordEvent>(savePassword);
|
on<SavePasswordEvent>(savePassword);
|
||||||
on<ToggleRepeatEvent>(toggleRepeat);
|
on<ToggleRepeatEvent>(toggleRepeat);
|
||||||
@ -31,7 +34,56 @@ class SmartDoorBloc extends Bloc<SmartDoorEvent, SmartDoorState> {
|
|||||||
on<GeneratePasswordEvent>(generate7DigitNumber);
|
on<GeneratePasswordEvent>(generate7DigitNumber);
|
||||||
on<SelectTimeEvent>(selectTime);
|
on<SelectTimeEvent>(selectTime);
|
||||||
on<DeletePasswordEvent>(deletePassword);
|
on<DeletePasswordEvent>(deletePassword);
|
||||||
|
on<GenerateAndSavePasswordTimeLimitEvent>(generateAndSavePasswordTimeLimited);
|
||||||
|
on<GenerateAndSavePasswordOneTimeEvent>(generateAndSavePasswordOneTime);
|
||||||
|
on<ToggleDaySelectionEvent>(toggleDaySelection);
|
||||||
|
on<RenamePasswordEvent>(_renamePassword);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TextEditingController passwordController = TextEditingController();
|
||||||
|
TextEditingController passwordNameController = TextEditingController();
|
||||||
|
String effectiveTime = 'Select Time';
|
||||||
|
String passwordId = '';
|
||||||
|
int? effectiveTimeTimeStamp;
|
||||||
|
String expirationTime = 'Select Time';
|
||||||
|
int? expirationTimeTimeStamp;
|
||||||
|
bool repeat = false;
|
||||||
|
bool isStartEndTime = true;
|
||||||
|
DateTime? startTime;
|
||||||
|
DateTime? endTime;
|
||||||
|
List<TemporaryPassword>? temporaryPasswords = [];
|
||||||
|
List<OfflinePasswordModel>? oneTimePasswords = [];
|
||||||
|
List<OfflinePasswordModel>? timeLimitPasswords = [];
|
||||||
|
|
||||||
|
Future generate7DigitNumber(GeneratePasswordEvent event, Emitter<SmartDoorState> 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());
|
||||||
|
return passwordController.text;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Future generateAndSavePasswordOneTime (GenerateAndSavePasswordOneTimeEvent event, Emitter<SmartDoorState> emit) async {
|
||||||
|
try {
|
||||||
|
if (isSavingPassword) return;
|
||||||
|
isSavingPassword = true;
|
||||||
|
emit(LoadingInitialState());
|
||||||
|
var res = await DevicesAPI.generateOneTimePassword(deviceId: deviceId);
|
||||||
|
ApiResponse pass= ApiResponse.fromJson(res);
|
||||||
|
passwordController.text =pass.data.offlineTempPassword;
|
||||||
|
passwordId=pass.data.offlineTempPasswordId;
|
||||||
|
emit(const GeneratePasswordOneTimestate(generated: true));
|
||||||
|
} catch (_) {
|
||||||
|
emit(FailedState(errorMessage: _.toString()));
|
||||||
|
}finally {
|
||||||
|
isSavingPassword = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void _fetchSmartDoorStatus(InitialEvent event, Emitter<SmartDoorState> emit) async {
|
void _fetchSmartDoorStatus(InitialEvent event, Emitter<SmartDoorState> emit) async {
|
||||||
try {
|
try {
|
||||||
emit(LoadingInitialState());
|
emit(LoadingInitialState());
|
||||||
@ -48,18 +100,29 @@ class SmartDoorBloc extends Bloc<SmartDoorEvent, SmartDoorState> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void _renamePassword(RenamePasswordEvent event, Emitter<SmartDoorState> emit) async {
|
||||||
|
try {
|
||||||
|
emit(LoadingInitialState());
|
||||||
|
var response = await DevicesAPI.renamePass(
|
||||||
|
name:passwordNameController.text ,
|
||||||
|
doorLockUuid:deviceId ,
|
||||||
|
passwordId:passwordId
|
||||||
|
);
|
||||||
|
emit(UpdateState(smartDoorModel: deviceStatus));
|
||||||
|
} catch (e) {
|
||||||
|
emit(FailedState(errorMessage: e.toString()));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void getTemporaryPasswords(InitialPasswordsPage event, Emitter<SmartDoorState> emit) async {
|
void getTemporaryPasswords(InitialPasswordsPage event, Emitter<SmartDoorState> emit) async {
|
||||||
try {
|
try {
|
||||||
emit(LoadingInitialState());
|
emit(LoadingInitialState());
|
||||||
pageType = event.type!;
|
var response = await DevicesAPI.getTemporaryPasswords(deviceId, );
|
||||||
var response = await DevicesAPI.getTemporaryPasswords(deviceId, pageType);
|
|
||||||
if (response is List) {
|
if (response is List) {
|
||||||
temporaryPasswords = response.map((item) => TemporaryPassword.fromJson(item)).toList();
|
temporaryPasswords = response.map((item) => TemporaryPassword.fromJson(item)).toList();
|
||||||
} else if (response is Map && response.containsKey('data')) {
|
} else if (response is Map && response.containsKey('data')) {
|
||||||
temporaryPasswords =
|
temporaryPasswords = (response['data'] as List).map((item) => TemporaryPassword.fromJson(item)).toList();
|
||||||
(response['data'] as List).map((item) => TemporaryPassword.fromJson(item)).toList();
|
|
||||||
} else {
|
|
||||||
throw Exception("Unexpected response format");
|
|
||||||
}
|
}
|
||||||
emit(TemporaryPasswordsLoadedState(temporaryPassword: temporaryPasswords!));
|
emit(TemporaryPasswordsLoadedState(temporaryPassword: temporaryPasswords!));
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
@ -67,41 +130,51 @@ class SmartDoorBloc extends Bloc<SmartDoorEvent, SmartDoorState> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TextEditingController passwordController = TextEditingController();
|
void getOneTimePasswords(InitialOneTimePassword event, Emitter<SmartDoorState> emit) async {
|
||||||
TextEditingController passwordNameController = TextEditingController();
|
try {
|
||||||
String effectiveTime = 'Select Time';
|
emit(LoadingInitialState());
|
||||||
int? effectiveTimeTimeStamp;
|
var response = await DevicesAPI.getOneTimePasswords(deviceId);
|
||||||
String expirationTime = 'Select Time';
|
if (response is List) {
|
||||||
int? expirationTimeTimeStamp;
|
oneTimePasswords = response.map((item) => OfflinePasswordModel.fromJson(item)).toList();
|
||||||
bool repeat = false;
|
}
|
||||||
bool isStartEndTime = true;
|
emit(TemporaryPasswordsLoadedState(temporaryPassword: temporaryPasswords!));
|
||||||
List<String>? selectedDay;
|
} catch (e) {
|
||||||
DateTime? startTime;
|
emit(FailedState(errorMessage: e.toString()));
|
||||||
DateTime? endTime;
|
}
|
||||||
List<TemporaryPassword>? temporaryPasswords = [];
|
}
|
||||||
List<TemporaryPassword>? oneTimePasswords = [];
|
|
||||||
|
void getTimeLimitPasswords(InitialTimeLimitPassword event, Emitter<SmartDoorState> emit) async {
|
||||||
|
try {
|
||||||
|
emit(LoadingInitialState());
|
||||||
|
var response = await DevicesAPI.getTimeLimitPasswords(deviceId);
|
||||||
|
if (response is List) {
|
||||||
|
timeLimitPasswords = response.map((item) => OfflinePasswordModel.fromJson(item)).toList();
|
||||||
|
}
|
||||||
|
emit(TemporaryPasswordsLoadedState(temporaryPassword: temporaryPasswords!));
|
||||||
|
} catch (e) {
|
||||||
|
emit(FailedState(errorMessage: e.toString()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
changeTime(ChangeTimeEvent event, Emitter<SmartDoorState> emit) {
|
changeTime(ChangeTimeEvent event, Emitter<SmartDoorState> emit) {
|
||||||
emit(LoadingInitialState());
|
|
||||||
if (event.isStartEndTime == true) {
|
if (event.isStartEndTime == true) {
|
||||||
startTime = event.val;
|
startTime = event.val;
|
||||||
} else {
|
} else {
|
||||||
endTime = event.val;
|
endTime = event.val;
|
||||||
}
|
}
|
||||||
emit(ChangeTimeState());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool toggleRepeat(ToggleRepeatEvent event, Emitter<SmartDoorState> emit) {
|
bool toggleRepeat(ToggleRepeatEvent event, Emitter<SmartDoorState> emit) {
|
||||||
emit(LoadingInitialState());
|
emit(LoadingInitialState());
|
||||||
repeat = !repeat;
|
repeat = !repeat;
|
||||||
emit(IsRepeatState());
|
emit(IsRepeatState(repeat: repeat));
|
||||||
return repeat;
|
return repeat;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool setStartEndTime(SetStartEndTimeEvent event, Emitter<SmartDoorState> emit) {
|
bool setStartEndTime(SetStartEndTimeEvent event, Emitter<SmartDoorState> emit) {
|
||||||
emit(LoadingInitialState());
|
emit(LoadingInitialState());
|
||||||
isStartEndTime = event.val;
|
isStartEndTime = event.val;
|
||||||
emit(IsStartEndState());
|
emit(IsStartEndState(isStartEndTime:isStartEndTime));
|
||||||
return isStartEndTime;
|
return isStartEndTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -119,16 +192,6 @@ class SmartDoorBloc extends Bloc<SmartDoorEvent, SmartDoorState> {
|
|||||||
emit(UpdateState(smartDoorModel: deviceStatus));
|
emit(UpdateState(smartDoorModel: deviceStatus));
|
||||||
}
|
}
|
||||||
|
|
||||||
void generate7DigitNumber(GeneratePasswordEvent event, Emitter<SmartDoorState> 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<void> selectTime(SelectTimeEvent event, Emitter<SmartDoorState> emit) async {
|
Future<void> selectTime(SelectTimeEvent event, Emitter<SmartDoorState> emit) async {
|
||||||
emit(ChangeTimeState());
|
emit(ChangeTimeState());
|
||||||
final DateTime? picked = await showDatePicker(
|
final DateTime? picked = await showDatePicker(
|
||||||
@ -166,7 +229,6 @@ class SmartDoorBloc extends Bloc<SmartDoorEvent, SmartDoorState> {
|
|||||||
timePicked.hour,
|
timePicked.hour,
|
||||||
timePicked.minute,
|
timePicked.minute,
|
||||||
);
|
);
|
||||||
// Convert selectedDateTime to a timestamp without seconds and milliseconds
|
|
||||||
final selectedTimestamp = DateTime(
|
final selectedTimestamp = DateTime(
|
||||||
selectedDateTime.year,
|
selectedDateTime.year,
|
||||||
selectedDateTime.month,
|
selectedDateTime.month,
|
||||||
@ -203,7 +265,6 @@ class SmartDoorBloc extends Bloc<SmartDoorEvent, SmartDoorState> {
|
|||||||
isSavingPassword = true;
|
isSavingPassword = true;
|
||||||
emit(LoadingSaveState());
|
emit(LoadingSaveState());
|
||||||
var res = await DevicesAPI.createPassword(
|
var res = await DevicesAPI.createPassword(
|
||||||
pageType: pageType,
|
|
||||||
deviceId: deviceId,
|
deviceId: deviceId,
|
||||||
effectiveTime: effectiveTimeTimeStamp.toString(),
|
effectiveTime: effectiveTimeTimeStamp.toString(),
|
||||||
invalidTime: expirationTimeTimeStamp.toString(),
|
invalidTime: expirationTimeTimeStamp.toString(),
|
||||||
@ -214,24 +275,48 @@ class SmartDoorBloc extends Bloc<SmartDoorEvent, SmartDoorState> {
|
|||||||
Schedule(
|
Schedule(
|
||||||
effectiveTime: getTimeOnly(startTime),
|
effectiveTime: getTimeOnly(startTime),
|
||||||
invalidTime: getTimeOnly(endTime).toString(),
|
invalidTime: getTimeOnly(endTime).toString(),
|
||||||
workingDay: selectedDay!,
|
workingDay: selectedDays,
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
Navigator.of(event.context).pop(true);
|
Navigator.of(event.context).pop(true);
|
||||||
CustomSnackBar.displaySnackBar('Save Successfully');
|
CustomSnackBar.displaySnackBar('Save Successfully');
|
||||||
emit(SaveState());
|
emit(SaveState());
|
||||||
} catch (_) {}finally {
|
} catch (_) {
|
||||||
|
|
||||||
|
}finally {
|
||||||
isSavingPassword = false;
|
isSavingPassword = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<void> generateAndSavePasswordTimeLimited (GenerateAndSavePasswordTimeLimitEvent event, Emitter<SmartDoorState> emit) async {
|
||||||
|
if (timeLimitValidate() || isSavingPassword) return;
|
||||||
|
try {
|
||||||
|
isSavingPassword = true;
|
||||||
|
emit(LoadingInitialState());
|
||||||
|
var res = await DevicesAPI.generateMultiTimePassword(deviceId: deviceId,
|
||||||
|
effectiveTime: effectiveTimeTimeStamp.toString(),
|
||||||
|
invalidTime: expirationTimeTimeStamp.toString(), );
|
||||||
|
ApiResponse pass= ApiResponse.fromJson(res);
|
||||||
|
passwordController.text =pass.data.offlineTempPassword;
|
||||||
|
passwordId=pass.data.offlineTempPasswordId;
|
||||||
|
CustomSnackBar.displaySnackBar('Save Successfully');
|
||||||
|
emit(const GeneratePasswordOneTimestate(generated: true));
|
||||||
|
} catch (_) {
|
||||||
|
emit(FailedState(errorMessage: e.toString()));
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
isSavingPassword = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Future<void> deletePassword(DeletePasswordEvent event, Emitter<SmartDoorState> emit) async {
|
Future<void> deletePassword(DeletePasswordEvent event, Emitter<SmartDoorState> emit) async {
|
||||||
try {
|
try {
|
||||||
emit(LoadingInitialState());
|
emit(LoadingInitialState());
|
||||||
var response =
|
var response =
|
||||||
await DevicesAPI.deletePassword(deviceId: deviceId, passwordId: event.passwordId)
|
await DevicesAPI.deletePassword(deviceId: deviceId, passwordId: event.passwordId)
|
||||||
.then((value) async {
|
.then((value) async {
|
||||||
add(InitialPasswordsPage(type: pageType));
|
add(InitialPasswordsPage());
|
||||||
});
|
});
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
emit(FailedState(errorMessage: e.toString()));
|
emit(FailedState(errorMessage: e.toString()));
|
||||||
@ -259,25 +344,51 @@ class SmartDoorBloc extends Bloc<SmartDoorEvent, SmartDoorState> {
|
|||||||
CustomSnackBar.displaySnackBar('Select expiration time');
|
CustomSnackBar.displaySnackBar('Select expiration time');
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (repeat == true && (endTime == null || startTime == null || selectedDay == null)) {
|
if (repeat == true && (endTime == null || startTime == null || selectedDays == null)) {
|
||||||
CustomSnackBar.displaySnackBar('Start Time and End time and the days required ');
|
CustomSnackBar.displaySnackBar('Start Time and End time and the days required ');
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
bool timeLimitValidate() {
|
||||||
|
|
||||||
List<DayInWeek> days = [
|
if (effectiveTime == 'Select Time' || effectiveTimeTimeStamp == null) {
|
||||||
DayInWeek("S", dayKey: 'Sun'),
|
CustomSnackBar.displaySnackBar('Select effective time');
|
||||||
DayInWeek("M", dayKey: 'Mon'),
|
return true;
|
||||||
DayInWeek("T", dayKey: 'Tue'),
|
}
|
||||||
DayInWeek("W", dayKey: 'Wed'),
|
if (expirationTime == 'Select Time' || expirationTimeTimeStamp == null) {
|
||||||
DayInWeek("T", dayKey: 'Thu'),
|
CustomSnackBar.displaySnackBar('Select expiration time');
|
||||||
DayInWeek("F", dayKey: 'Fri'),
|
return true;
|
||||||
DayInWeek("S", dayKey: 'Sat'),
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
List<Map<String, String>> days = [
|
||||||
|
{"day": "Sun", "key": "Sun"},
|
||||||
|
{"day": "Mon", "key": "Mon"},
|
||||||
|
{"day": "Tue", "key": "Tue"},
|
||||||
|
{"day": "Wed", "key": "Wed"},
|
||||||
|
{"day": "Thu", "key": "Thu"},
|
||||||
|
{"day": "Fri", "key": "Fri"},
|
||||||
|
{"day": "Sat", "key": "Sat"},
|
||||||
];
|
];
|
||||||
|
|
||||||
|
List<String> selectedDays = [];
|
||||||
|
|
||||||
|
Future<void> toggleDaySelection(ToggleDaySelectionEvent event, Emitter<SmartDoorState> emit,)async {
|
||||||
|
emit(LoadingInitialState());
|
||||||
|
if (selectedDays.contains(event.key)) {
|
||||||
|
selectedDays.remove(event.key);
|
||||||
|
} else {
|
||||||
|
selectedDays.add(event.key);
|
||||||
|
}
|
||||||
|
emit(ChangeTimeState());
|
||||||
|
}
|
||||||
|
|
||||||
String getTimeOnly(DateTime? dateTime) {
|
String getTimeOnly(DateTime? dateTime) {
|
||||||
if (dateTime == null) return '';
|
if (dateTime == null) return '';
|
||||||
return DateFormat('HH:mm').format(dateTime);
|
return DateFormat('HH:mm').format(dateTime);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -9,11 +9,9 @@ abstract class SmartDoorEvent extends Equatable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class InitialEvent extends SmartDoorEvent {}
|
class InitialEvent extends SmartDoorEvent {}
|
||||||
class InitialPasswordsPage extends SmartDoorEvent {
|
class InitialPasswordsPage extends SmartDoorEvent {}
|
||||||
final String? type;
|
|
||||||
const InitialPasswordsPage({ this.type});
|
|
||||||
}
|
|
||||||
class InitialOneTimePassword extends SmartDoorEvent {}
|
class InitialOneTimePassword extends SmartDoorEvent {}
|
||||||
|
class InitialTimeLimitPassword extends SmartDoorEvent {}
|
||||||
|
|
||||||
class UpdateLockEvent extends SmartDoorEvent {
|
class UpdateLockEvent extends SmartDoorEvent {
|
||||||
final bool value;
|
final bool value;
|
||||||
@ -27,9 +25,26 @@ class SavePasswordEvent extends SmartDoorEvent {
|
|||||||
const SavePasswordEvent({required this.context});
|
const SavePasswordEvent({required this.context});
|
||||||
@override
|
@override
|
||||||
List<Object> get props => [context];
|
List<Object> get props => [context];
|
||||||
|
}
|
||||||
|
class GenerateAndSavePasswordTimeLimitEvent extends SmartDoorEvent {
|
||||||
|
final BuildContext context;
|
||||||
|
const GenerateAndSavePasswordTimeLimitEvent({required this.context});
|
||||||
|
@override
|
||||||
|
List<Object> get props => [context];
|
||||||
|
}
|
||||||
|
|
||||||
|
class GenerateAndSavePasswordOneTimeEvent extends SmartDoorEvent {
|
||||||
|
final BuildContext context;
|
||||||
|
const GenerateAndSavePasswordOneTimeEvent({required this.context});
|
||||||
|
@override
|
||||||
|
List<Object> get props => [context];
|
||||||
|
}
|
||||||
|
|
||||||
|
class GeneratePasswordEvent extends SmartDoorEvent {
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class GeneratePasswordEvent extends SmartDoorEvent {}
|
|
||||||
class SelectTimeEvent extends SmartDoorEvent {
|
class SelectTimeEvent extends SmartDoorEvent {
|
||||||
final BuildContext context;
|
final BuildContext context;
|
||||||
final bool isEffective;
|
final bool isEffective;
|
||||||
@ -41,7 +56,6 @@ class SelectTimeEvent extends SmartDoorEvent {
|
|||||||
class ToggleRepeatEvent extends SmartDoorEvent {}
|
class ToggleRepeatEvent extends SmartDoorEvent {}
|
||||||
class SetStartEndTimeEvent extends SmartDoorEvent {
|
class SetStartEndTimeEvent extends SmartDoorEvent {
|
||||||
final bool val;
|
final bool val;
|
||||||
|
|
||||||
const SetStartEndTimeEvent({required this.val});
|
const SetStartEndTimeEvent({required this.val});
|
||||||
@override
|
@override
|
||||||
List<Object> get props => [val];
|
List<Object> get props => [val];
|
||||||
@ -55,6 +69,14 @@ class DeletePasswordEvent extends SmartDoorEvent {
|
|||||||
List<Object> get props => [passwordId];
|
List<Object> get props => [passwordId];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class ToggleDaySelectionEvent extends SmartDoorEvent {
|
||||||
|
final String key;
|
||||||
|
|
||||||
|
const ToggleDaySelectionEvent({required this.key});
|
||||||
|
@override
|
||||||
|
List<Object> get props => [key];
|
||||||
|
}
|
||||||
|
|
||||||
class ChangeTimeEvent extends SmartDoorEvent {
|
class ChangeTimeEvent extends SmartDoorEvent {
|
||||||
final dynamic val;
|
final dynamic val;
|
||||||
final bool isStartEndTime;
|
final bool isStartEndTime;
|
||||||
@ -64,4 +86,7 @@ class ChangeTimeEvent extends SmartDoorEvent {
|
|||||||
List<Object> get props => [val,isStartEndTime];
|
List<Object> get props => [val,isStartEndTime];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class RenamePasswordEvent extends SmartDoorEvent {
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -38,13 +38,27 @@ class FailedState extends SmartDoorState {
|
|||||||
List<Object> get props => [errorMessage];
|
List<Object> get props => [errorMessage];
|
||||||
}
|
}
|
||||||
|
|
||||||
class GeneratePasswordState extends SmartDoorState {}
|
class GeneratePasswordState extends SmartDoorState {
|
||||||
|
}
|
||||||
|
|
||||||
class TimeSelectedState extends SmartDoorState {}
|
class TimeSelectedState extends SmartDoorState {}
|
||||||
|
|
||||||
class IsRepeatState extends SmartDoorState {}
|
class IsRepeatState extends SmartDoorState {
|
||||||
|
final bool repeat;
|
||||||
|
const IsRepeatState({required this.repeat});
|
||||||
|
|
||||||
class IsStartEndState extends SmartDoorState {}
|
@override
|
||||||
|
List<Object> get props => [repeat];
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
class IsStartEndState extends SmartDoorState {
|
||||||
|
final bool isStartEndTime;
|
||||||
|
const IsStartEndState({required this.isStartEndTime});
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<Object> get props => [isStartEndTime];
|
||||||
|
}
|
||||||
|
|
||||||
class ChangeStartTimeState extends SmartDoorState {}
|
class ChangeStartTimeState extends SmartDoorState {}
|
||||||
|
|
||||||
@ -56,6 +70,12 @@ class SaveState extends SmartDoorState {}
|
|||||||
|
|
||||||
class LoadingSaveState extends SmartDoorState {}
|
class LoadingSaveState extends SmartDoorState {}
|
||||||
|
|
||||||
|
class GeneratePasswordOneTimestate extends SmartDoorState {
|
||||||
|
final bool generated;
|
||||||
|
const GeneratePasswordOneTimestate({required this.generated});
|
||||||
|
List<Object> get props => [generated];
|
||||||
|
}
|
||||||
|
|
||||||
class TemporaryPasswordsLoadedState extends SmartDoorState {
|
class TemporaryPasswordsLoadedState extends SmartDoorState {
|
||||||
final List<TemporaryPassword> temporaryPassword;
|
final List<TemporaryPassword> temporaryPassword;
|
||||||
const TemporaryPasswordsLoadedState({required this.temporaryPassword});
|
const TemporaryPasswordsLoadedState({required this.temporaryPassword});
|
||||||
|
63
lib/features/devices/model/offline_password_model.dart
Normal file
63
lib/features/devices/model/offline_password_model.dart
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
|
||||||
|
|
||||||
|
class OfflinePasswordModel {
|
||||||
|
final dynamic gmtCreate;
|
||||||
|
final dynamic gmtExpired;
|
||||||
|
final dynamic gmtStart;
|
||||||
|
final bool hasClearPwd;
|
||||||
|
final String optUid;
|
||||||
|
final String pwd;
|
||||||
|
final dynamic pwdId;
|
||||||
|
final String pwdName;
|
||||||
|
final String pwdTypeCode;
|
||||||
|
final String revokedPwdName;
|
||||||
|
final dynamic status;
|
||||||
|
|
||||||
|
OfflinePasswordModel({
|
||||||
|
required this.gmtCreate,
|
||||||
|
required this.gmtExpired,
|
||||||
|
required this.gmtStart,
|
||||||
|
required this.hasClearPwd,
|
||||||
|
required this.optUid,
|
||||||
|
required this.pwd,
|
||||||
|
required this.pwdId,
|
||||||
|
required this.pwdName,
|
||||||
|
required this.pwdTypeCode,
|
||||||
|
required this.revokedPwdName,
|
||||||
|
required this.status,
|
||||||
|
});
|
||||||
|
|
||||||
|
// Factory method to create a Password from a JSON map
|
||||||
|
factory OfflinePasswordModel.fromJson(Map<String, dynamic> json) {
|
||||||
|
return OfflinePasswordModel(
|
||||||
|
gmtCreate: json['gmtCreate'],
|
||||||
|
gmtExpired: json['gmtExpired'],
|
||||||
|
gmtStart: json['gmtStart'],
|
||||||
|
hasClearPwd: json['hasClearPwd'],
|
||||||
|
optUid: json['optUid'],
|
||||||
|
pwd: json['pwd'],
|
||||||
|
pwdId: json['pwdId'],
|
||||||
|
pwdName: json['pwdName'],
|
||||||
|
pwdTypeCode: json['pwdTypeCode'],
|
||||||
|
revokedPwdName: json['revokedPwdName'],
|
||||||
|
status: json['status'],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Method to convert a Password object to a JSON map
|
||||||
|
Map<String, dynamic> toJson() {
|
||||||
|
return {
|
||||||
|
'gmtCreate': gmtCreate,
|
||||||
|
'gmtExpired': gmtExpired,
|
||||||
|
'gmtStart': gmtStart,
|
||||||
|
'hasClearPwd': hasClearPwd,
|
||||||
|
'optUid': optUid,
|
||||||
|
'pwd': pwd,
|
||||||
|
'pwdId': pwdId,
|
||||||
|
'pwdName': pwdName,
|
||||||
|
'pwdTypeCode': pwdTypeCode,
|
||||||
|
'revokedPwdName': revokedPwdName,
|
||||||
|
'status': status,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
69
lib/features/devices/model/offline_temporary_password.dart
Normal file
69
lib/features/devices/model/offline_temporary_password.dart
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
class OfflineTemporaryPassword {
|
||||||
|
dynamic effectiveTime;
|
||||||
|
dynamic invalidTime;
|
||||||
|
dynamic offlineTempPassword;
|
||||||
|
dynamic offlineTempPasswordId;
|
||||||
|
dynamic offlineTempPasswordName;
|
||||||
|
|
||||||
|
OfflineTemporaryPassword({
|
||||||
|
required this.effectiveTime,
|
||||||
|
required this.invalidTime,
|
||||||
|
required this.offlineTempPassword,
|
||||||
|
required this.offlineTempPasswordId,
|
||||||
|
required this.offlineTempPasswordName,
|
||||||
|
});
|
||||||
|
|
||||||
|
factory OfflineTemporaryPassword.fromJson(Map<String, dynamic> json) {
|
||||||
|
return OfflineTemporaryPassword(
|
||||||
|
effectiveTime: json['effective_time'],
|
||||||
|
invalidTime: json['invalid_time'],
|
||||||
|
offlineTempPassword: json['offline_temp_password'],
|
||||||
|
offlineTempPasswordId: json['offline_temp_password_id'],
|
||||||
|
offlineTempPasswordName: json['offline_temp_password_name'],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, dynamic> toJson() {
|
||||||
|
return {
|
||||||
|
'effective_time': effectiveTime,
|
||||||
|
'invalid_time': invalidTime,
|
||||||
|
'offline_temp_password': offlineTempPassword,
|
||||||
|
'offline_temp_password_id': offlineTempPasswordId,
|
||||||
|
'offline_temp_password_name': offlineTempPasswordName,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class ApiResponse {
|
||||||
|
int statusCode;
|
||||||
|
bool success;
|
||||||
|
String message;
|
||||||
|
OfflineTemporaryPassword data;
|
||||||
|
|
||||||
|
ApiResponse({
|
||||||
|
required this.statusCode,
|
||||||
|
required this.success,
|
||||||
|
required this.message,
|
||||||
|
required this.data,
|
||||||
|
});
|
||||||
|
|
||||||
|
factory ApiResponse.fromJson(Map<String, dynamic> json) {
|
||||||
|
return ApiResponse(
|
||||||
|
statusCode: json['statusCode'],
|
||||||
|
success: json['success'],
|
||||||
|
message: json['message'],
|
||||||
|
data: OfflineTemporaryPassword.fromJson(json['data']['result']),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, dynamic> toJson() {
|
||||||
|
return {
|
||||||
|
'statusCode': statusCode,
|
||||||
|
'success': success,
|
||||||
|
'message': message,
|
||||||
|
'data': {
|
||||||
|
'result': data.toJson(),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
116
lib/features/devices/view/widgets/name_time_widget.dart
Normal file
116
lib/features/devices/view/widgets/name_time_widget.dart
Normal file
@ -0,0 +1,116 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
import 'package:syncrow_app/features/devices/bloc/smart_door_bloc/smart_door_bloc.dart';
|
||||||
|
import 'package:syncrow_app/features/devices/bloc/smart_door_bloc/smart_door_event.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/utils/resource_manager/color_manager.dart';
|
||||||
|
|
||||||
|
class NameTimeWidget extends StatelessWidget {
|
||||||
|
const NameTimeWidget({super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return DefaultContainer(
|
||||||
|
padding: const EdgeInsets.all(20),
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
child: Container(
|
||||||
|
padding: const EdgeInsets.all(10.0),
|
||||||
|
child: const BodyMedium(
|
||||||
|
text: 'Password Name',
|
||||||
|
fontWeight: FontWeight.normal,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
SizedBox(
|
||||||
|
width: MediaQuery.of(context).size.width / 2.6,
|
||||||
|
child: TextFormField(
|
||||||
|
controller: BlocProvider.of<SmartDoorBloc>(context)
|
||||||
|
.passwordNameController,
|
||||||
|
decoration: const InputDecoration(
|
||||||
|
hintText: 'Enter The Name',
|
||||||
|
hintStyle: TextStyle(
|
||||||
|
fontSize: 14, color: ColorsManager.textGray)),
|
||||||
|
)),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
Column(
|
||||||
|
children: [
|
||||||
|
const Divider(
|
||||||
|
color: ColorsManager.graysColor,
|
||||||
|
),
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.all(10.0),
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
const Expanded(
|
||||||
|
child: BodyMedium(
|
||||||
|
text: 'Effective Time',
|
||||||
|
fontWeight: FontWeight.normal,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
SizedBox(
|
||||||
|
width: MediaQuery.of(context).size.width / 3.5,
|
||||||
|
child: InkWell(
|
||||||
|
onTap: () {
|
||||||
|
|
||||||
|
BlocProvider.of<SmartDoorBloc>(context).add(SelectTimeEvent(context: context, isEffective: true));
|
||||||
|
},
|
||||||
|
child: Text(
|
||||||
|
BlocProvider.of<SmartDoorBloc>(context).effectiveTime,
|
||||||
|
style: TextStyle(fontSize: 14,
|
||||||
|
color: BlocProvider.of<SmartDoorBloc>(context).effectiveTime ==
|
||||||
|
'Select Time'
|
||||||
|
? ColorsManager.textGray
|
||||||
|
: null),
|
||||||
|
),
|
||||||
|
)),
|
||||||
|
],),
|
||||||
|
),
|
||||||
|
const Divider(
|
||||||
|
color: ColorsManager.graysColor,
|
||||||
|
),
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.all(10.0),
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
const Expanded(
|
||||||
|
child: BodyMedium(
|
||||||
|
text: 'Expiration Time',
|
||||||
|
fontWeight: FontWeight.normal,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
SizedBox(
|
||||||
|
width: MediaQuery.of(context).size.width / 3.5,
|
||||||
|
child: InkWell(
|
||||||
|
onTap: () {
|
||||||
|
BlocProvider.of<SmartDoorBloc>(context).add(
|
||||||
|
SelectTimeEvent(
|
||||||
|
context: context, isEffective: false));
|
||||||
|
},
|
||||||
|
child: Text(
|
||||||
|
BlocProvider.of<SmartDoorBloc>(context).expirationTime,
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 14,
|
||||||
|
color: BlocProvider.of<SmartDoorBloc>(context).expirationTime == 'Select Time'
|
||||||
|
? ColorsManager.textGray
|
||||||
|
: null),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,228 @@
|
|||||||
|
|
||||||
|
import 'package:flutter/cupertino.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter/services.dart';
|
||||||
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
import 'package:syncrow_app/features/devices/bloc/smart_door_bloc/smart_door_bloc.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/view/widgets/smart_door/repeat_widget.dart';
|
||||||
|
import 'package:syncrow_app/features/shared_widgets/default_button.dart';
|
||||||
|
import 'package:syncrow_app/features/shared_widgets/default_container.dart';
|
||||||
|
import 'package:syncrow_app/features/shared_widgets/default_scaffold.dart';
|
||||||
|
import 'package:syncrow_app/features/shared_widgets/door_lock_button.dart';
|
||||||
|
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_large.dart';
|
||||||
|
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_medium.dart';
|
||||||
|
import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
|
||||||
|
import 'package:syncrow_app/utils/resource_manager/font_manager.dart';
|
||||||
|
|
||||||
|
class OfflineOneTimePasswordPage extends StatelessWidget {
|
||||||
|
final String? deviceId;
|
||||||
|
final String? type;
|
||||||
|
const OfflineOneTimePasswordPage({super.key, this.deviceId, this.type});
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
bool isRepeat = false;
|
||||||
|
bool generated = false;
|
||||||
|
return BlocProvider(
|
||||||
|
create: (BuildContext context) => SmartDoorBloc(deviceId: deviceId!),
|
||||||
|
child: BlocConsumer<SmartDoorBloc, SmartDoorState>(listener: (context, state) {
|
||||||
|
if (state is FailedState) {
|
||||||
|
ScaffoldMessenger.of(context).showSnackBar(
|
||||||
|
SnackBar(
|
||||||
|
content: Text(state.errorMessage),
|
||||||
|
backgroundColor: Colors.red,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (state is IsRepeatState){
|
||||||
|
isRepeat = state.repeat;
|
||||||
|
}
|
||||||
|
if (state is GeneratePasswordOneTimestate ){
|
||||||
|
generated = state.generated;
|
||||||
|
}
|
||||||
|
}, builder: (context, state) {
|
||||||
|
final smartDoorBloc = BlocProvider.of<SmartDoorBloc>(context);
|
||||||
|
return DefaultScaffold(
|
||||||
|
appBar: AppBar(
|
||||||
|
backgroundColor: Colors.transparent,
|
||||||
|
centerTitle: true,
|
||||||
|
title: const BodyLarge(
|
||||||
|
text: 'Create One-Time Password',
|
||||||
|
fontColor: ColorsManager.primaryColor,
|
||||||
|
fontWeight: FontsManager.bold,
|
||||||
|
),
|
||||||
|
leading: IconButton(
|
||||||
|
onPressed: () {
|
||||||
|
Navigator.of(context).pop(true);
|
||||||
|
},
|
||||||
|
icon: const Icon(Icons.arrow_back)
|
||||||
|
),
|
||||||
|
),
|
||||||
|
child: state is LoadingInitialState
|
||||||
|
? const Center(child: CircularProgressIndicator())
|
||||||
|
: SingleChildScrollView(
|
||||||
|
child: Column(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
const BodyMedium(
|
||||||
|
text: 'Save the password immediately. The password is not displayed in the app.',
|
||||||
|
fontWeight: FontWeight.normal,
|
||||||
|
fontColor: ColorsManager.grayColor,
|
||||||
|
),
|
||||||
|
const SizedBox(
|
||||||
|
height: 20,
|
||||||
|
),
|
||||||
|
const BodyMedium(
|
||||||
|
text: '7-Digit Password',
|
||||||
|
fontWeight: FontWeight.normal,
|
||||||
|
fontColor: ColorsManager.grayColor,
|
||||||
|
),
|
||||||
|
DefaultContainer(
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 15, vertical: 15),
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
mainAxisSize: MainAxisSize.max,
|
||||||
|
children: [
|
||||||
|
Flexible(
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
children:smartDoorBloc.passwordController.text.isEmpty?
|
||||||
|
List.generate(10, (index) {
|
||||||
|
return const Padding(
|
||||||
|
padding: EdgeInsets.symmetric(horizontal: 4.0,vertical: 15),
|
||||||
|
child: Icon(
|
||||||
|
Icons.circle,
|
||||||
|
size: 20.0,
|
||||||
|
color: Colors.black,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}) :[
|
||||||
|
Expanded(
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
child: BodyLarge(
|
||||||
|
style: const TextStyle(
|
||||||
|
color: ColorsManager.primaryColor,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
letterSpacing: 8.0 ,
|
||||||
|
fontSize: 25,
|
||||||
|
wordSpacing: 2),
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
text: smartDoorBloc.passwordController.text,
|
||||||
|
fontSize: 25,
|
||||||
|
),),
|
||||||
|
IconButton(
|
||||||
|
onPressed: () async {
|
||||||
|
await Clipboard.setData(ClipboardData(
|
||||||
|
text: smartDoorBloc.passwordController.text));
|
||||||
|
},
|
||||||
|
icon: const Icon(Icons.copy)
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
)),
|
||||||
|
const SizedBox(
|
||||||
|
width: 10,
|
||||||
|
),
|
||||||
|
|
||||||
|
],
|
||||||
|
),
|
||||||
|
if(smartDoorBloc.passwordController.text.isNotEmpty)
|
||||||
|
Column(
|
||||||
|
children: [
|
||||||
|
const Divider(
|
||||||
|
color: ColorsManager.graysColor,
|
||||||
|
),
|
||||||
|
Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
child: Container(
|
||||||
|
padding: const EdgeInsets.all(10.0),
|
||||||
|
child: const BodyMedium(
|
||||||
|
text: 'Password Name',
|
||||||
|
fontWeight: FontWeight.normal,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
SizedBox(
|
||||||
|
width: MediaQuery.of(context).size.width / 2.6,
|
||||||
|
child: TextFormField(
|
||||||
|
controller: BlocProvider.of<SmartDoorBloc>(context).passwordNameController,
|
||||||
|
decoration: const InputDecoration(
|
||||||
|
hintText: 'Enter The Name',
|
||||||
|
hintStyle: TextStyle(
|
||||||
|
fontSize: 14, color: ColorsManager.textGray)),
|
||||||
|
)),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
|
||||||
|
],
|
||||||
|
),
|
||||||
|
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(
|
||||||
|
height: 20,
|
||||||
|
),
|
||||||
|
const BodyMedium(
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
text: 'Save the password immediately. The password is not displayed in the app.',
|
||||||
|
fontWeight: FontWeight.normal,
|
||||||
|
fontColor: ColorsManager.grayColor,
|
||||||
|
),
|
||||||
|
|
||||||
|
// NameTimeWidget(type:type!),
|
||||||
|
const SizedBox(
|
||||||
|
height: 20,
|
||||||
|
),
|
||||||
|
Center(
|
||||||
|
child: SizedBox(
|
||||||
|
width: MediaQuery.of(context).size.width/1.5,
|
||||||
|
child: DoorLockButton(
|
||||||
|
isDone: generated,
|
||||||
|
isLoading: smartDoorBloc.isSavingPassword ,
|
||||||
|
borderRadius: 30,
|
||||||
|
backgroundColor:ColorsManager.primaryColor ,
|
||||||
|
onPressed: () async {
|
||||||
|
if(generated==false){
|
||||||
|
smartDoorBloc.add(GenerateAndSavePasswordOneTimeEvent(context: context));
|
||||||
|
await Clipboard.setData(
|
||||||
|
ClipboardData(text: smartDoorBloc.passwordController.text)
|
||||||
|
);
|
||||||
|
}else{
|
||||||
|
if(smartDoorBloc.passwordNameController.text.isNotEmpty){
|
||||||
|
smartDoorBloc.add(RenamePasswordEvent());
|
||||||
|
}
|
||||||
|
Navigator.of(context).pop(true);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
child: const BodyMedium(
|
||||||
|
text: 'Obtain Password',
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
fontColor: Colors.white,
|
||||||
|
),),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(
|
||||||
|
height: 20,
|
||||||
|
),
|
||||||
|
isRepeat? const RepeatWidget():const SizedBox(),
|
||||||
|
const SizedBox(
|
||||||
|
height: 40,
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
}
|
@ -1,4 +1,3 @@
|
|||||||
import 'package:day_picker/day_picker.dart';
|
|
||||||
import 'package:flutter/cupertino.dart';
|
import 'package:flutter/cupertino.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
@ -7,6 +6,8 @@ import 'package:pin_code_fields/pin_code_fields.dart';
|
|||||||
import 'package:syncrow_app/features/devices/bloc/smart_door_bloc/smart_door_bloc.dart';
|
import 'package:syncrow_app/features/devices/bloc/smart_door_bloc/smart_door_bloc.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_event.dart';
|
||||||
import 'package:syncrow_app/features/devices/bloc/smart_door_bloc/smart_door_state.dart';
|
import 'package:syncrow_app/features/devices/bloc/smart_door_bloc/smart_door_state.dart';
|
||||||
|
import 'package:syncrow_app/features/devices/view/widgets/name_time_widget.dart';
|
||||||
|
import 'package:syncrow_app/features/devices/view/widgets/smart_door/repeat_widget.dart';
|
||||||
import 'package:syncrow_app/features/shared_widgets/default_container.dart';
|
import 'package:syncrow_app/features/shared_widgets/default_container.dart';
|
||||||
import 'package:syncrow_app/features/shared_widgets/default_scaffold.dart';
|
import 'package:syncrow_app/features/shared_widgets/default_scaffold.dart';
|
||||||
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_large.dart';
|
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_large.dart';
|
||||||
@ -14,15 +15,15 @@ import 'package:syncrow_app/features/shared_widgets/text_widgets/body_medium.dar
|
|||||||
import 'package:syncrow_app/utils/helpers/snack_bar.dart';
|
import 'package:syncrow_app/utils/helpers/snack_bar.dart';
|
||||||
import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
|
import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
|
||||||
import 'package:syncrow_app/utils/resource_manager/font_manager.dart';
|
import 'package:syncrow_app/utils/resource_manager/font_manager.dart';
|
||||||
import 'package:time_picker_spinner/time_picker_spinner.dart';
|
|
||||||
|
|
||||||
class CreateTemporaryPassword extends StatelessWidget {
|
class CreateTemporaryPassword extends StatelessWidget {
|
||||||
final String? deviceId;
|
final String? deviceId;
|
||||||
final String? type;
|
final String? type;
|
||||||
|
|
||||||
const CreateTemporaryPassword({super.key, this.deviceId, this.type});
|
const CreateTemporaryPassword({super.key, this.deviceId, this.type});
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
bool isRepeat = false;
|
||||||
|
bool generated = false;
|
||||||
return BlocProvider(
|
return BlocProvider(
|
||||||
create: (BuildContext context) => SmartDoorBloc(deviceId: deviceId!),
|
create: (BuildContext context) => SmartDoorBloc(deviceId: deviceId!),
|
||||||
child: BlocConsumer<SmartDoorBloc, SmartDoorState>(listener: (context, state) {
|
child: BlocConsumer<SmartDoorBloc, SmartDoorState>(listener: (context, state) {
|
||||||
@ -34,7 +35,14 @@ class CreateTemporaryPassword extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
if (state is IsRepeatState){
|
||||||
|
isRepeat = state.repeat;
|
||||||
|
}
|
||||||
|
if (state is GeneratePasswordOneTimestate ){
|
||||||
|
generated = state.generated;
|
||||||
|
}
|
||||||
}, builder: (context, state) {
|
}, builder: (context, state) {
|
||||||
|
final smartDoorBloc = BlocProvider.of<SmartDoorBloc>(context);
|
||||||
return DefaultScaffold(
|
return DefaultScaffold(
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
backgroundColor: Colors.transparent,
|
backgroundColor: Colors.transparent,
|
||||||
@ -46,19 +54,19 @@ class CreateTemporaryPassword extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
leading: IconButton(
|
leading: IconButton(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
Navigator.of(context).pop('UpdatePage');
|
Navigator.of(context).pop(true);
|
||||||
},
|
},
|
||||||
icon: const Icon(Icons.arrow_back)
|
icon: const Icon(Icons.arrow_back)
|
||||||
),
|
),
|
||||||
actions: [
|
actions:
|
||||||
|
type == 'Online Password'?[
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
BlocProvider.of<SmartDoorBloc>(context)
|
smartDoorBloc.add(SavePasswordEvent(context: context));
|
||||||
.add(SavePasswordEvent(context: context));
|
|
||||||
},
|
},
|
||||||
child: const Text('Save')
|
child: const Text('Save')
|
||||||
)
|
)
|
||||||
],
|
]:null,
|
||||||
),
|
),
|
||||||
child: state is LoadingInitialState
|
child: state is LoadingInitialState
|
||||||
? const Center(child: CircularProgressIndicator())
|
? const Center(child: CircularProgressIndicator())
|
||||||
@ -82,6 +90,8 @@ class CreateTemporaryPassword extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
DefaultContainer(
|
DefaultContainer(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 15, vertical: 15),
|
padding: const EdgeInsets.symmetric(horizontal: 15, vertical: 15),
|
||||||
|
child: Padding(
|
||||||
|
padding: EdgeInsets.symmetric(horizontal: type == 'Online Password'?0:25),
|
||||||
child: Row(
|
child: Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
mainAxisSize: MainAxisSize.max,
|
mainAxisSize: MainAxisSize.max,
|
||||||
@ -91,14 +101,14 @@ class CreateTemporaryPassword extends StatelessWidget {
|
|||||||
child: PinCodeTextField(
|
child: PinCodeTextField(
|
||||||
onCompleted: (value) {
|
onCompleted: (value) {
|
||||||
if (value.split('').every((char) => char == '1')) {
|
if (value.split('').every((char) => char == '1')) {
|
||||||
BlocProvider.of<SmartDoorBloc>(context).passwordController.clear();
|
smartDoorBloc.passwordController.clear();
|
||||||
CustomSnackBar.displaySnackBar('All characters cannot be 1.');
|
CustomSnackBar.displaySnackBar('All characters cannot be 1.');
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
autoDisposeControllers: false,
|
autoDisposeControllers: false,
|
||||||
keyboardType: TextInputType.phone,
|
keyboardType: TextInputType.phone,
|
||||||
length: 7,
|
length: 7,
|
||||||
enabled: true,
|
// enabled:type == 'Online Password'? true:false,
|
||||||
obscureText: false,
|
obscureText: false,
|
||||||
animationType: AnimationType.fade,
|
animationType: AnimationType.fade,
|
||||||
pinTheme: PinTheme(
|
pinTheme: PinTheme(
|
||||||
@ -115,17 +125,17 @@ class CreateTemporaryPassword extends StatelessWidget {
|
|||||||
animationDuration: const Duration(milliseconds: 300),
|
animationDuration: const Duration(milliseconds: 300),
|
||||||
backgroundColor: Colors.white,
|
backgroundColor: Colors.white,
|
||||||
enableActiveFill: false,
|
enableActiveFill: false,
|
||||||
controller: BlocProvider.of<SmartDoorBloc>(context).passwordController,
|
controller: smartDoorBloc.passwordController,
|
||||||
appContext: context,
|
appContext: context,
|
||||||
)),
|
)),
|
||||||
const SizedBox(
|
const SizedBox(
|
||||||
width: 10,
|
width: 10,
|
||||||
),
|
),
|
||||||
|
if(type == 'Online Password')
|
||||||
Flexible(
|
Flexible(
|
||||||
child: InkWell(
|
child: InkWell(
|
||||||
onTap: () {
|
onTap: () {
|
||||||
BlocProvider.of<SmartDoorBloc>(context)
|
smartDoorBloc.add(GeneratePasswordEvent());
|
||||||
.add(GeneratePasswordEvent());
|
|
||||||
},
|
},
|
||||||
child: const BodyMedium(
|
child: const BodyMedium(
|
||||||
text: 'Generate Randomly',
|
text: 'Generate Randomly',
|
||||||
@ -136,126 +146,22 @@ class CreateTemporaryPassword extends StatelessWidget {
|
|||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
BlocProvider.of<SmartDoorBloc>(context).passwordController.text.isNotEmpty
|
),
|
||||||
? TextButton(
|
if(smartDoorBloc.passwordController.text.isNotEmpty)
|
||||||
|
TextButton(
|
||||||
onPressed: () async {
|
onPressed: () async {
|
||||||
await Clipboard.setData(ClipboardData(
|
await Clipboard.setData(ClipboardData(
|
||||||
text: BlocProvider.of<SmartDoorBloc>(context)
|
text: smartDoorBloc.passwordController.text));
|
||||||
.passwordController
|
|
||||||
.text));
|
|
||||||
},
|
},
|
||||||
child: const Text('Copy'))
|
child: const Text('Copy')
|
||||||
: const SizedBox(),
|
),
|
||||||
const SizedBox(
|
const SizedBox(
|
||||||
height: 20,
|
height: 20,
|
||||||
),
|
),
|
||||||
DefaultContainer(
|
NameTimeWidget(),
|
||||||
padding: const EdgeInsets.all(20),
|
|
||||||
child: Column(
|
|
||||||
children: [
|
|
||||||
Row(
|
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
||||||
children: [
|
|
||||||
Expanded(
|
|
||||||
child: Container(
|
|
||||||
padding: const EdgeInsets.all(10.0),
|
|
||||||
child: const BodyMedium(
|
|
||||||
text: 'Password Name',
|
|
||||||
fontWeight: FontWeight.normal,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
SizedBox(
|
|
||||||
width: MediaQuery.of(context).size.width / 2.6,
|
|
||||||
child: TextFormField(
|
|
||||||
controller: BlocProvider.of<SmartDoorBloc>(context)
|
|
||||||
.passwordNameController,
|
|
||||||
decoration: const InputDecoration(
|
|
||||||
hintText: 'Enter The Name',
|
|
||||||
hintStyle: TextStyle(
|
|
||||||
fontSize: 14, color: ColorsManager.textGray)),
|
|
||||||
)),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
const Divider(
|
|
||||||
color: ColorsManager.graysColor,
|
|
||||||
),
|
|
||||||
Padding(
|
|
||||||
padding: const EdgeInsets.all(10.0),
|
|
||||||
child: Row(
|
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
||||||
children: [
|
|
||||||
const Expanded(
|
|
||||||
child: BodyMedium(
|
|
||||||
text: 'Effective Time',
|
|
||||||
fontWeight: FontWeight.normal,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
SizedBox(
|
|
||||||
width: MediaQuery.of(context).size.width / 3.5,
|
|
||||||
child: InkWell(
|
|
||||||
onTap: () {
|
|
||||||
BlocProvider.of<SmartDoorBloc>(context).add(
|
|
||||||
SelectTimeEvent(
|
|
||||||
context: context, isEffective: true));
|
|
||||||
},
|
|
||||||
child: Text(
|
|
||||||
BlocProvider.of<SmartDoorBloc>(context).effectiveTime,
|
|
||||||
style: TextStyle(
|
|
||||||
fontSize: 14,
|
|
||||||
color: BlocProvider.of<SmartDoorBloc>(context)
|
|
||||||
.effectiveTime ==
|
|
||||||
'Select Time'
|
|
||||||
? ColorsManager.textGray
|
|
||||||
: null),
|
|
||||||
),
|
|
||||||
)),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
const Divider(
|
|
||||||
color: ColorsManager.graysColor,
|
|
||||||
),
|
|
||||||
Padding(
|
|
||||||
padding: const EdgeInsets.all(10.0),
|
|
||||||
child: Row(
|
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
||||||
children: [
|
|
||||||
const Expanded(
|
|
||||||
child: BodyMedium(
|
|
||||||
text: 'Expiration Time',
|
|
||||||
fontWeight: FontWeight.normal,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
SizedBox(
|
|
||||||
width: MediaQuery.of(context).size.width / 3.5,
|
|
||||||
child: InkWell(
|
|
||||||
onTap: () {
|
|
||||||
BlocProvider.of<SmartDoorBloc>(context).add(
|
|
||||||
SelectTimeEvent(
|
|
||||||
context: context, isEffective: false));
|
|
||||||
},
|
|
||||||
child: Text(
|
|
||||||
BlocProvider.of<SmartDoorBloc>(context).expirationTime,
|
|
||||||
style: TextStyle(
|
|
||||||
fontSize: 14,
|
|
||||||
color: BlocProvider.of<SmartDoorBloc>(context)
|
|
||||||
.expirationTime ==
|
|
||||||
'Select Time'
|
|
||||||
? ColorsManager.textGray
|
|
||||||
: null),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
)),
|
|
||||||
const SizedBox(
|
const SizedBox(
|
||||||
height: 20,
|
height: 20,
|
||||||
),
|
),
|
||||||
if (type == 'Online Password')
|
|
||||||
DefaultContainer(
|
DefaultContainer(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 5),
|
padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 5),
|
||||||
child: ListTile(
|
child: ListTile(
|
||||||
@ -267,10 +173,9 @@ class CreateTemporaryPassword extends StatelessWidget {
|
|||||||
trailing: Transform.scale(
|
trailing: Transform.scale(
|
||||||
scale: .8,
|
scale: .8,
|
||||||
child: CupertinoSwitch(
|
child: CupertinoSwitch(
|
||||||
value: BlocProvider.of<SmartDoorBloc>(context).repeat,
|
value: smartDoorBloc.repeat,
|
||||||
onChanged: (value) {
|
onChanged: (value) {
|
||||||
BlocProvider.of<SmartDoorBloc>(context)
|
smartDoorBloc.add(ToggleRepeatEvent());
|
||||||
.add(ToggleRepeatEvent());
|
|
||||||
},
|
},
|
||||||
applyTheme: true,
|
applyTheme: true,
|
||||||
)),
|
)),
|
||||||
@ -279,121 +184,7 @@ class CreateTemporaryPassword extends StatelessWidget {
|
|||||||
const SizedBox(
|
const SizedBox(
|
||||||
height: 20,
|
height: 20,
|
||||||
),
|
),
|
||||||
BlocProvider.of<SmartDoorBloc>(context).repeat
|
isRepeat? const RepeatWidget():const SizedBox(),
|
||||||
? DefaultContainer(
|
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 5),
|
|
||||||
child: Column(
|
|
||||||
children: <Widget>[
|
|
||||||
Padding(
|
|
||||||
padding: const EdgeInsets.all(8.0),
|
|
||||||
child: Row(
|
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
||||||
children: [
|
|
||||||
InkWell(
|
|
||||||
onTap: () {
|
|
||||||
BlocProvider.of<SmartDoorBloc>(context)
|
|
||||||
.add(const SetStartEndTimeEvent(val: true));
|
|
||||||
},
|
|
||||||
child: BodyMedium(
|
|
||||||
text: 'Start',
|
|
||||||
fontColor: BlocProvider.of<SmartDoorBloc>(context)
|
|
||||||
.isStartEndTime ==
|
|
||||||
false
|
|
||||||
? Colors.black
|
|
||||||
: Colors.blue,
|
|
||||||
fontSize: 18,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
InkWell(
|
|
||||||
onTap: () {
|
|
||||||
BlocProvider.of<SmartDoorBloc>(context)
|
|
||||||
.add(const SetStartEndTimeEvent(val: false));
|
|
||||||
},
|
|
||||||
child: BodyMedium(
|
|
||||||
text: 'End',
|
|
||||||
fontColor: BlocProvider.of<SmartDoorBloc>(context)
|
|
||||||
.isStartEndTime
|
|
||||||
? Colors.black
|
|
||||||
: Colors.blue,
|
|
||||||
fontSize: 18,
|
|
||||||
),
|
|
||||||
)
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
const Divider(
|
|
||||||
color: ColorsManager.graysColor,
|
|
||||||
),
|
|
||||||
Container(
|
|
||||||
height: 110,
|
|
||||||
child: BlocProvider.of<SmartDoorBloc>(context).isStartEndTime
|
|
||||||
? TimePickerSpinner(
|
|
||||||
time:
|
|
||||||
BlocProvider.of<SmartDoorBloc>(context).startTime,
|
|
||||||
is24HourMode: false,
|
|
||||||
itemHeight: 40,
|
|
||||||
normalTextStyle: const TextStyle(
|
|
||||||
color: Colors.grey,
|
|
||||||
fontSize: 24,
|
|
||||||
),
|
|
||||||
highlightedTextStyle:
|
|
||||||
const TextStyle(fontSize: 30, color: Colors.blue),
|
|
||||||
onTimeChange: (time) {
|
|
||||||
BlocProvider.of<SmartDoorBloc>(context).add(
|
|
||||||
ChangeTimeEvent(
|
|
||||||
val: time,
|
|
||||||
isStartEndTime:
|
|
||||||
BlocProvider.of<SmartDoorBloc>(context)
|
|
||||||
.isStartEndTime));
|
|
||||||
},
|
|
||||||
)
|
|
||||||
: Container(
|
|
||||||
child: TimePickerSpinner(
|
|
||||||
time:
|
|
||||||
BlocProvider.of<SmartDoorBloc>(context).endTime,
|
|
||||||
is24HourMode: false,
|
|
||||||
itemHeight: 40,
|
|
||||||
normalTextStyle: const TextStyle(
|
|
||||||
color: Colors.grey,
|
|
||||||
fontSize: 24,
|
|
||||||
),
|
|
||||||
highlightedTextStyle: const TextStyle(
|
|
||||||
fontSize: 30, color: Colors.blue),
|
|
||||||
onTimeChange: (time) {
|
|
||||||
BlocProvider.of<SmartDoorBloc>(context).add(
|
|
||||||
ChangeTimeEvent(
|
|
||||||
val: time,
|
|
||||||
isStartEndTime:
|
|
||||||
BlocProvider.of<SmartDoorBloc>(
|
|
||||||
context)
|
|
||||||
.isStartEndTime));
|
|
||||||
},
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
const Divider(
|
|
||||||
color: ColorsManager.graysColor,
|
|
||||||
),
|
|
||||||
const SizedBox(height: 20),
|
|
||||||
SelectWeekDays(
|
|
||||||
width: MediaQuery.of(context).size.width / 1,
|
|
||||||
fontSize: 18,
|
|
||||||
fontWeight: FontWeight.w600,
|
|
||||||
days: BlocProvider.of<SmartDoorBloc>(context).days,
|
|
||||||
border: false,
|
|
||||||
selectedDayTextColor: Colors.black,
|
|
||||||
unSelectedDayTextColor: Colors.grey,
|
|
||||||
boxDecoration: BoxDecoration(
|
|
||||||
borderRadius: BorderRadius.circular(30.0),
|
|
||||||
color: Colors.white),
|
|
||||||
onSelect: (values) {
|
|
||||||
BlocProvider.of<SmartDoorBloc>(context).selectedDay =
|
|
||||||
values;
|
|
||||||
},
|
|
||||||
),
|
|
||||||
],
|
|
||||||
))
|
|
||||||
: const SizedBox(),
|
|
||||||
const SizedBox(
|
const SizedBox(
|
||||||
height: 40,
|
height: 40,
|
||||||
)
|
)
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:intl/intl.dart';
|
import 'package:intl/intl.dart';
|
||||||
|
import 'package:syncrow_app/features/devices/model/offline_password_model.dart';
|
||||||
import 'package:syncrow_app/features/devices/model/temporary_password_model.dart';
|
import 'package:syncrow_app/features/devices/model/temporary_password_model.dart';
|
||||||
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_medium.dart';
|
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_medium.dart';
|
||||||
import 'package:syncrow_app/utils/context_extension.dart';
|
import 'package:syncrow_app/utils/context_extension.dart';
|
||||||
@ -7,13 +8,15 @@ import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
|
|||||||
import 'package:syncrow_app/utils/resource_manager/font_manager.dart';
|
import 'package:syncrow_app/utils/resource_manager/font_manager.dart';
|
||||||
|
|
||||||
class DoorDialog extends StatefulWidget {
|
class DoorDialog extends StatefulWidget {
|
||||||
final String title;
|
final String? title;
|
||||||
final TemporaryPassword value;
|
final TemporaryPassword? temporaryPassword;
|
||||||
|
final OfflinePasswordModel? offline;
|
||||||
|
|
||||||
const DoorDialog({
|
const DoorDialog({
|
||||||
super.key,
|
super.key,
|
||||||
required this.title,
|
this.title,
|
||||||
required this.value,
|
this.offline,
|
||||||
|
this.temporaryPassword,
|
||||||
});
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -28,16 +31,18 @@ class DoorDialogState extends State<DoorDialog> {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
final effectiveTime = widget.temporaryPassword?.effectiveTime ??int.parse( widget.offline?.gmtStart);
|
||||||
|
final invalidTime = widget.temporaryPassword?.invalidTime ?? int.parse(widget.offline?.gmtExpired);
|
||||||
|
|
||||||
final DateTime effectiveDateTime =
|
final DateTime effectiveDateTime =
|
||||||
DateTime.fromMillisecondsSinceEpoch(widget.value.effectiveTime * 1000, isUtc: false);
|
DateTime.fromMillisecondsSinceEpoch(effectiveTime! * 1000, isUtc: false);
|
||||||
String formattedDateEffectiveTime = DateFormat('yyyy-MM-dd').format(effectiveDateTime);
|
String formattedDateEffectiveTime = DateFormat('yyyy-MM-dd').format(effectiveDateTime);
|
||||||
String formattedTimeEffectiveTime = DateFormat('HH:mm:ss').format(effectiveDateTime);
|
String formattedTimeEffectiveTime = DateFormat('hh:mm a').format(effectiveDateTime);
|
||||||
|
|
||||||
final DateTime expiredDateTime =
|
final DateTime expiredDateTime =
|
||||||
DateTime.fromMillisecondsSinceEpoch(widget.value.invalidTime * 1000, isUtc: false);
|
DateTime.fromMillisecondsSinceEpoch(invalidTime! * 1000, isUtc: false);
|
||||||
String formattedDateExpiredDateTime = DateFormat('yyyy-MM-dd').format(expiredDateTime);
|
String formattedDateExpiredDateTime = DateFormat('yyyy-MM-dd').format(expiredDateTime);
|
||||||
String formattedTimeExpiredDateTime = DateFormat('HH:mm:ss').format(expiredDateTime);
|
String formattedTimeExpiredDateTime = DateFormat('hh:mm a').format(expiredDateTime);
|
||||||
|
|
||||||
return Dialog(
|
return Dialog(
|
||||||
child: Container(
|
child: Container(
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
@ -49,7 +54,7 @@ class DoorDialogState extends State<DoorDialog> {
|
|||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
children: [
|
children: [
|
||||||
BodyMedium(
|
BodyMedium(
|
||||||
text: widget.title,
|
text: widget.title ?? '',
|
||||||
style: context.bodyMedium.copyWith(
|
style: context.bodyMedium.copyWith(
|
||||||
color: ColorsManager.primaryColorWithOpacity,
|
color: ColorsManager.primaryColorWithOpacity,
|
||||||
fontWeight: FontsManager.extraBold,
|
fontWeight: FontsManager.extraBold,
|
||||||
@ -111,6 +116,7 @@ class DoorDialogState extends State<DoorDialog> {
|
|||||||
width: double.infinity,
|
width: double.infinity,
|
||||||
color: ColorsManager.greyColor,
|
color: ColorsManager.greyColor,
|
||||||
),
|
),
|
||||||
|
widget.temporaryPassword?.effectiveTime!=null?
|
||||||
Row(
|
Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
||||||
children: [
|
children: [
|
||||||
@ -142,6 +148,27 @@ class DoorDialogState extends State<DoorDialog> {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
):
|
||||||
|
Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
||||||
|
children: [
|
||||||
|
Container(
|
||||||
|
height: 50,
|
||||||
|
child: InkWell(
|
||||||
|
onTap: () {
|
||||||
|
Navigator.pop(context);
|
||||||
|
},
|
||||||
|
child: Center(
|
||||||
|
child: BodyMedium(
|
||||||
|
text: 'Cancel',
|
||||||
|
style: context.bodyMedium.copyWith(color: ColorsManager.greyColor),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
|
),
|
||||||
|
|
||||||
|
],
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
@ -0,0 +1,295 @@
|
|||||||
|
import 'package:flutter/cupertino.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter/services.dart';
|
||||||
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
import 'package:syncrow_app/features/devices/bloc/smart_door_bloc/smart_door_bloc.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/view/widgets/smart_door/repeat_widget.dart';
|
||||||
|
import 'package:syncrow_app/features/shared_widgets/default_container.dart';
|
||||||
|
import 'package:syncrow_app/features/shared_widgets/default_scaffold.dart';
|
||||||
|
import 'package:syncrow_app/features/shared_widgets/door_lock_button.dart';
|
||||||
|
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_large.dart';
|
||||||
|
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_medium.dart';
|
||||||
|
import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
|
||||||
|
import 'package:syncrow_app/utils/resource_manager/font_manager.dart';
|
||||||
|
|
||||||
|
class CreateOfflineTimeLimitPasswordPage extends StatelessWidget {
|
||||||
|
final String? deviceId;
|
||||||
|
final String? type;
|
||||||
|
const CreateOfflineTimeLimitPasswordPage({super.key, this.deviceId, this.type});
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
bool isRepeat = false;
|
||||||
|
bool generated = false;
|
||||||
|
return BlocProvider(
|
||||||
|
create: (BuildContext context) => SmartDoorBloc(deviceId: deviceId!),
|
||||||
|
child: BlocConsumer<SmartDoorBloc, SmartDoorState>(
|
||||||
|
listener: (context, state) {
|
||||||
|
if (state is FailedState) {
|
||||||
|
ScaffoldMessenger.of(context).showSnackBar(
|
||||||
|
SnackBar(
|
||||||
|
content: Text(state.errorMessage),
|
||||||
|
backgroundColor: Colors.red,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (state is IsRepeatState) {
|
||||||
|
isRepeat = state.repeat;
|
||||||
|
}
|
||||||
|
if (state is GeneratePasswordOneTimestate) {
|
||||||
|
generated = state.generated;
|
||||||
|
}
|
||||||
|
}, builder: (context, state) {
|
||||||
|
final smartDoorBloc = BlocProvider.of<SmartDoorBloc>(context);
|
||||||
|
return DefaultScaffold(
|
||||||
|
appBar: AppBar(
|
||||||
|
backgroundColor: Colors.transparent,
|
||||||
|
centerTitle: true,
|
||||||
|
title: const BodyLarge(
|
||||||
|
text: 'Create Time-Limited Password',
|
||||||
|
fontColor: ColorsManager.primaryColor,
|
||||||
|
fontWeight: FontsManager.bold,
|
||||||
|
),
|
||||||
|
leading: IconButton(
|
||||||
|
onPressed: () {
|
||||||
|
Navigator.of(context).pop(true);
|
||||||
|
},
|
||||||
|
icon: const Icon(Icons.arrow_back)),
|
||||||
|
),
|
||||||
|
child: state is LoadingInitialState
|
||||||
|
? const Center(child: CircularProgressIndicator())
|
||||||
|
: SingleChildScrollView(
|
||||||
|
child: Column(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
const BodyMedium(
|
||||||
|
text:
|
||||||
|
'Save the password immediately. The password is not displayed in the app.',
|
||||||
|
fontWeight: FontWeight.normal,
|
||||||
|
fontColor: ColorsManager.grayColor,
|
||||||
|
),
|
||||||
|
const SizedBox(
|
||||||
|
height: 20,
|
||||||
|
),
|
||||||
|
|
||||||
|
DefaultContainer(
|
||||||
|
padding: const EdgeInsets.symmetric(
|
||||||
|
horizontal: 10, vertical: 15),
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
Row(
|
||||||
|
mainAxisAlignment:
|
||||||
|
MainAxisAlignment.spaceBetween,
|
||||||
|
mainAxisSize: MainAxisSize.max,
|
||||||
|
children: [
|
||||||
|
Flexible(
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
children: smartDoorBloc.passwordController.text.isEmpty ?
|
||||||
|
List.generate(10, (index) {
|
||||||
|
return const Padding(
|
||||||
|
padding: EdgeInsets.symmetric(
|
||||||
|
horizontal: 4.0,
|
||||||
|
vertical: 15),
|
||||||
|
child: Icon(
|
||||||
|
Icons.circle,
|
||||||
|
size: 20.0,
|
||||||
|
color: Colors.black,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}) : [
|
||||||
|
Expanded(
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
child: BodyLarge(
|
||||||
|
style: const TextStyle(
|
||||||
|
color: ColorsManager.primaryColor,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
letterSpacing: 8.0,
|
||||||
|
fontSize: 25,
|
||||||
|
wordSpacing: 2),
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
text: smartDoorBloc.passwordController.text,
|
||||||
|
fontSize: 25,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
IconButton(
|
||||||
|
onPressed: () async {
|
||||||
|
await Clipboard.setData(
|
||||||
|
ClipboardData(text: smartDoorBloc.passwordController.text)
|
||||||
|
);
|
||||||
|
},
|
||||||
|
icon: const Icon(Icons.copy)),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
)),
|
||||||
|
const SizedBox(
|
||||||
|
width: 10,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
DefaultContainer(
|
||||||
|
padding: const EdgeInsets.all(20),
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
child: Container(
|
||||||
|
padding: const EdgeInsets.all(10.0),
|
||||||
|
child: const BodyMedium(
|
||||||
|
text: 'Password Name',
|
||||||
|
fontWeight: FontWeight.normal,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
SizedBox(
|
||||||
|
width: MediaQuery.of(context).size.width / 2.6,
|
||||||
|
child: TextFormField(
|
||||||
|
controller: BlocProvider.of<SmartDoorBloc>(context).passwordNameController,
|
||||||
|
decoration:
|
||||||
|
const InputDecoration(
|
||||||
|
hintText: 'Enter The Name',
|
||||||
|
hintStyle: TextStyle(
|
||||||
|
fontSize: 14,
|
||||||
|
color: ColorsManager.textGray)
|
||||||
|
),
|
||||||
|
)),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
Column(
|
||||||
|
children: [
|
||||||
|
const Divider(color: ColorsManager.graysColor,),
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.all(10.0),
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
const Expanded(
|
||||||
|
child: BodyMedium(
|
||||||
|
text: 'Effective Time',
|
||||||
|
fontWeight: FontWeight.normal,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
SizedBox(
|
||||||
|
width: MediaQuery.of(context).size.width / 3.5,
|
||||||
|
child: InkWell(
|
||||||
|
onTap: () {
|
||||||
|
BlocProvider.of<SmartDoorBloc>(context).add(SelectTimeEvent(context: context, isEffective: true));
|
||||||
|
},
|
||||||
|
child: Text(
|
||||||
|
BlocProvider.of<SmartDoorBloc>(context).effectiveTime,
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 14,
|
||||||
|
color: BlocProvider.of<SmartDoorBloc>(context).effectiveTime ==
|
||||||
|
'Select Time' ? ColorsManager.textGray : null),
|
||||||
|
),
|
||||||
|
)),],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const Divider(
|
||||||
|
color: ColorsManager.graysColor,
|
||||||
|
),
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.all(10.0),
|
||||||
|
child: Row(mainAxisAlignment:
|
||||||
|
MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
const Expanded(
|
||||||
|
child: BodyMedium(
|
||||||
|
text: 'Expiration Time',
|
||||||
|
fontWeight: FontWeight.normal,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
SizedBox(
|
||||||
|
width: MediaQuery.of(context).size.width / 3.5,
|
||||||
|
child: InkWell(
|
||||||
|
onTap: () {
|
||||||
|
BlocProvider.of<SmartDoorBloc>(context).add(SelectTimeEvent(
|
||||||
|
context: context,
|
||||||
|
isEffective: false));
|
||||||
|
},
|
||||||
|
child: Text(
|
||||||
|
BlocProvider.of<SmartDoorBloc>(context).expirationTime,
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 14,
|
||||||
|
color: BlocProvider.of<SmartDoorBloc>(context)
|
||||||
|
.expirationTime == 'Select Time' ? ColorsManager
|
||||||
|
.textGray : null),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
)),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(
|
||||||
|
height: 20,
|
||||||
|
),
|
||||||
|
const BodyMedium(
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
text:
|
||||||
|
'Use the time-limited password at least once within 24 hours after the password takes effect. Otherwise, the password becomes invalid.',
|
||||||
|
fontWeight: FontWeight.normal,
|
||||||
|
fontColor: ColorsManager.grayColor,
|
||||||
|
),
|
||||||
|
// NameTimeWidget(type:type!),
|
||||||
|
const SizedBox(
|
||||||
|
height: 20,
|
||||||
|
),
|
||||||
|
Center(
|
||||||
|
child: SizedBox(
|
||||||
|
width: MediaQuery.of(context).size.width / 1.5,
|
||||||
|
child: DoorLockButton(
|
||||||
|
isDone: generated,
|
||||||
|
isLoading: smartDoorBloc.isSavingPassword,
|
||||||
|
borderRadius: 30,
|
||||||
|
backgroundColor: ColorsManager.primaryColor,
|
||||||
|
onPressed: () async {
|
||||||
|
if (generated == false) {
|
||||||
|
smartDoorBloc.add(
|
||||||
|
GenerateAndSavePasswordTimeLimitEvent(context: context));
|
||||||
|
await Clipboard.setData(
|
||||||
|
ClipboardData(text: smartDoorBloc.passwordController.text)
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
if(smartDoorBloc.passwordNameController.text.isNotEmpty){
|
||||||
|
smartDoorBloc.add(RenamePasswordEvent());
|
||||||
|
}
|
||||||
|
Navigator.of(context).pop(true);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
child: const BodyMedium(
|
||||||
|
text: 'Obtain Password',
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
fontColor: Colors.white,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(
|
||||||
|
height: 20,
|
||||||
|
),
|
||||||
|
isRepeat ? const RepeatWidget() : const SizedBox(),
|
||||||
|
const SizedBox(
|
||||||
|
height: 40,
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,111 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
import 'package:flutter_svg/svg.dart';
|
||||||
|
import 'package:syncrow_app/features/devices/bloc/smart_door_bloc/smart_door_bloc.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/view/widgets/offline_one_time_password_page.dart';
|
||||||
|
import 'package:syncrow_app/features/devices/view/widgets/smart_door/door_dialog.dart';
|
||||||
|
import 'package:syncrow_app/features/shared_widgets/default_container.dart';
|
||||||
|
import 'package:syncrow_app/features/shared_widgets/default_scaffold.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 OnetimePasswordPage extends StatelessWidget {
|
||||||
|
final String? deviceId;
|
||||||
|
const OnetimePasswordPage({super.key, this.deviceId,});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return BlocProvider(
|
||||||
|
create: (BuildContext context) => SmartDoorBloc(deviceId: deviceId!)..add(InitialOneTimePassword( )),
|
||||||
|
child: BlocConsumer<SmartDoorBloc, SmartDoorState>(
|
||||||
|
listener: (context, state) {
|
||||||
|
if (state is FailedState) {
|
||||||
|
ScaffoldMessenger.of(context).showSnackBar(
|
||||||
|
SnackBar(
|
||||||
|
content: Text(state.errorMessage),
|
||||||
|
backgroundColor: Colors.red,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
builder: (context, state) {
|
||||||
|
final smartDoorBloc = BlocProvider.of<SmartDoorBloc>(context);
|
||||||
|
return DefaultScaffold(
|
||||||
|
title: 'Passwords',
|
||||||
|
actions: [
|
||||||
|
IconButton(
|
||||||
|
onPressed: () {
|
||||||
|
Navigator.of(context).push(
|
||||||
|
MaterialPageRoute(builder: (context) => OfflineOneTimePasswordPage(deviceId: deviceId, )
|
||||||
|
)).then((result) {
|
||||||
|
if(result!=null){
|
||||||
|
smartDoorBloc.add(InitialOneTimePassword());
|
||||||
|
smartDoorBloc.add(InitialOneTimePassword());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
icon: const Icon(Icons.add)
|
||||||
|
)
|
||||||
|
],
|
||||||
|
child: Builder(
|
||||||
|
builder: (context) {
|
||||||
|
return state is LoadingInitialState
|
||||||
|
? const Center(child: CircularProgressIndicator())
|
||||||
|
: Center(
|
||||||
|
child: smartDoorBloc.oneTimePasswords!.isNotEmpty
|
||||||
|
? ListView.builder(
|
||||||
|
itemCount: smartDoorBloc.oneTimePasswords!.length,
|
||||||
|
itemBuilder: (context, index) {
|
||||||
|
return Padding(
|
||||||
|
padding: const EdgeInsets.all(5.0),
|
||||||
|
child: DefaultContainer(
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 15, vertical: 10),
|
||||||
|
child: ListTile(
|
||||||
|
contentPadding: EdgeInsets.zero,
|
||||||
|
leading: SvgPicture.asset(Assets.timeLimitedPasswordIcon),
|
||||||
|
title: BodyMedium(
|
||||||
|
text: 'Password Name: ${smartDoorBloc.oneTimePasswords![index].pwdName}',
|
||||||
|
fontWeight: FontWeight.normal,
|
||||||
|
),
|
||||||
|
onTap: () async {
|
||||||
|
final result = await showDialog(
|
||||||
|
context: context,
|
||||||
|
builder: (context) {
|
||||||
|
return DoorDialog(
|
||||||
|
title: 'Password Information',
|
||||||
|
offline: smartDoorBloc.oneTimePasswords![index],
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
},
|
||||||
|
trailing: const Icon(
|
||||||
|
Icons.arrow_forward_ios,
|
||||||
|
color: ColorsManager.greyColor,
|
||||||
|
size: 15,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
) : Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
SvgPicture.asset(Assets.noValidPasswords),
|
||||||
|
const SizedBox(
|
||||||
|
height: 10,
|
||||||
|
),
|
||||||
|
const BodyMedium(text: 'No Valid Passwords')
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
));
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
125
lib/features/devices/view/widgets/smart_door/repeat_widget.dart
Normal file
125
lib/features/devices/view/widgets/smart_door/repeat_widget.dart
Normal file
@ -0,0 +1,125 @@
|
|||||||
|
import 'package:flutter/cupertino.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
import 'package:syncrow_app/features/devices/bloc/smart_door_bloc/smart_door_bloc.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/shared_widgets/default_container.dart';
|
||||||
|
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_medium.dart';
|
||||||
|
import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
|
||||||
|
|
||||||
|
class RepeatWidget extends StatelessWidget {
|
||||||
|
const RepeatWidget({
|
||||||
|
super.key,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
|
||||||
|
return BlocBuilder<SmartDoorBloc, SmartDoorState>(
|
||||||
|
builder: (context, state) {
|
||||||
|
final smartDoorBloc = BlocProvider.of<SmartDoorBloc>(context);
|
||||||
|
return DefaultContainer(
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 5),
|
||||||
|
child: Column(children: <Widget>[
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.all(8.0),
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
InkWell(
|
||||||
|
onTap: () {
|
||||||
|
smartDoorBloc.add(const SetStartEndTimeEvent(val: true));
|
||||||
|
},
|
||||||
|
child: BodyMedium(
|
||||||
|
text: 'Start',
|
||||||
|
fontColor: smartDoorBloc.isStartEndTime == false
|
||||||
|
? Colors.black
|
||||||
|
: Colors.blue,
|
||||||
|
fontSize: 18,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
InkWell(
|
||||||
|
onTap: () {
|
||||||
|
smartDoorBloc.add(const SetStartEndTimeEvent(val: false));
|
||||||
|
},
|
||||||
|
child: BodyMedium(
|
||||||
|
text: 'End',
|
||||||
|
fontColor: smartDoorBloc.isStartEndTime
|
||||||
|
? Colors.black
|
||||||
|
: Colors.blue,
|
||||||
|
fontSize: 18,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const Divider(
|
||||||
|
color: ColorsManager.graysColor,
|
||||||
|
),
|
||||||
|
smartDoorBloc.isStartEndTime
|
||||||
|
? Container(
|
||||||
|
height: 110,
|
||||||
|
child: CupertinoDatePicker(
|
||||||
|
mode: CupertinoDatePickerMode.time,
|
||||||
|
initialDateTime:smartDoorBloc.startTime,
|
||||||
|
onDateTimeChanged: (startTime) {
|
||||||
|
smartDoorBloc.add(ChangeTimeEvent(val: startTime, isStartEndTime: true));
|
||||||
|
},
|
||||||
|
)
|
||||||
|
):SizedBox(
|
||||||
|
height: 110,
|
||||||
|
child: CupertinoDatePicker(
|
||||||
|
mode: CupertinoDatePickerMode.time,
|
||||||
|
initialDateTime:smartDoorBloc.endTime,
|
||||||
|
onDateTimeChanged: (endTime) {
|
||||||
|
smartDoorBloc.add(ChangeTimeEvent(val: endTime, isStartEndTime: false));
|
||||||
|
},
|
||||||
|
)
|
||||||
|
),
|
||||||
|
const Divider(
|
||||||
|
color: ColorsManager.graysColor,
|
||||||
|
),
|
||||||
|
const SizedBox(height: 20),
|
||||||
|
SizedBox(
|
||||||
|
height: MediaQuery.of(context).size.height *0.10,
|
||||||
|
child: ListView(
|
||||||
|
scrollDirection: Axis.horizontal,
|
||||||
|
children: smartDoorBloc.days.map((day) {
|
||||||
|
bool isSelected = smartDoorBloc.selectedDays.contains(day['key']);
|
||||||
|
return Padding(
|
||||||
|
padding: const EdgeInsets.all(8.0),
|
||||||
|
child: InkWell(
|
||||||
|
onTap: () {
|
||||||
|
smartDoorBloc.add(ToggleDaySelectionEvent(key:day['key']!));
|
||||||
|
},
|
||||||
|
child: Container(
|
||||||
|
width: 70,
|
||||||
|
padding: EdgeInsets.symmetric(vertical: 8, horizontal: 8),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
border: Border.all(
|
||||||
|
color: isSelected?
|
||||||
|
Colors.black:ColorsManager.grayColor
|
||||||
|
),
|
||||||
|
color: Colors.transparent,
|
||||||
|
borderRadius: BorderRadius.circular(55),
|
||||||
|
),
|
||||||
|
child: Center(
|
||||||
|
child: Text(
|
||||||
|
day['day']!,
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 18,
|
||||||
|
color: isSelected ? Colors.black : ColorsManager.grayColor,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}).toList(),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
]));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
@ -1,6 +1,8 @@
|
|||||||
import 'package:flutter/cupertino.dart';
|
import 'package:flutter/cupertino.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_svg/svg.dart';
|
import 'package:flutter_svg/svg.dart';
|
||||||
|
import 'package:syncrow_app/features/devices/view/widgets/smart_door/onetime_password_page.dart';
|
||||||
|
import 'package:syncrow_app/features/devices/view/widgets/smart_door/timelimited_password_page.dart';
|
||||||
import 'package:syncrow_app/features/devices/view/widgets/smart_door/view_temporary_password.dart';
|
import 'package:syncrow_app/features/devices/view/widgets/smart_door/view_temporary_password.dart';
|
||||||
import 'package:syncrow_app/features/shared_widgets/default_container.dart';
|
import 'package:syncrow_app/features/shared_widgets/default_container.dart';
|
||||||
import 'package:syncrow_app/features/shared_widgets/default_scaffold.dart';
|
import 'package:syncrow_app/features/shared_widgets/default_scaffold.dart';
|
||||||
@ -46,7 +48,11 @@ class TemporaryPasswordPage extends StatelessWidget {
|
|||||||
fontWeight: FontWeight.normal,
|
fontWeight: FontWeight.normal,
|
||||||
),
|
),
|
||||||
onTap: () {
|
onTap: () {
|
||||||
Navigator.of(context).push(MaterialPageRoute(builder: (context) => ViewTemporaryPassword(deviceId:deviceId,type:'Online Password'),));
|
Navigator.of(context).push(MaterialPageRoute(builder: (context) =>
|
||||||
|
ViewTemporaryPassword(
|
||||||
|
deviceId:deviceId,
|
||||||
|
type:'Online Password'),
|
||||||
|
));
|
||||||
},
|
},
|
||||||
trailing: const Icon(
|
trailing: const Icon(
|
||||||
Icons.arrow_forward_ios,
|
Icons.arrow_forward_ios,
|
||||||
@ -57,7 +63,6 @@ class TemporaryPasswordPage extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|
||||||
const SizedBox(height: 10),
|
const SizedBox(height: 10),
|
||||||
Column(
|
Column(
|
||||||
mainAxisAlignment: MainAxisAlignment.start,
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
@ -76,7 +81,8 @@ class TemporaryPasswordPage extends StatelessWidget {
|
|||||||
const SizedBox(height: 10),
|
const SizedBox(height: 10),
|
||||||
DefaultContainer(
|
DefaultContainer(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 15, vertical: 20),
|
padding: const EdgeInsets.symmetric(horizontal: 15, vertical: 20),
|
||||||
child: Column(children: [
|
child: Column(
|
||||||
|
children: [
|
||||||
ListTile(
|
ListTile(
|
||||||
contentPadding: EdgeInsets.zero,
|
contentPadding: EdgeInsets.zero,
|
||||||
leading: SvgPicture.asset(Assets.oneTimePassword),
|
leading: SvgPicture.asset(Assets.oneTimePassword),
|
||||||
@ -86,8 +92,7 @@ class TemporaryPasswordPage extends StatelessWidget {
|
|||||||
fontWeight: FontWeight.normal,
|
fontWeight: FontWeight.normal,
|
||||||
),
|
),
|
||||||
onTap: () {
|
onTap: () {
|
||||||
Navigator.of(context).push(MaterialPageRoute(builder: (context) => ViewTemporaryPassword(deviceId:deviceId,type:'One-Time'),));
|
Navigator.of(context).push(MaterialPageRoute(builder: (context) => OnetimePasswordPage(deviceId:deviceId,),));
|
||||||
|
|
||||||
},
|
},
|
||||||
trailing: const Icon(
|
trailing: const Icon(
|
||||||
Icons.arrow_forward_ios,
|
Icons.arrow_forward_ios,
|
||||||
@ -95,7 +100,6 @@ class TemporaryPasswordPage extends StatelessWidget {
|
|||||||
size: 15,
|
size: 15,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
||||||
const Divider(color:ColorsManager.graysColor,),
|
const Divider(color:ColorsManager.graysColor,),
|
||||||
ListTile(
|
ListTile(
|
||||||
contentPadding: EdgeInsets.zero,
|
contentPadding: EdgeInsets.zero,
|
||||||
@ -106,7 +110,7 @@ class TemporaryPasswordPage extends StatelessWidget {
|
|||||||
fontWeight: FontWeight.normal,
|
fontWeight: FontWeight.normal,
|
||||||
),
|
),
|
||||||
onTap: () {
|
onTap: () {
|
||||||
Navigator.of(context).push(MaterialPageRoute(builder: (context) => ViewTemporaryPassword(deviceId:deviceId,type:'Time-Limited'),));
|
Navigator.of(context).push(MaterialPageRoute(builder: (context) => TimeLimitedPasswordPage(deviceId:deviceId,),));
|
||||||
},
|
},
|
||||||
trailing: const Icon(
|
trailing: const Icon(
|
||||||
Icons.arrow_forward_ios,
|
Icons.arrow_forward_ios,
|
||||||
|
@ -0,0 +1,109 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
import 'package:flutter_svg/flutter_svg.dart';
|
||||||
|
import 'package:syncrow_app/features/devices/bloc/smart_door_bloc/smart_door_bloc.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/view/widgets/smart_door/offline_timeLimit_password_page.dart';
|
||||||
|
import 'package:syncrow_app/features/shared_widgets/default_container.dart';
|
||||||
|
import 'package:syncrow_app/features/shared_widgets/default_scaffold.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';
|
||||||
|
import 'door_dialog.dart';
|
||||||
|
|
||||||
|
class TimeLimitedPasswordPage extends StatelessWidget {
|
||||||
|
final String? deviceId;
|
||||||
|
const TimeLimitedPasswordPage({super.key, this.deviceId});
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return BlocProvider(
|
||||||
|
create: (BuildContext context) => SmartDoorBloc(deviceId: deviceId!)..add(InitialTimeLimitPassword()),
|
||||||
|
child: BlocConsumer<SmartDoorBloc, SmartDoorState>(
|
||||||
|
listener: (context, state) {
|
||||||
|
if (state is FailedState) {
|
||||||
|
ScaffoldMessenger.of(context).showSnackBar(
|
||||||
|
SnackBar(
|
||||||
|
content: Text(state.errorMessage),
|
||||||
|
backgroundColor: Colors.red,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
builder: (context, state) {
|
||||||
|
final smartDoorBloc = BlocProvider.of<SmartDoorBloc>(context);
|
||||||
|
return DefaultScaffold(
|
||||||
|
title: 'Passwords',
|
||||||
|
actions: [
|
||||||
|
IconButton(
|
||||||
|
onPressed: () {
|
||||||
|
Navigator.of(context).push(
|
||||||
|
MaterialPageRoute(builder: (context) => CreateOfflineTimeLimitPasswordPage(deviceId: deviceId,)
|
||||||
|
)).then((result) {
|
||||||
|
if (result != null) {
|
||||||
|
smartDoorBloc.add(InitialTimeLimitPassword());
|
||||||
|
smartDoorBloc.add(InitialTimeLimitPassword());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
icon: const Icon(Icons.add)
|
||||||
|
)
|
||||||
|
],
|
||||||
|
child: Builder(
|
||||||
|
builder: (context) {
|
||||||
|
return state is LoadingInitialState
|
||||||
|
? const Center(child: CircularProgressIndicator())
|
||||||
|
: Center(
|
||||||
|
child: smartDoorBloc.timeLimitPasswords!.isNotEmpty
|
||||||
|
? ListView.builder(
|
||||||
|
itemCount: smartDoorBloc.timeLimitPasswords!.length,
|
||||||
|
itemBuilder: (context, index) {
|
||||||
|
return Padding(
|
||||||
|
padding: const EdgeInsets.all(5.0),
|
||||||
|
child: DefaultContainer(
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 15, vertical: 10),
|
||||||
|
child: ListTile(
|
||||||
|
contentPadding: EdgeInsets.zero,
|
||||||
|
leading: SvgPicture.asset(Assets.timeLimitedPasswordIcon),
|
||||||
|
title: BodyMedium(
|
||||||
|
text: 'Password Name: ${smartDoorBloc.timeLimitPasswords![index].pwdName}',
|
||||||
|
fontWeight: FontWeight.normal,
|
||||||
|
),
|
||||||
|
onTap: () async {
|
||||||
|
final result = await showDialog(
|
||||||
|
context: context,
|
||||||
|
builder: (context) {
|
||||||
|
return DoorDialog(
|
||||||
|
title: 'Password Information',
|
||||||
|
offline: smartDoorBloc.timeLimitPasswords![index],
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
trailing: const Icon(
|
||||||
|
Icons.arrow_forward_ios,
|
||||||
|
color: ColorsManager.greyColor,
|
||||||
|
size: 15,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
) : Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
SvgPicture.asset(Assets.noValidPasswords),
|
||||||
|
const SizedBox(
|
||||||
|
height: 10,
|
||||||
|
),
|
||||||
|
const BodyMedium(text: 'No Valid Passwords')
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
));
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -20,8 +20,7 @@ class ViewTemporaryPassword extends StatelessWidget {
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return BlocProvider(
|
return BlocProvider(
|
||||||
create: (BuildContext context) =>
|
create: (BuildContext context) => SmartDoorBloc(deviceId: deviceId!)..add(InitialPasswordsPage( )),
|
||||||
SmartDoorBloc(deviceId: deviceId!)..add(InitialPasswordsPage(type:type )),
|
|
||||||
child: BlocConsumer<SmartDoorBloc, SmartDoorState>(
|
child: BlocConsumer<SmartDoorBloc, SmartDoorState>(
|
||||||
listener: (context, state) {
|
listener: (context, state) {
|
||||||
if (state is FailedState) {
|
if (state is FailedState) {
|
||||||
@ -32,22 +31,25 @@ class ViewTemporaryPassword extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}, builder: (context, state) {
|
},
|
||||||
|
builder: (context, state) {
|
||||||
final smartDoorBloc = BlocProvider.of<SmartDoorBloc>(context);
|
final smartDoorBloc = BlocProvider.of<SmartDoorBloc>(context);
|
||||||
return DefaultScaffold(
|
return DefaultScaffold(
|
||||||
title: 'Passwords',
|
title: 'Passwords',
|
||||||
actions: [
|
actions: [
|
||||||
IconButton(
|
IconButton(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
Navigator.of(context).push(MaterialPageRoute(
|
Navigator.of(context).push(
|
||||||
builder: (context) => CreateTemporaryPassword(deviceId: deviceId, type: type),
|
MaterialPageRoute(builder: (context) =>
|
||||||
)).then((result) {
|
CreateTemporaryPassword(deviceId: deviceId, type: type))).then((result) {
|
||||||
if (result != null && result) {
|
if (result != null && result) {
|
||||||
smartDoorBloc.add(InitialPasswordsPage(type:type ));
|
smartDoorBloc.add(InitialPasswordsPage());
|
||||||
|
smartDoorBloc.add(InitialPasswordsPage());
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
icon: const Icon(Icons.add))
|
icon: const Icon(Icons.add)
|
||||||
|
)
|
||||||
],
|
],
|
||||||
child: Builder(
|
child: Builder(
|
||||||
builder: (context) {
|
builder: (context) {
|
||||||
@ -61,15 +63,13 @@ class ViewTemporaryPassword extends StatelessWidget {
|
|||||||
return Padding(
|
return Padding(
|
||||||
padding: const EdgeInsets.all(5.0),
|
padding: const EdgeInsets.all(5.0),
|
||||||
child: DefaultContainer(
|
child: DefaultContainer(
|
||||||
padding: const EdgeInsets.symmetric(
|
padding: const EdgeInsets.symmetric(horizontal: 15, vertical: 10),
|
||||||
horizontal: 15, vertical: 10),
|
|
||||||
child: ListTile(
|
child: ListTile(
|
||||||
contentPadding: EdgeInsets.zero,
|
contentPadding: EdgeInsets.zero,
|
||||||
leading: SvgPicture.asset(
|
leading: SvgPicture.asset(
|
||||||
Assets.timeLimitedPasswordIcon),
|
Assets.timeLimitedPasswordIcon),
|
||||||
title: BodyMedium(
|
title: BodyMedium(
|
||||||
text:
|
text: 'Password Name: ${smartDoorBloc.temporaryPasswords![index].name}',
|
||||||
'Password Name: ${smartDoorBloc.temporaryPasswords![index].name}',
|
|
||||||
fontWeight: FontWeight.normal,
|
fontWeight: FontWeight.normal,
|
||||||
),
|
),
|
||||||
onTap: () async {
|
onTap: () async {
|
||||||
@ -78,7 +78,7 @@ class ViewTemporaryPassword extends StatelessWidget {
|
|||||||
builder: (context) {
|
builder: (context) {
|
||||||
return DoorDialog(
|
return DoorDialog(
|
||||||
title: 'Password Information',
|
title: 'Password Information',
|
||||||
value: smartDoorBloc.temporaryPasswords![index],
|
temporaryPassword: smartDoorBloc.temporaryPasswords![index],
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
@ -110,6 +110,7 @@ class ViewTemporaryPassword extends StatelessWidget {
|
|||||||
);
|
);
|
||||||
},
|
},
|
||||||
));
|
));
|
||||||
}));
|
})
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
99
lib/features/shared_widgets/door_lock_button.dart
Normal file
99
lib/features/shared_widgets/door_lock_button.dart
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:syncrow_app/utils/context_extension.dart';
|
||||||
|
import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
|
||||||
|
|
||||||
|
class DoorLockButton extends StatelessWidget {
|
||||||
|
const DoorLockButton({
|
||||||
|
super.key,
|
||||||
|
this.enabled = true,
|
||||||
|
this.onPressed,
|
||||||
|
required this.child,
|
||||||
|
this.isSecondary = false,
|
||||||
|
this.isLoading = false,
|
||||||
|
this.isDone = false,
|
||||||
|
this.customTextStyle,
|
||||||
|
this.customButtonStyle,
|
||||||
|
this.backgroundColor,
|
||||||
|
this.foregroundColor,
|
||||||
|
this.borderRadius,
|
||||||
|
this.height,
|
||||||
|
this.padding,
|
||||||
|
});
|
||||||
|
|
||||||
|
final void Function()? onPressed;
|
||||||
|
final Widget child;
|
||||||
|
final double? height;
|
||||||
|
final bool isSecondary;
|
||||||
|
final double? borderRadius;
|
||||||
|
final bool enabled;
|
||||||
|
final double? padding;
|
||||||
|
final bool isDone;
|
||||||
|
final bool isLoading;
|
||||||
|
final TextStyle? customTextStyle;
|
||||||
|
|
||||||
|
final ButtonStyle? customButtonStyle;
|
||||||
|
|
||||||
|
final Color? backgroundColor;
|
||||||
|
|
||||||
|
final Color? foregroundColor;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return ElevatedButton(
|
||||||
|
onPressed: enabled ? onPressed : null,
|
||||||
|
style: isSecondary
|
||||||
|
? null
|
||||||
|
: customButtonStyle ??
|
||||||
|
ButtonStyle(
|
||||||
|
textStyle: MaterialStateProperty.all(
|
||||||
|
customTextStyle ??
|
||||||
|
context.bodyMedium.copyWith(
|
||||||
|
fontSize: 16,
|
||||||
|
color: foregroundColor,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
foregroundColor: MaterialStateProperty.all(
|
||||||
|
isSecondary
|
||||||
|
? Colors.black
|
||||||
|
: enabled
|
||||||
|
? foregroundColor ?? Colors.white
|
||||||
|
: Colors.black,
|
||||||
|
),
|
||||||
|
backgroundColor: MaterialStateProperty.resolveWith<Color>(
|
||||||
|
(Set<MaterialState> states) {
|
||||||
|
return enabled
|
||||||
|
? backgroundColor ?? ColorsManager.primaryColor
|
||||||
|
: Colors.grey;
|
||||||
|
}),
|
||||||
|
shape: MaterialStateProperty.all(
|
||||||
|
RoundedRectangleBorder(
|
||||||
|
borderRadius: BorderRadius.circular(borderRadius ?? 20),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
fixedSize: MaterialStateProperty.all(
|
||||||
|
const Size.fromHeight(50),
|
||||||
|
),
|
||||||
|
padding: MaterialStateProperty.all(
|
||||||
|
EdgeInsets.all(padding ?? 10),
|
||||||
|
),
|
||||||
|
minimumSize: MaterialStateProperty.all(
|
||||||
|
const Size.fromHeight(50),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
child: SizedBox(
|
||||||
|
height: height ?? 50,
|
||||||
|
child: Center(
|
||||||
|
child: isLoading
|
||||||
|
? const SizedBox.square(
|
||||||
|
dimension: 24,
|
||||||
|
child: CircularProgressIndicator(
|
||||||
|
color: Colors.white,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
: isDone
|
||||||
|
? const Text('Done') :child ,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -160,15 +160,7 @@ abstract class ApiEndpoints {
|
|||||||
static const String getOneTimeTemporaryPassword =
|
static const String getOneTimeTemporaryPassword =
|
||||||
'/door-lock/temporary-password/offline/one-time/{doorLockUuid}';
|
'/door-lock/temporary-password/offline/one-time/{doorLockUuid}';
|
||||||
|
|
||||||
//multiple-time offline
|
|
||||||
static const String addMultipleTimeTemporaryPassword =
|
|
||||||
'/door-lock/temporary-password/offline/multiple-time/{doorLockUuid}';
|
|
||||||
static const String getMultipleTimeTemporaryPassword =
|
|
||||||
'/door-lock/temporary-password/offline/multiple-time/{doorLockUuid}';
|
|
||||||
|
|
||||||
//multiple-time offline
|
|
||||||
static const String deleteTemporaryPassword =
|
|
||||||
'/door-lock/temporary-password/{doorLockUuid}/{passwordId}';
|
|
||||||
|
|
||||||
//user
|
//user
|
||||||
|
|
||||||
@ -179,4 +171,17 @@ abstract class ApiEndpoints {
|
|||||||
static const String sendPicture = '/user/profile-picture/{userUuid}';
|
static const String sendPicture = '/user/profile-picture/{userUuid}';
|
||||||
static const String getRegion = '/region';
|
static const String getRegion = '/region';
|
||||||
static const String getTimezone = '/timezone';
|
static const String getTimezone = '/timezone';
|
||||||
|
|
||||||
|
//multiple-time offline
|
||||||
|
static const String addMultipleTimeTemporaryPassword =
|
||||||
|
'/door-lock/temporary-password/offline/multiple-time/{doorLockUuid}';
|
||||||
|
static const String getMultipleTimeTemporaryPassword =
|
||||||
|
'/door-lock/temporary-password/offline/multiple-time/{doorLockUuid}';
|
||||||
|
|
||||||
|
static const String renamePassword =
|
||||||
|
'/door-lock/temporary-password/{doorLockUuid}/offline/{passwordId}';
|
||||||
|
|
||||||
|
//multiple-time offline
|
||||||
|
static const String deleteTemporaryPassword =
|
||||||
|
'/door-lock/temporary-password/online/{doorLockUuid}/{passwordId}';
|
||||||
}
|
}
|
||||||
|
@ -69,6 +69,24 @@ class DevicesAPI {
|
|||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Future<Map<String, dynamic>> renamePass({
|
||||||
|
required String name,
|
||||||
|
required String doorLockUuid,
|
||||||
|
required String passwordId}) async {
|
||||||
|
final response = await _httpService.put(
|
||||||
|
path: ApiEndpoints.renamePassword
|
||||||
|
.replaceAll('{doorLockUuid}', doorLockUuid)
|
||||||
|
.replaceAll('{passwordId}', passwordId),
|
||||||
|
body: {
|
||||||
|
"name": name
|
||||||
|
},
|
||||||
|
expectedResponseModel: (json) {
|
||||||
|
return json;
|
||||||
|
},
|
||||||
|
);
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
/// Get Device Functions
|
/// Get Device Functions
|
||||||
static Future<FunctionModel> deviceFunctions(String deviceId) async {
|
static Future<FunctionModel> deviceFunctions(String deviceId) async {
|
||||||
final response = await _httpService.get(
|
final response = await _httpService.get(
|
||||||
@ -138,14 +156,31 @@ class DevicesAPI {
|
|||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Future getTemporaryPasswords(String deviceId, pageType) async {
|
static Future getTemporaryPasswords(String deviceId, ) async {
|
||||||
final response = await _httpService.get(
|
final response = await _httpService.get(
|
||||||
path: pageType == 'One-Time'
|
path: ApiEndpoints.getTemporaryPassword.replaceAll('{doorLockUuid}', deviceId),
|
||||||
? ApiEndpoints.getOneTimeTemporaryPassword.replaceAll('{doorLockUuid}', deviceId)
|
showServerMessage: false,
|
||||||
: pageType == 'Online Password'
|
expectedResponseModel: (json) {
|
||||||
? ApiEndpoints.getTemporaryPassword.replaceAll('{doorLockUuid}', deviceId)
|
return json;
|
||||||
: ApiEndpoints.getMultipleTimeTemporaryPassword
|
},
|
||||||
.replaceAll('{doorLockUuid}', deviceId),
|
);
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Future getOneTimePasswords(String deviceId) async {
|
||||||
|
final response = await _httpService.get(
|
||||||
|
path: ApiEndpoints.getOneTimeTemporaryPassword.replaceAll('{doorLockUuid}', deviceId),
|
||||||
|
showServerMessage: false,
|
||||||
|
expectedResponseModel: (json) {
|
||||||
|
return json;
|
||||||
|
},
|
||||||
|
);
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Future getTimeLimitPasswords(String deviceId) async {
|
||||||
|
final response = await _httpService.get(
|
||||||
|
path: ApiEndpoints.getMultipleTimeTemporaryPassword.replaceAll('{doorLockUuid}', deviceId),
|
||||||
showServerMessage: false,
|
showServerMessage: false,
|
||||||
expectedResponseModel: (json) {
|
expectedResponseModel: (json) {
|
||||||
return json;
|
return json;
|
||||||
@ -161,30 +196,19 @@ class DevicesAPI {
|
|||||||
required String effectiveTime,
|
required String effectiveTime,
|
||||||
required String invalidTime,
|
required String invalidTime,
|
||||||
required String deviceId,
|
required String deviceId,
|
||||||
required String pageType,
|
List<Schedule>? scheduleList,}) async {
|
||||||
List<Schedule>? scheduleList,
|
|
||||||
}) async {
|
|
||||||
String endpointPath;
|
|
||||||
if (pageType == 'Online Password') {
|
|
||||||
endpointPath = ApiEndpoints.addTemporaryPassword.replaceAll('{doorLockUuid}', deviceId);
|
|
||||||
} else if (pageType == 'One-Time') {
|
|
||||||
endpointPath =
|
|
||||||
ApiEndpoints.addOneTimeTemporaryPassword.replaceAll('{doorLockUuid}', deviceId);
|
|
||||||
} else {
|
|
||||||
endpointPath =
|
|
||||||
ApiEndpoints.addMultipleTimeTemporaryPassword.replaceAll('{doorLockUuid}', deviceId);
|
|
||||||
}
|
|
||||||
Map<String, dynamic> body = {
|
Map<String, dynamic> body = {
|
||||||
"name": name,
|
"name": name,
|
||||||
"password": password,
|
"password": password,
|
||||||
"effectiveTime": effectiveTime,
|
"effectiveTime": effectiveTime,
|
||||||
"invalidTime": invalidTime,
|
"invalidTime": invalidTime,
|
||||||
};
|
};
|
||||||
if (pageType == 'Online Password' && scheduleList != null) {
|
if (scheduleList != null) {
|
||||||
body["scheduleList"] = scheduleList.map((schedule) => schedule.toJson()).toList();
|
body["scheduleList"] = scheduleList.map((schedule) => schedule.toJson()).toList();
|
||||||
}
|
}
|
||||||
final response = await _httpService.post(
|
final response = await _httpService.post(
|
||||||
path: endpointPath,
|
path: ApiEndpoints.addTemporaryPassword.replaceAll('{doorLockUuid}', deviceId),
|
||||||
body: body,
|
body: body,
|
||||||
showServerMessage: false,
|
showServerMessage: false,
|
||||||
expectedResponseModel: (json) => json,
|
expectedResponseModel: (json) => json,
|
||||||
@ -192,6 +216,40 @@ class DevicesAPI {
|
|||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Future generateOneTimePassword({deviceId}) async {
|
||||||
|
try {
|
||||||
|
final response = await _httpService.post(
|
||||||
|
path: ApiEndpoints.addOneTimeTemporaryPassword.replaceAll('{doorLockUuid}', deviceId),
|
||||||
|
showServerMessage: false,
|
||||||
|
expectedResponseModel: (json) {
|
||||||
|
return json;
|
||||||
|
},
|
||||||
|
);
|
||||||
|
return response;
|
||||||
|
} catch (e) {
|
||||||
|
rethrow;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static Future generateMultiTimePassword({deviceId,effectiveTime,invalidTime}) async {
|
||||||
|
try {
|
||||||
|
final response = await _httpService.post(
|
||||||
|
path: ApiEndpoints.addMultipleTimeTemporaryPassword.replaceAll('{doorLockUuid}', deviceId),
|
||||||
|
showServerMessage: false,
|
||||||
|
body: {
|
||||||
|
"effectiveTime": effectiveTime,
|
||||||
|
"invalidTime": invalidTime
|
||||||
|
},
|
||||||
|
expectedResponseModel: (json) {
|
||||||
|
return json;
|
||||||
|
},
|
||||||
|
);
|
||||||
|
return response;
|
||||||
|
} catch (e) {
|
||||||
|
rethrow;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static Future<Map<String, dynamic>> deletePassword(
|
static Future<Map<String, dynamic>> deletePassword(
|
||||||
{required String passwordId, required String deviceId}) async {
|
{required String passwordId, required String deviceId}) async {
|
||||||
final response = await _httpService.delete(
|
final response = await _httpService.delete(
|
||||||
@ -205,4 +263,5 @@ class DevicesAPI {
|
|||||||
);
|
);
|
||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user