CreateTemporaryPassword

This commit is contained in:
mohammad
2024-06-28 23:50:14 +03:00
parent 3e7b6839d9
commit 1f93614900
3 changed files with 455 additions and 248 deletions
@@ -1,5 +1,7 @@
import 'dart:math';
import 'package:day_picker/model/day_in_week.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package: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';
@@ -11,13 +13,52 @@ import 'package:syncrow_app/services/api/devices_api.dart';
class SmartDoorBloc extends Bloc<SmartDoorEvent, SmartDoorState> {
final String deviceId;
late SmartDoorModel deviceStatus;
TextEditingController passwordController = TextEditingController();
TextEditingController passwordNameController = TextEditingController();
String effectiveTime = 'Select Time';
int? effectiveTimeTimeStamp;
String expirationTime = 'Select Time';
int? expirationTimeTimeStamp;
bool repeat = false;
bool isStartEndTime = true;
List<String>? selectedDay;
DateTime? startTime;
DateTime? endTime ; // This sets the date to December 31, 2050.
changeTime(val,isStartEndTime){
if(isStartEndTime==true){
startTime=val;
}else{
endTime=val;
}
emit(changeTimeState());
}
bool repeatFunction() {
repeat = !repeat;
emit(IsRepeatState());
return repeat;
}
bool isStartEndTimeFun(val) {
emit(LoadingInitialState());
isStartEndTime = val;
emit(IsStartEndState());
return isStartEndTime;
}
SmartDoorBloc({required this.deviceId}) : super(InitialState()) {
on<InitialEvent>(_fetchSmartDoorStatus);
on<UpdateLockEvent>(_updateLock);
}
void _fetchSmartDoorStatus(InitialEvent event, Emitter<SmartDoorState> emit) async {
void _fetchSmartDoorStatus(
InitialEvent event, Emitter<SmartDoorState> emit) async {
emit(LoadingInitialState());
try {
var response = await DevicesAPI.getDeviceStatus(deviceId);
@@ -37,7 +78,10 @@ class SmartDoorBloc extends Bloc<SmartDoorEvent, SmartDoorState> {
emit(LoadingNewSate(smartDoorModel: deviceStatus));
try {
final response = await DevicesAPI.controlDevice(
DeviceControlModel(deviceId: deviceId, code: 'normal_open_switch', value: !event.value),
DeviceControlModel(
deviceId: deviceId,
code: 'normal_open_switch',
value: !event.value),
deviceId);
if (response['success'] ?? false) {
@@ -47,13 +91,144 @@ class SmartDoorBloc extends Bloc<SmartDoorEvent, SmartDoorState> {
emit(UpdateState(smartDoorModel: deviceStatus));
}
int generate7DigitNumber() {
void generate7DigitNumber() async {
emit(LoadingInitialState());
passwordController.clear();
Random random = Random();
int min = 1000000; // Minimum 7-digit number
int max = 9999999; // Maximum 7-digit number
return min + random.nextInt(max - min + 1);
passwordController.text = (min + random.nextInt(max - min + 1)).toString();
emit(GeneratePasswordState());
}
Future<void> selectTime(BuildContext context, {required bool isEffective}) async {
final DateTime? picked = await showDatePicker(
context: context,
initialDate: DateTime.now(),
firstDate: DateTime(2015, 8),
lastDate: DateTime(2101),
);
if (picked != null) {
final TimeOfDay? timePicked = await showTimePicker(
context: context,
initialTime: TimeOfDay.now(),
);
if (timePicked != null) {
final selectedDateTime = DateTime(
picked.year,
picked.month,
picked.day,
timePicked.hour,
timePicked.minute,
);
if (isEffective) {
if (expirationTimeTimeStamp != null &&
selectedDateTime.millisecondsSinceEpoch >
expirationTimeTimeStamp!) {
// Show error message
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content: Text(
'Effective Time cannot be later than Expiration Time.'),
),
);
} else {
effectiveTime = selectedDateTime.toString();
effectiveTimeTimeStamp = selectedDateTime.millisecondsSinceEpoch;
}
} else {
if (effectiveTimeTimeStamp != null &&
selectedDateTime.millisecondsSinceEpoch <
effectiveTimeTimeStamp!) {
// Show error message
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content: Text(
'Expiration Time cannot be earlier than Effective Time.'),
),
);
} else {
expirationTime = selectedDateTime.toString();
expirationTimeTimeStamp = selectedDateTime.millisecondsSinceEpoch;
}
}
emit(TimeSelectedState());
}
}
}
}
Future<void> saveFunction(BuildContext context,) async {
if (passwordController.text.isEmpty) {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content: Text('Password name required'),
backgroundColor: Colors.red,
),
);
return;
}
if (passwordNameController.text.isEmpty) {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content: Text('Password name required'),
backgroundColor: Colors.red,
),
);
return;
}
if (effectiveTime == 'Select Time' || effectiveTimeTimeStamp == null) {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content: Text('Select effective time'),
backgroundColor: Colors.red,
),
);
return;
}
if (expirationTime == 'Select Time' || expirationTimeTimeStamp == null) {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content: Text('Select expiration time'),
backgroundColor: Colors.red,
),
);
return;
}
}
//["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"]
List<DayInWeek> days = [
DayInWeek(
"Sun",
dayKey: 'Sun',
),
DayInWeek(
"Mon",
dayKey: 'Mon',
),
DayInWeek(
"Tue",
isSelected: true,
dayKey: 'Tue'
),
DayInWeek(
"Wed",
dayKey: 'Wed',
),
DayInWeek(
"Thu",
dayKey: 'Thu',
),
DayInWeek(
"Fri",
dayKey: 'Fri',
),
DayInWeek(
"Sat",
dayKey: 'Sat',
),
];
}
@@ -36,3 +36,11 @@ class FailedState extends SmartDoorState {
@override
List<Object> get props => [errorMessage];
}
class GeneratePasswordState extends SmartDoorState{}
class TimeSelectedState extends SmartDoorState{}
class IsRepeatState extends SmartDoorState{}
class IsStartEndState extends SmartDoorState{}
class changeStartTimeState extends SmartDoorState{}
class changeEndTimeState extends SmartDoorState{}
class changeTimeState extends SmartDoorState{}
@@ -1,7 +1,10 @@
import 'package:day_picker/day_picker.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
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_state.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';
@@ -9,258 +12,279 @@ import 'package:syncrow_app/features/shared_widgets/text_widgets/body_small.dart
import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
import 'package:time_picker_spinner/time_picker_spinner.dart';
class CreateTemporaryPassword extends StatefulWidget {
class CreateTemporaryPassword extends StatelessWidget {
const CreateTemporaryPassword({super.key});
@override
State<CreateTemporaryPassword> createState() =>
_CreateTemporaryPasswordState();
}
class _CreateTemporaryPasswordState extends State<CreateTemporaryPassword> {
List<DayInWeek> _days = [
DayInWeek(
"Sun",
dayKey: '',
),
DayInWeek(
"Mon",
dayKey: '',
),
DayInWeek("Tue", isSelected: true, dayKey: ''),
DayInWeek(
"Wed",
dayKey: '',
),
DayInWeek(
"Thu",
dayKey: '',
),
DayInWeek(
"Fri",
dayKey: '',
),
DayInWeek(
"Sat",
dayKey: '',
),
];
DateTime dateTime = DateTime.now();
@override
Widget build(BuildContext context) {
TextEditingController? controller = TextEditingController();
return DefaultScaffold(
title: 'Create Password',
actions: [TextButton(onPressed: () {}, child: const Text('Save'))],
child: SingleChildScrollView(
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
BodyMedium(
text:
'Save the password immediately. The password is not displayed in the app.',
fontWeight: FontWeight.normal,
fontColor: ColorsManager.grayColor,
),
SizedBox(
height: 20,
),
const BodyMedium(
text: '7-Digit Password',
fontWeight: FontWeight.normal,
fontColor: ColorsManager.grayColor,
),
DefaultContainer(
padding: const EdgeInsets.symmetric(horizontal: 5, vertical: 5),
child: Row(
return BlocProvider(
create: (BuildContext context) => SmartDoorBloc(deviceId: ''),
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) {
return DefaultScaffold(
title: 'Create Password',
actions: [
TextButton(
onPressed: () {
BlocProvider.of<SmartDoorBloc>(context).saveFunction(context);
},
child: const Text('Save'))
],
child: SingleChildScrollView(
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Expanded(
child: PinCodeTextField(
keyboardType: TextInputType.phone,
length: 7,
enabled: true,
obscureText: false,
animationType: AnimationType.fade,
pinTheme: PinTheme(
shape: PinCodeFieldShape.underline,
fieldHeight: 45,
fieldWidth: 20,
activeFillColor: Colors.white,
disabledColor: Colors.grey,
activeColor: Colors.grey,
errorBorderColor: Colors.grey,
inactiveColor: Colors.grey,
inactiveFillColor: Colors.grey,
selectedColor: Colors.grey),
animationDuration: Duration(milliseconds: 300),
backgroundColor: Colors.white,
enableActiveFill: false,
controller: controller,
onCompleted: (v) {
print("Completed");
},
onChanged: (value) {
print(value);
},
appContext: context,
)),
const SizedBox(
width: 10,
const BodyMedium(
text: 'Save the password immediately. The password is not displayed in the app.',
fontWeight: FontWeight.normal,
fontColor: ColorsManager.grayColor,
),
InkWell(
onTap: () {},
child: const BodyMedium(
text: 'Generate Randomly',
fontWeight: FontWeight.bold,
fontColor: ColorsManager.primaryColor,
))
const SizedBox(
height: 20,
),
const BodyMedium(
text: '7-Digit Password',
fontWeight: FontWeight.normal,
fontColor: ColorsManager.grayColor,
),
DefaultContainer(
padding:
const EdgeInsets.symmetric(horizontal: 5, vertical: 5),
child: Row(
children: [
Expanded(
child: PinCodeTextField(
keyboardType: TextInputType.phone,
length: 7,
enabled: true,
obscureText: false,
animationType: AnimationType.fade,
pinTheme: PinTheme(
shape: PinCodeFieldShape.underline,
fieldHeight: 45,
fieldWidth: 20,
activeFillColor: Colors.white,
disabledColor: Colors.grey,
activeColor: Colors.grey,
errorBorderColor: Colors.grey,
inactiveColor: Colors.grey,
inactiveFillColor: Colors.grey,
selectedColor: Colors.grey),
animationDuration: Duration(milliseconds: 300),
backgroundColor: Colors.white,
enableActiveFill: false,
controller: BlocProvider.of<SmartDoorBloc>(context).passwordController,
appContext: context,
)),
const SizedBox(
width: 10,
),
InkWell(
onTap: () {BlocProvider.of<SmartDoorBloc>(context).generate7DigitNumber();},
child: const BodyMedium(
text: 'Generate Randomly',
fontWeight: FontWeight.bold,
fontColor: ColorsManager.primaryColor,
))
],
),
),
const SizedBox(
height: 20,
),
DefaultContainer(
padding: const EdgeInsets.all(10),
child: Column(
children: [
ListTile(
contentPadding: EdgeInsets.zero,
leading: const BodyMedium(
text: 'Password Name',
fontWeight: FontWeight.normal,
),
trailing: SizedBox(
width: MediaQuery.of(context).size.width / 2,
child: TextFormField(
controller: BlocProvider.of<SmartDoorBloc>(context).passwordNameController,
decoration: const InputDecoration(labelText: 'Enter The Name'),
)),
),
const Divider(),
ListTile(
contentPadding: EdgeInsets.zero,
leading: const BodyMedium(
text: 'Effective Time',
fontWeight: FontWeight.normal,
),
trailing: SizedBox(
width: MediaQuery.of(context).size.width / 2,
child: InkWell(
onTap: () {
BlocProvider.of<SmartDoorBloc>(context).selectTime(context, isEffective: true);
},
child: Text(BlocProvider.of<SmartDoorBloc>(context).effectiveTime),
))
),
const Divider(),
ListTile(
contentPadding: EdgeInsets.zero,
leading: const BodyMedium(
text: 'Expiration Time',
fontWeight: FontWeight.normal,
),
trailing: SizedBox(
width: MediaQuery.of(context).size.width / 2,
child: SizedBox(
width: MediaQuery.of(context).size.width / 2,
child: InkWell(
onTap: () {
BlocProvider.of<SmartDoorBloc>(context).selectTime(context, isEffective: false);
},
child: Text(BlocProvider.of<SmartDoorBloc>(context).expirationTime),
)),
),
),
],
)),
const SizedBox(
height: 20,
),
DefaultContainer(
padding:
const EdgeInsets.symmetric(horizontal: 5, vertical: 5),
child: ListTile(
contentPadding: EdgeInsets.zero,
leading: const BodyMedium(
text: 'Repeat',
fontWeight: FontWeight.normal,
),
trailing: Transform.scale(
scale: .8,
child: CupertinoSwitch(
value:
BlocProvider.of<SmartDoorBloc>(context).repeat,
onChanged: (value) {
BlocProvider.of<SmartDoorBloc>(context).repeatFunction();
},
applyTheme: true,
)),
),
),
const SizedBox(
height: 20,
),
BlocProvider.of<SmartDoorBloc>(context).repeat
? DefaultContainer(
padding: const EdgeInsets.symmetric(horizontal: 5, 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).isStartEndTimeFun(true);
},
child: BodyMedium(
text: 'Start',
fontColor:
BlocProvider.of<SmartDoorBloc>(context).isStartEndTime == false
? Colors.black : Colors.blue,
fontSize: 18,
),
),
InkWell(
onTap: () {
BlocProvider.of<SmartDoorBloc>(context).isStartEndTimeFun(false);
},
child: BodyMedium(
text: 'End',
fontColor:
BlocProvider.of<SmartDoorBloc>(context).isStartEndTime
? Colors.black : Colors.blue,
fontSize: 18,
),
)
],
),
),
const Divider(),
SizedBox(
height: 80,
child: BlocProvider.of<SmartDoorBloc>(context).isStartEndTime
? TimePickerSpinner(
time: BlocProvider.of<SmartDoorBloc>(context).startTime,
is24HourMode: false,
itemHeight: 40,
normalTextStyle: const TextStyle(
fontSize: 24,
),
highlightedTextStyle: const TextStyle(
fontSize: 30, color: Colors.blue),
onTimeChange: (time) {
BlocProvider.of<SmartDoorBloc>(context).startTime = time;
BlocProvider.of<SmartDoorBloc>(
context).changeTime(time, BlocProvider.of<SmartDoorBloc>(context).isStartEndTime);
},
)
: TimePickerSpinner(
time: BlocProvider.of<SmartDoorBloc>(context).endTime,
is24HourMode: false,
itemHeight: 40,
normalTextStyle: const TextStyle(
fontSize: 24,
),
highlightedTextStyle: const TextStyle(
fontSize: 24, color: Colors.blue),
onTimeChange: (time) {
BlocProvider.of<SmartDoorBloc>(context).endTime = time;
BlocProvider.of<SmartDoorBloc>(context).changeTime(time, BlocProvider.of<SmartDoorBloc>(context).isStartEndTime);
},
),
),
const Divider(),
const SizedBox(height: 20),
SelectWeekDays(
width: MediaQuery.of(context).size.width / 1,
fontSize: 10,
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) {
print(values);
BlocProvider.of<SmartDoorBloc>(context)
.selectedDay = values;
},
),
],
))
: SizedBox(),
const SizedBox(
height: 40,
)
],
),
),
const SizedBox(
height: 20,
),
DefaultContainer(
padding: const EdgeInsets.all(10),
child: Column(
children: [
ListTile(
contentPadding: EdgeInsets.zero,
leading: const BodyMedium(
text: 'Password Name',
fontWeight: FontWeight.normal,
),
trailing: Container(
width: MediaQuery.of(context).size.width / 2,
child: TextFormField(
decoration:
InputDecoration(labelText: 'Enter The Name'),
)),
),
Divider(),
ListTile(
contentPadding: EdgeInsets.zero,
leading: const BodyMedium(
text: 'Effective Time',
fontWeight: FontWeight.normal,
),
trailing: Container(
width: MediaQuery.of(context).size.width / 2,
child: TextFormField(
enabled: false,
decoration: InputDecoration(
border: InputBorder.none,
labelText: 'Select Time'),
)),
),
Divider(),
ListTile(
contentPadding: EdgeInsets.zero,
leading: const BodyMedium(
text: 'Select Time',
fontWeight: FontWeight.normal,
),
trailing: Container(
width: MediaQuery.of(context).size.width / 2,
child: TextFormField(
enabled: false,
decoration: InputDecoration(
border: InputBorder.none,
labelText: 'Select Time'),
)),
),
],
)),
SizedBox(
height: 20,
),
DefaultContainer(
padding: const EdgeInsets.symmetric(horizontal: 5, vertical: 5),
child: ListTile(
contentPadding: EdgeInsets.zero,
leading: const BodyMedium(
text: 'Repeat',
fontWeight: FontWeight.normal,
),
trailing: Transform.scale(
scale: .8,
child: CupertinoSwitch(
value: true,
onChanged: (value) {},
applyTheme: true,
)),
),
),
const SizedBox(
height: 20,
),
DefaultContainer(
padding: const EdgeInsets.symmetric(horizontal: 5, vertical: 5),
child: Column(
children: <Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
TextButton(
onPressed: () {},
child: const Text('Start'),
),
TextButton(
onPressed: () {},
child: const Text('End'),
)
],
),
Divider(),
SizedBox(
height: 80,
child: TimePickerSpinner(
spacing: 10,
locale: const Locale('en', ''),
time: dateTime,
is24HourMode: false,
itemHeight: 40,
normalTextStyle: const TextStyle(
fontSize: 24,
),
highlightedTextStyle:
const TextStyle(fontSize: 24, color: Colors.blue),
onTimeChange: (time) {
setState(() {
dateTime = time;
});
},
),
),
Divider(),
SizedBox(height: 20),
SelectWeekDays(
width: MediaQuery.of(context).size.width/1,
fontSize: 10,
fontWeight: FontWeight.w600,
days: _days,
border: false,
selectedDayTextColor: Colors.black,
unSelectedDayTextColor: Colors.grey,
boxDecoration: BoxDecoration(
borderRadius: BorderRadius.circular(30.0),
color: Colors.white),
onSelect: (values) {
print(values);
},
),
],
)),
SizedBox(height: 40,)
],
),
),
);
);
}));
}
}