mirror of
https://github.com/SyncrowIOT/web.git
synced 2025-07-09 22:57:21 +00:00
Success dialog and Failed dialog changes with VisitorPasswordDialog
This commit is contained in:
@ -1,96 +0,0 @@
|
||||
[
|
||||
{
|
||||
"accessUser": "Ali Doe",
|
||||
"accessType": "Admin",
|
||||
"startTime": "2023-08-01",
|
||||
"endTime": "2023-08-02",
|
||||
"accessibleDevice": "Smart Door",
|
||||
"authorizationSource": "System",
|
||||
"authorizer": "Jane Smith",
|
||||
"authorizationTime": "2023-08-01 10:00 AM",
|
||||
"accessStatus": "Granted",
|
||||
"actions": "View"
|
||||
}, {
|
||||
"accessUser": "oamr Doe",
|
||||
"accessType": "Admin",
|
||||
"startTime": "2023-08-01",
|
||||
"endTime": "2023-08-05",
|
||||
"accessibleDevice": "Smart Door",
|
||||
"authorizationSource": "System",
|
||||
"authorizer": "Jane Smith",
|
||||
"authorizationTime": "2023-08-01 10:00 AM",
|
||||
"accessStatus": "Granted",
|
||||
"actions": "View"
|
||||
}, {
|
||||
"accessUser": "John Doe",
|
||||
"accessType": "Admin",
|
||||
"startTime": "2023-08-01",
|
||||
"endTime": "2023-08-10",
|
||||
"accessibleDevice": "Smart Door",
|
||||
"authorizationSource": "System",
|
||||
"authorizer": "Jane Smith",
|
||||
"authorizationTime": "2023-08-01 10:00 AM",
|
||||
"accessStatus": "Granted",
|
||||
"actions": "View"
|
||||
},
|
||||
|
||||
{
|
||||
"accessUser": "John Doe",
|
||||
"accessType": "Admin",
|
||||
"startTime": "2023-08-01",
|
||||
"endTime": "2023-10-10",
|
||||
"accessibleDevice": "Smart Door",
|
||||
"authorizationSource": "System",
|
||||
"authorizer": "Jane Smith",
|
||||
"authorizationTime": "2023-08-01 10:00 AM",
|
||||
"accessStatus": "Granted",
|
||||
"actions": "View"
|
||||
},
|
||||
{
|
||||
"accessUser": "John Doe",
|
||||
"accessType": "Admin",
|
||||
"startTime": "2023-03-01",
|
||||
"endTime": "2023-05-10",
|
||||
"accessibleDevice": "Smart Door",
|
||||
"authorizationSource": "System",
|
||||
"authorizer": "Jane Smith",
|
||||
"authorizationTime": "2023-08-01 10:00 AM",
|
||||
"accessStatus": "Granted",
|
||||
"actions": "View"
|
||||
},
|
||||
{
|
||||
"accessUser": "John Doe",
|
||||
"accessType": "Admin",
|
||||
"startTime": "2023-07-01",
|
||||
"endTime": "2023-08-10",
|
||||
"accessibleDevice": "Smart Door",
|
||||
"authorizationSource": "System",
|
||||
"authorizer": "Jane Smith",
|
||||
"authorizationTime": "2023-08-01 10:00 AM",
|
||||
"accessStatus": "Granted",
|
||||
"actions": "View"
|
||||
}, {
|
||||
"accessUser": "John Doe",
|
||||
"accessType": "Admin",
|
||||
"startTime": "2023-01-01",
|
||||
"endTime": "2023-09-05",
|
||||
"accessibleDevice": "Smart Door",
|
||||
"authorizationSource": "System",
|
||||
"authorizer": "Jane Smith",
|
||||
"authorizationTime": "2023-08-01 10:00 AM",
|
||||
"accessStatus": "Granted",
|
||||
"actions": "View"
|
||||
},
|
||||
{
|
||||
"accessUser": "Alice Johnson",
|
||||
"accessType": "User",
|
||||
"startTime": "2023-08-01",
|
||||
"endTime": "2023-08-10",
|
||||
"accessibleDevice": "Smart Lock",
|
||||
"authorizationSource": "Admin",
|
||||
"authorizer": "John Doe",
|
||||
"authorizationTime": "2023-08-02 11:00 AM",
|
||||
"accessStatus": "Pending",
|
||||
"actions": "Approve"
|
||||
}
|
||||
]
|
@ -5,8 +5,7 @@ import 'package:syncrow_web/pages/auth/bloc/auth_bloc.dart';
|
||||
import 'package:syncrow_web/pages/auth/view/login_page.dart';
|
||||
import 'package:syncrow_web/pages/home/bloc/home_bloc.dart';
|
||||
import 'package:syncrow_web/pages/home/view/home_page.dart';
|
||||
import 'package:syncrow_web/pages/visitor_password/view/add_device_dialog.dart';
|
||||
import 'package:syncrow_web/pages/visitor_password/view/visitor_password_dialog.dart';
|
||||
import 'package:syncrow_web/pages/visitor_password/bloc/visitor_password_bloc.dart';
|
||||
import 'package:syncrow_web/services/locator.dart';
|
||||
import 'package:syncrow_web/utils/color_manager.dart';
|
||||
|
||||
@ -30,6 +29,8 @@ class MyApp extends StatelessWidget {
|
||||
return MultiBlocProvider(
|
||||
providers: [
|
||||
BlocProvider(create: (context) => HomeBloc()),
|
||||
BlocProvider<VisitorPasswordBloc>(
|
||||
create: (context) => VisitorPasswordBloc(),)
|
||||
],
|
||||
child: MaterialApp(
|
||||
debugShowCheckedModeBanner: false, // Hide debug banner
|
||||
|
@ -39,12 +39,9 @@ class AccessBloc extends Bloc<AccessEvent, AccessState> {
|
||||
}
|
||||
}
|
||||
void updateTabsCount() {
|
||||
// Count occurrences based on the type field
|
||||
int toBeEffectiveCount = data.where((item) => item.passwordStatus.value== 'To Be Effective').length;
|
||||
int effectiveCount = data.where((item) => item.passwordStatus.value == 'Effective').length;
|
||||
int expiredCount = data.where((item) => item.passwordStatus.value == 'Expired').length;
|
||||
|
||||
// Update tab labels with counts
|
||||
tabs[1] = 'To Be Effective ($toBeEffectiveCount)';
|
||||
tabs[2] = 'Effective ($effectiveCount)';
|
||||
tabs[3] = 'Expired ($expiredCount)';
|
||||
@ -53,7 +50,6 @@ class AccessBloc extends Bloc<AccessEvent, AccessState> {
|
||||
|
||||
|
||||
int selectedIndex = 0;
|
||||
|
||||
final List<String> tabs = [
|
||||
'All',
|
||||
'To Be Effective (0)',
|
||||
@ -76,7 +72,6 @@ class AccessBloc extends Bloc<AccessEvent, AccessState> {
|
||||
|
||||
|
||||
Future<void> selectTime(SelectTime event, Emitter<AccessState> emit) async {
|
||||
|
||||
final DateTime? picked = await showDatePicker(
|
||||
context: event.context,
|
||||
initialDate: DateTime.now(),
|
||||
@ -146,8 +141,6 @@ class AccessBloc extends Bloc<AccessEvent, AccessState> {
|
||||
try {
|
||||
filteredData = data.where((item) {
|
||||
bool matchesCriteria = true;
|
||||
|
||||
// Filter by password name if provided
|
||||
if (event.passwordName != null && event.passwordName!.isNotEmpty) {
|
||||
final bool matchesName = item.passwordName != null &&
|
||||
item.passwordName.contains(event.passwordName);
|
||||
@ -155,8 +148,6 @@ class AccessBloc extends Bloc<AccessEvent, AccessState> {
|
||||
matchesCriteria = false;
|
||||
}
|
||||
}
|
||||
|
||||
// Filter by date range if provided
|
||||
if (event.startTime != null && event.endTime != null) {
|
||||
final int? effectiveTime = int.tryParse(item.effectiveTime.toString());
|
||||
final int? invalidTime = int.tryParse(item.invalidTime.toString());
|
||||
@ -170,8 +161,6 @@ class AccessBloc extends Bloc<AccessEvent, AccessState> {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Filter by tab selection
|
||||
if (event.selectedTabIndex == 1 && item.passwordStatus.value != 'To Be Effective') {
|
||||
matchesCriteria = false;
|
||||
} else if (event.selectedTabIndex == 2 && item.passwordStatus.value != 'Effective') {
|
||||
@ -179,7 +168,6 @@ class AccessBloc extends Bloc<AccessEvent, AccessState> {
|
||||
} else if (event.selectedTabIndex == 3 && item.passwordStatus.value != 'Expired') {
|
||||
matchesCriteria = false;
|
||||
}
|
||||
|
||||
return matchesCriteria;
|
||||
}).toList();
|
||||
emit(TableLoaded(filteredData));
|
||||
@ -206,7 +194,6 @@ class AccessBloc extends Bloc<AccessEvent, AccessState> {
|
||||
try {
|
||||
emit(AccessLoaded());
|
||||
selectedIndex = event.selectedIndex;
|
||||
// Apply filtering based on selected tab
|
||||
switch (selectedIndex) {
|
||||
case 0: // All
|
||||
filteredData = data;
|
||||
@ -216,7 +203,6 @@ class AccessBloc extends Bloc<AccessEvent, AccessState> {
|
||||
break;
|
||||
case 2: // Effective
|
||||
filteredData = data.where((item) => item.passwordStatus.value == "Effective").toList();
|
||||
|
||||
break;
|
||||
case 3: // Expired
|
||||
filteredData = data.where((item) => item.passwordStatus.value == "Expired").toList();
|
||||
@ -225,7 +211,7 @@ class AccessBloc extends Bloc<AccessEvent, AccessState> {
|
||||
filteredData = data;
|
||||
}
|
||||
add(FilterDataEvent(
|
||||
selectedTabIndex: selectedIndex, // Pass the selected tab index
|
||||
selectedTabIndex: selectedIndex,
|
||||
passwordName: passwordName.text.toLowerCase(),
|
||||
startTime: effectiveTimeTimeStamp,
|
||||
endTime: expirationTimeTimeStamp
|
||||
|
@ -21,17 +21,14 @@ class AccessManagementPage extends StatelessWidget {
|
||||
enableMenuSideba: false,
|
||||
appBarTitle: Row(
|
||||
children: [
|
||||
Text(
|
||||
'Access Management',
|
||||
Text('Access Management',
|
||||
style: Theme.of(context).textTheme.headlineLarge,
|
||||
)
|
||||
],
|
||||
),
|
||||
appBarBody: [
|
||||
Text(
|
||||
'Physical Access',
|
||||
style: Theme.of(context)
|
||||
.textTheme
|
||||
Text('Physical Access',
|
||||
style: Theme.of(context).textTheme
|
||||
.headlineMedium!
|
||||
.copyWith(color: Colors.white),
|
||||
),
|
||||
@ -101,7 +98,9 @@ class AccessManagementPage extends StatelessWidget {
|
||||
height: 20,
|
||||
),
|
||||
Row(
|
||||
children: [
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.end,
|
||||
textBaseline: TextBaseline.ideographic, children: [
|
||||
Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
@ -111,7 +110,7 @@ class AccessManagementPage extends StatelessWidget {
|
||||
color: Colors.black,fontSize: 13),),
|
||||
const SizedBox(height: 5,),
|
||||
Container(
|
||||
height:size.height * 0.053,
|
||||
height:43,
|
||||
width: size.width * 0.15,
|
||||
decoration: containerDecoration,
|
||||
child: TextFormField(
|
||||
@ -145,51 +144,44 @@ class AccessManagementPage extends StatelessWidget {
|
||||
),
|
||||
|
||||
SizedBox(
|
||||
height:45,
|
||||
|
||||
width: size.width * 0.06,
|
||||
child: Column(
|
||||
children: [
|
||||
Text(''),
|
||||
Container(
|
||||
decoration: containerDecoration,
|
||||
child: DefaultButton(
|
||||
onPressed: () {
|
||||
accessBloc.add(FilterDataEvent(
|
||||
selectedTabIndex: BlocProvider.of<AccessBloc>(context).selectedIndex, // Pass the selected tab index
|
||||
passwordName: accessBloc.passwordName.text.toLowerCase(),
|
||||
startTime: accessBloc.effectiveTimeTimeStamp,
|
||||
endTime: accessBloc.expirationTimeTimeStamp
|
||||
));
|
||||
}, borderRadius: 9,
|
||||
child: const Text('Search'))),
|
||||
],
|
||||
),
|
||||
child:Container(
|
||||
decoration: containerDecoration,
|
||||
child: DefaultButton(
|
||||
onPressed: () {
|
||||
accessBloc.add(FilterDataEvent(
|
||||
selectedTabIndex: BlocProvider.of<AccessBloc>(context).selectedIndex, // Pass the selected tab index
|
||||
passwordName: accessBloc.passwordName.text.toLowerCase(),
|
||||
startTime: accessBloc.effectiveTimeTimeStamp,
|
||||
endTime: accessBloc.expirationTimeTimeStamp
|
||||
));
|
||||
}, borderRadius: 9,
|
||||
child: const Text('Search'))),
|
||||
),
|
||||
const SizedBox(
|
||||
width: 10,
|
||||
),
|
||||
SizedBox(
|
||||
height:45,
|
||||
width: size.width * 0.06,
|
||||
child: Column(
|
||||
children: [
|
||||
Text(''),
|
||||
Container(
|
||||
decoration: containerDecoration,
|
||||
child: DefaultButton(
|
||||
onPressed: () {
|
||||
accessBloc.add(ResetSearch());
|
||||
},
|
||||
backgroundColor: ColorsManager.whiteColors,
|
||||
borderRadius: 9,
|
||||
child: Text(
|
||||
'Reset',
|
||||
style: Theme.of(context)
|
||||
.textTheme
|
||||
.bodySmall!
|
||||
.copyWith(color: Colors.black),
|
||||
),
|
||||
),
|
||||
child: Container(
|
||||
decoration: containerDecoration,
|
||||
child: DefaultButton(
|
||||
onPressed: () {
|
||||
accessBloc.add(ResetSearch());
|
||||
},
|
||||
backgroundColor: ColorsManager.whiteColors,
|
||||
borderRadius: 9,
|
||||
child: Text(
|
||||
'Reset',
|
||||
style: Theme.of(context)
|
||||
.textTheme
|
||||
.bodySmall!
|
||||
.copyWith(color: Colors.black),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
|
@ -146,7 +146,6 @@ class LoginMobilePage extends StatelessWidget {
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
),
|
||||
|
||||
isDense: true,
|
||||
style: const TextStyle(color: Colors.black),
|
||||
items:loginBloc.regionList!.map((RegionModel region) {
|
||||
@ -156,7 +155,6 @@ class LoginMobilePage extends StatelessWidget {
|
||||
);
|
||||
}).toList(),
|
||||
onChanged: (String? value) {
|
||||
print(value);
|
||||
},
|
||||
),
|
||||
)
|
||||
|
75
lib/pages/common/custom_dialog.dart
Normal file
75
lib/pages/common/custom_dialog.dart
Normal file
@ -0,0 +1,75 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_svg/flutter_svg.dart';
|
||||
import 'package:syncrow_web/utils/color_manager.dart';
|
||||
|
||||
Future<void> showCustomDialog({
|
||||
required BuildContext context,
|
||||
required String message,
|
||||
String? title,
|
||||
String? iconPath,
|
||||
double? dialogHeight,
|
||||
double? iconHeight,
|
||||
double? iconWidth,
|
||||
VoidCallback? onOkPressed,
|
||||
bool barrierDismissible = false, required actions,
|
||||
}) {
|
||||
return showDialog(
|
||||
context: context,
|
||||
barrierDismissible: barrierDismissible,
|
||||
builder: (BuildContext context) {
|
||||
final size = MediaQuery.of(context).size;
|
||||
return AlertDialog(
|
||||
alignment: Alignment.center,
|
||||
content: SizedBox(
|
||||
height: dialogHeight ?? size.height * 0.15,
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
if (iconPath != null)
|
||||
SvgPicture.asset(
|
||||
iconPath,
|
||||
height: iconHeight ?? 35,
|
||||
width: iconWidth ?? 35,
|
||||
),
|
||||
if (title != null)
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(top: 8.0),
|
||||
child: Text(
|
||||
title,
|
||||
style: Theme.of(context).textTheme.headlineLarge!.copyWith(
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.w400,
|
||||
color: Colors.black),
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(top: 8.0),
|
||||
child: Text(
|
||||
message,
|
||||
style: Theme.of(context)
|
||||
.textTheme
|
||||
.bodyMedium!
|
||||
.copyWith(color: Colors.black),
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
actionsAlignment: MainAxisAlignment.center,
|
||||
actions: <Widget>[
|
||||
TextButton(
|
||||
onPressed: onOkPressed ?? () => Navigator.of(context).pop(),
|
||||
child: Text(
|
||||
'OK',
|
||||
style: Theme.of(context).textTheme.bodySmall!.copyWith(
|
||||
fontWeight: FontWeight.w400,
|
||||
color: ColorsManager.blackColor,
|
||||
fontSize: 16),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
@ -15,7 +15,7 @@ class DynamicTable extends StatefulWidget {
|
||||
final void Function(int, bool?)? onRowCheckboxChanged;
|
||||
|
||||
const DynamicTable({
|
||||
Key? key,
|
||||
super.key,
|
||||
required this.headers,
|
||||
required this.data,
|
||||
required this.size,
|
||||
@ -25,7 +25,7 @@ class DynamicTable extends StatefulWidget {
|
||||
this.cellDecoration,
|
||||
this.selectAll,
|
||||
this.onRowCheckboxChanged,
|
||||
}) : super(key: key);
|
||||
});
|
||||
|
||||
@override
|
||||
_DynamicTableState createState() => _DynamicTableState();
|
||||
@ -66,7 +66,7 @@ class _DynamicTableState extends State<DynamicTable> {
|
||||
return Container(
|
||||
decoration: widget.cellDecoration,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(10.0),
|
||||
padding: const EdgeInsets.all(2.0),
|
||||
child:
|
||||
ListView(
|
||||
scrollDirection: Axis.horizontal,
|
||||
@ -102,7 +102,7 @@ class _DynamicTableState extends State<DynamicTable> {
|
||||
SvgPicture.asset(
|
||||
Assets.emptyTable
|
||||
),
|
||||
SizedBox(height: 15,),
|
||||
const SizedBox(height: 15,),
|
||||
Text('No Passwords',style: Theme.of(context).textTheme.bodySmall!.copyWith(color:ColorsManager.grayColor ),)
|
||||
],
|
||||
),
|
||||
@ -122,9 +122,9 @@ class _DynamicTableState extends State<DynamicTable> {
|
||||
return Row(
|
||||
children: [
|
||||
if (widget.withCheckBox)
|
||||
_buildRowCheckbox(index),
|
||||
_buildRowCheckbox(index,widget.size.height*0.10),
|
||||
...row.map((cell) =>
|
||||
_buildTableCell(cell.toString())).toList(),
|
||||
_buildTableCell(cell.toString(),widget.size.height*0.10)).toList(),
|
||||
],
|
||||
);
|
||||
},
|
||||
@ -141,8 +141,12 @@ class _DynamicTableState extends State<DynamicTable> {
|
||||
}
|
||||
|
||||
Widget _buildSelectAllCheckbox() {
|
||||
return SizedBox(
|
||||
width: 50,
|
||||
return Container(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
|
||||
decoration: const BoxDecoration(
|
||||
border: Border.symmetric(
|
||||
vertical: BorderSide(color: ColorsManager.boxDivider))),
|
||||
child: Checkbox(
|
||||
value: _selectAll,
|
||||
onChanged: _toggleSelectAll,
|
||||
@ -150,16 +154,27 @@ class _DynamicTableState extends State<DynamicTable> {
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildRowCheckbox(int index) {
|
||||
return SizedBox(
|
||||
width: 50,
|
||||
child: Checkbox(
|
||||
Widget _buildRowCheckbox(int index,size) {
|
||||
return Container(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
|
||||
height:size ,
|
||||
decoration: const BoxDecoration(
|
||||
border: Border(
|
||||
bottom: BorderSide(
|
||||
color: ColorsManager.boxDivider,
|
||||
width: 1.0,
|
||||
),
|
||||
)),
|
||||
alignment: Alignment.centerLeft,
|
||||
child: Center(child: Checkbox(
|
||||
value: _selected[index],
|
||||
onChanged: (bool? value) {
|
||||
_toggleRowSelection(index, value);
|
||||
},
|
||||
),
|
||||
),)
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
Widget _buildTableHeaderCell(String title) {
|
||||
@ -177,11 +192,11 @@ class _DynamicTableState extends State<DynamicTable> {
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildTableCell(String content) {
|
||||
Widget _buildTableCell(String content,size) {
|
||||
return Expanded(
|
||||
child: Container(
|
||||
height: 80,
|
||||
padding: const EdgeInsets.all(15.0),
|
||||
height:size ,
|
||||
padding: const EdgeInsets.all(5.0),
|
||||
decoration: const BoxDecoration(
|
||||
border: Border(
|
||||
bottom: BorderSide(
|
||||
|
@ -33,8 +33,7 @@ class CustomWebTextField extends StatelessWidget {
|
||||
children: [
|
||||
Text('* ',
|
||||
style: Theme.of(context)
|
||||
.textTheme
|
||||
.bodyMedium!
|
||||
.textTheme.bodyMedium!
|
||||
.copyWith(color: Colors.red),
|
||||
),
|
||||
Text(textFieldName, style: Theme.of(context).textTheme.bodySmall!.copyWith(
|
||||
@ -46,10 +45,8 @@ class CustomWebTextField extends StatelessWidget {
|
||||
child: Text(
|
||||
description??'',
|
||||
style: Theme.of(context)
|
||||
.textTheme
|
||||
.bodySmall!
|
||||
.copyWith(
|
||||
fontSize: 9,
|
||||
.textTheme.bodySmall!
|
||||
.copyWith(fontSize: 9,
|
||||
fontWeight: FontWeight.w400,
|
||||
color: ColorsManager.textGray),
|
||||
),
|
||||
@ -65,21 +62,19 @@ class CustomWebTextField extends StatelessWidget {
|
||||
color: Colors.grey.withOpacity(0.3),
|
||||
spreadRadius:2,
|
||||
blurRadius: 3,
|
||||
offset: Offset(1, 1), // changes position of shadow
|
||||
offset: const Offset(1, 1), // changes position of shadow
|
||||
),
|
||||
]
|
||||
),
|
||||
child: Container(
|
||||
child: TextFormField(
|
||||
validator: validator,
|
||||
controller: controller,
|
||||
style: const TextStyle(color: Colors.black),
|
||||
decoration: textBoxDecoration()!
|
||||
.copyWith(
|
||||
errorStyle: const TextStyle(height: 0), // Hide the error text space
|
||||
child: TextFormField(
|
||||
validator: validator,
|
||||
controller: controller,
|
||||
style: const TextStyle(color: Colors.black),
|
||||
decoration: textBoxDecoration()!
|
||||
.copyWith(
|
||||
errorStyle: const TextStyle(height: 0), // Hide the error text space
|
||||
|
||||
hintText: 'Please enter'),
|
||||
),
|
||||
hintText: 'Please enter'),
|
||||
),
|
||||
),
|
||||
],
|
||||
|
@ -4,7 +4,7 @@ import 'package:flutter/material.dart';
|
||||
|
||||
class HourPickerDialog extends StatefulWidget {
|
||||
final TimeOfDay initialTime;
|
||||
HourPickerDialog({required this.initialTime});
|
||||
const HourPickerDialog({super.key, required this.initialTime});
|
||||
|
||||
@override
|
||||
_HourPickerDialogState createState() => _HourPickerDialogState();
|
||||
@ -24,7 +24,7 @@ class _HourPickerDialogState extends State<HourPickerDialog> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return AlertDialog(
|
||||
title: Text('Select Hour'),
|
||||
title: const Text('Select Hour'),
|
||||
content: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
@ -46,7 +46,7 @@ class _HourPickerDialogState extends State<HourPickerDialog> {
|
||||
SizedBox(width: 16.0),
|
||||
DropdownButton<bool>(
|
||||
value: _isPm,
|
||||
items: [
|
||||
items: const [
|
||||
DropdownMenuItem(
|
||||
value: false,
|
||||
child: Text('AM'),
|
||||
@ -67,14 +67,14 @@ class _HourPickerDialogState extends State<HourPickerDialog> {
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () => Navigator.of(context).pop(null),
|
||||
child: Text('Cancel'),
|
||||
child: const Text('Cancel'),
|
||||
),
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
int hour = _isPm ? _selectedHour + 12 : _selectedHour;
|
||||
Navigator.of(context).pop(TimeOfDay(hour: hour, minute: 0));
|
||||
},
|
||||
child: Text('OK'),
|
||||
child: const Text('OK'),
|
||||
),
|
||||
],
|
||||
);
|
||||
|
@ -66,7 +66,7 @@ class InfoDialog extends StatelessWidget {
|
||||
onPressed: () {
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
child: Text('OK'),
|
||||
child: const Text('OK'),
|
||||
),
|
||||
],
|
||||
);
|
||||
|
@ -2,13 +2,11 @@ import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:flutter_svg/svg.dart';
|
||||
import 'package:syncrow_web/pages/home/bloc/home_bloc.dart';
|
||||
import 'package:syncrow_web/pages/home/bloc/home_state.dart';
|
||||
import 'package:syncrow_web/pages/home/view/home_card.dart';
|
||||
import 'package:syncrow_web/utils/color_manager.dart';
|
||||
import 'package:syncrow_web/utils/constants/assets.dart';
|
||||
import 'package:syncrow_web/web_layout/web_scaffold.dart';
|
||||
|
||||
import '../bloc/home_state.dart';
|
||||
|
||||
class HomeWebPage extends StatelessWidget {
|
||||
HomeWebPage({super.key});
|
||||
@override
|
||||
|
@ -2,6 +2,7 @@ import 'dart:math';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
import 'package:syncrow_web/pages/common/custom_dialog.dart';
|
||||
import 'package:syncrow_web/pages/common/hour_picker_dialog.dart';
|
||||
import 'package:syncrow_web/pages/visitor_password/bloc/visitor_password_event.dart';
|
||||
import 'package:syncrow_web/pages/visitor_password/bloc/visitor_password_state.dart';
|
||||
@ -9,9 +10,9 @@ import 'package:syncrow_web/pages/visitor_password/model/device_model.dart';
|
||||
import 'package:syncrow_web/pages/visitor_password/model/schedule_model.dart';
|
||||
import 'package:syncrow_web/services/access_mang_api.dart';
|
||||
import 'package:syncrow_web/utils/color_manager.dart';
|
||||
import 'package:syncrow_web/utils/constants/assets.dart';
|
||||
import 'package:syncrow_web/utils/snack_bar.dart';
|
||||
|
||||
|
||||
class VisitorPasswordBloc
|
||||
extends Bloc<VisitorPasswordEvent, VisitorPasswordState> {
|
||||
VisitorPasswordBloc() : super(VisitorPasswordInitial()) {
|
||||
@ -23,10 +24,8 @@ class VisitorPasswordBloc
|
||||
on<ToggleDaySelectionEvent>(toggleDaySelection);
|
||||
on<SelectDeviceEvent>(selectDevice);
|
||||
on<UpdateFilteredDevicesEvent>(_onUpdateFilteredDevices);
|
||||
|
||||
on<OnlineOneTimePasswordEvent>(postOnlineOneTimePassword);
|
||||
on<OnlineMultipleTimePasswordEvent>(postOnlineMultipleTimePassword);
|
||||
|
||||
on<OfflineMultipleTimePasswordEvent>(postOfflineMultipleTimePassword);
|
||||
on<OfflineOneTimePasswordEvent>(postOfflineOneTimePassword);
|
||||
on<SelectTimeEvent>(selectTimeOfLinePassword);
|
||||
@ -58,16 +57,12 @@ class VisitorPasswordBloc
|
||||
int? effectiveTimeTimeStamp;
|
||||
int? expirationTimeTimeStamp;
|
||||
|
||||
int? repeatEffectiveTimeTimeStamp;
|
||||
int? repeatExpirationTimeTimeStamp;
|
||||
|
||||
DateTime? startTime = DateTime.now();
|
||||
DateTime? endTime;
|
||||
|
||||
String startTimeAccess = 'Start Time';
|
||||
String endTimeAccess = 'End Time';
|
||||
|
||||
|
||||
selectAccessType(
|
||||
SelectPasswordType event, Emitter<VisitorPasswordState> emit) {
|
||||
accessTypeSelected = event.type;
|
||||
@ -81,9 +76,9 @@ class VisitorPasswordBloc
|
||||
}
|
||||
|
||||
Future<void> selectTimeVisitorPassword(
|
||||
SelectTimeVisitorPassword event,
|
||||
Emitter<VisitorPasswordState> emit,
|
||||
) async {
|
||||
SelectTimeVisitorPassword event,
|
||||
Emitter<VisitorPasswordState> emit,
|
||||
) async {
|
||||
final DateTime? picked = await showDatePicker(
|
||||
context: event.context,
|
||||
initialDate: DateTime.now(),
|
||||
@ -122,7 +117,8 @@ class VisitorPasswordBloc
|
||||
timePicked.minute,
|
||||
);
|
||||
|
||||
final selectedTimestamp = selectedDateTime.millisecondsSinceEpoch ~/ 1000;
|
||||
final selectedTimestamp =
|
||||
selectedDateTime.millisecondsSinceEpoch ~/ 1000;
|
||||
|
||||
if (event.isStart) {
|
||||
if (expirationTimeTimeStamp != null &&
|
||||
@ -133,9 +129,7 @@ class VisitorPasswordBloc
|
||||
return;
|
||||
}
|
||||
effectiveTimeTimeStamp = selectedTimestamp;
|
||||
|
||||
startTimeAccess = selectedDateTime.toString().split('.').first;
|
||||
|
||||
startTimeAccess = selectedDateTime.toString().split('.').first;
|
||||
} else {
|
||||
if (effectiveTimeTimeStamp != null &&
|
||||
selectedTimestamp < effectiveTimeTimeStamp!) {
|
||||
@ -145,11 +139,8 @@ class VisitorPasswordBloc
|
||||
return;
|
||||
}
|
||||
expirationTimeTimeStamp = selectedTimestamp;
|
||||
|
||||
endTimeAccess = selectedDateTime.toString().split('.').first;
|
||||
|
||||
endTimeAccess = selectedDateTime.toString().split('.').first;
|
||||
}
|
||||
|
||||
emit(ChangeTimeState());
|
||||
emit(VisitorPasswordInitial());
|
||||
}
|
||||
@ -201,10 +192,10 @@ class VisitorPasswordBloc
|
||||
}
|
||||
|
||||
//online password
|
||||
|
||||
Future<void> postOnlineOneTimePassword(OnlineOneTimePasswordEvent event,
|
||||
Emitter<VisitorPasswordState> emit) async {
|
||||
try {
|
||||
emit(LoadingInitialState());
|
||||
generate7DigitNumber();
|
||||
bool res = await AccessMangApi().postOnlineOneTime(
|
||||
email: event.email,
|
||||
@ -213,27 +204,37 @@ class VisitorPasswordBloc
|
||||
passwordName: event.passwordName,
|
||||
effectiveTime: effectiveTimeTimeStamp.toString(),
|
||||
invalidTime: expirationTimeTimeStamp.toString());
|
||||
if (res = true) {
|
||||
Navigator.pop(event.context!);
|
||||
if (res == true) {
|
||||
emit(SuccessState());
|
||||
} else {
|
||||
throw Exception('Failed to create password');
|
||||
}
|
||||
emit(TableLoaded(data));
|
||||
} catch (e) {
|
||||
|
||||
emit(FailedState(e.toString()));
|
||||
Navigator.pop(event.context!);
|
||||
stateDialog(
|
||||
context: event.context!,
|
||||
message: e.toString(),
|
||||
title: 'Something Wrong');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Future<void> postOnlineMultipleTimePassword(
|
||||
OnlineMultipleTimePasswordEvent event,
|
||||
Emitter<VisitorPasswordState> emit) async {
|
||||
try {
|
||||
generate7DigitNumber();
|
||||
bool res = await AccessMangApi().postOnlineMultipleTime(
|
||||
emit(LoadingInitialState());
|
||||
|
||||
await generate7DigitNumber();
|
||||
bool res = await AccessMangApi().postOnlineMultipleTime(
|
||||
scheduleList: [
|
||||
if (repeat)
|
||||
Schedule(
|
||||
effectiveTime: getTimeFromDateTimeString(expirationTime),
|
||||
invalidTime: getTimeFromDateTimeString(effectiveTime).toString(),
|
||||
invalidTime:
|
||||
getTimeFromDateTimeString(effectiveTime).toString(),
|
||||
workingDay: selectedDays,
|
||||
),
|
||||
],
|
||||
@ -243,9 +244,11 @@ class VisitorPasswordBloc
|
||||
email: event.email,
|
||||
devicesUuid: selectedDevices,
|
||||
passwordName: event.passwordName);
|
||||
if(res==true){
|
||||
Navigator.pop(event.context!);
|
||||
if (res == true) {
|
||||
emit(SuccessState());
|
||||
emit(TableLoaded(data));
|
||||
}
|
||||
|
||||
} catch (e) {
|
||||
emit(FailedState(e.toString()));
|
||||
}
|
||||
@ -255,11 +258,16 @@ class VisitorPasswordBloc
|
||||
Future<void> postOfflineOneTimePassword(OfflineOneTimePasswordEvent event,
|
||||
Emitter<VisitorPasswordState> emit) async {
|
||||
try {
|
||||
generate7DigitNumber();
|
||||
await AccessMangApi().postOffLineOneTime(
|
||||
emit(LoadingInitialState());
|
||||
await generate7DigitNumber();
|
||||
bool res = await AccessMangApi().postOffLineOneTime(
|
||||
email: event.email,
|
||||
devicesUuid: selectedDevices,
|
||||
passwordName: event.passwordName);
|
||||
if (res == true) {
|
||||
emit(SuccessState());
|
||||
emit(TableLoaded(data));
|
||||
}
|
||||
} catch (e) {
|
||||
emit(FailedState(e.toString()));
|
||||
}
|
||||
@ -269,15 +277,19 @@ class VisitorPasswordBloc
|
||||
OfflineMultipleTimePasswordEvent event,
|
||||
Emitter<VisitorPasswordState> emit) async {
|
||||
try {
|
||||
generate7DigitNumber();
|
||||
await AccessMangApi().postOffLineMultipleTime(
|
||||
email: event.email,
|
||||
devicesUuid: selectedDevices,
|
||||
passwordName: event.passwordName,
|
||||
emit(LoadingInitialState());
|
||||
await generate7DigitNumber();
|
||||
bool res = await AccessMangApi().postOffLineMultipleTime(
|
||||
email: event.email,
|
||||
devicesUuid: selectedDevices,
|
||||
passwordName: event.passwordName,
|
||||
invalidTime: expirationTimeTimeStamp.toString(),
|
||||
effectiveTime: effectiveTimeTimeStamp.toString(),
|
||||
|
||||
);
|
||||
if (res == true) {
|
||||
emit(SuccessState());
|
||||
emit(TableLoaded(data));
|
||||
}
|
||||
} catch (e) {
|
||||
emit(FailedState(e.toString()));
|
||||
}
|
||||
@ -300,13 +312,11 @@ class VisitorPasswordBloc
|
||||
}
|
||||
|
||||
Future generate7DigitNumber() async {
|
||||
emit(LoadingInitialState());
|
||||
passwordController = '';
|
||||
Random random = Random();
|
||||
int min = 1000000;
|
||||
int max = 9999999;
|
||||
passwordController = (min + random.nextInt(max - min + 1)).toString();
|
||||
emit(GeneratePasswordState());
|
||||
return passwordController;
|
||||
}
|
||||
|
||||
@ -319,12 +329,10 @@ class VisitorPasswordBloc
|
||||
final deviceName = deviceNameController.text.toLowerCase();
|
||||
final deviceId = deviceIdController.text.toLowerCase();
|
||||
final unitName = unitNameController.text.toLowerCase();
|
||||
|
||||
final filteredData = data.where((device) {
|
||||
final matchesDeviceName = device.name.toLowerCase().contains(deviceName);
|
||||
final matchesDeviceId = device.uuid.toLowerCase().contains(deviceId);
|
||||
// final matchesUnitName = device.unitName.toLowerCase().contains(unitName); // Assuming unitName is a property of the device
|
||||
|
||||
return matchesDeviceName && matchesDeviceId;
|
||||
}).toList();
|
||||
add(UpdateFilteredDevicesEvent(filteredData));
|
||||
@ -334,7 +342,6 @@ class VisitorPasswordBloc
|
||||
Stream<VisitorPasswordState> mapEventToState(
|
||||
VisitorPasswordEvent event) async* {
|
||||
if (event is FetchDevice) {
|
||||
// Fetching logic...
|
||||
} else if (event is UpdateFilteredDevicesEvent) {
|
||||
yield TableLoaded(event.filteredData);
|
||||
}
|
||||
@ -347,10 +354,11 @@ class VisitorPasswordBloc
|
||||
|
||||
addDeviceToList(context) {
|
||||
selectedDevices = selectedDeviceIds;
|
||||
Navigator.of(context).pop(selectedDevices); // Close the dialog
|
||||
Navigator.of(context).pop(selectedDevices);
|
||||
}
|
||||
|
||||
Future<void> selectTimeOfLinePassword(SelectTimeEvent event, Emitter<VisitorPasswordState> emit) async {
|
||||
Future<void> selectTimeOfLinePassword(
|
||||
SelectTimeEvent event, Emitter<VisitorPasswordState> emit) async {
|
||||
emit(ChangeTimeState());
|
||||
final DateTime? picked = await showDatePicker(
|
||||
context: event.context,
|
||||
@ -416,11 +424,10 @@ class VisitorPasswordBloc
|
||||
endTime = event.val;
|
||||
}
|
||||
}
|
||||
|
||||
DateTime? convertStringToDateTime(String dateTimeString) {
|
||||
try {
|
||||
// Define the input format. Adjust this pattern based on your input string format.
|
||||
final DateFormat inputFormat = DateFormat('yyyy-MM-dd HH:mm:ss');
|
||||
// Convert the string to a DateTime object.
|
||||
DateTime dateTime = inputFormat.parse(dateTimeString);
|
||||
return dateTime;
|
||||
} catch (e) {
|
||||
@ -432,8 +439,6 @@ class VisitorPasswordBloc
|
||||
String getTimeFromDateTimeString(String dateTimeString) {
|
||||
DateTime? dateTime = convertStringToDateTime(dateTimeString);
|
||||
if (dateTime == null) return '';
|
||||
|
||||
// Extract the time component from the DateTime object.
|
||||
return DateFormat('HH:mm').format(dateTime);
|
||||
}
|
||||
|
||||
@ -444,4 +449,27 @@ class VisitorPasswordBloc
|
||||
return null;
|
||||
}
|
||||
|
||||
Future<void> stateDialog({
|
||||
BuildContext? context,
|
||||
String? message,
|
||||
String? title,
|
||||
dynamic actions,
|
||||
}) {
|
||||
return showCustomDialog(
|
||||
context: context!,
|
||||
message: message!,
|
||||
iconPath: Assets.deviceNoteIcon,
|
||||
title: title,
|
||||
dialogHeight: 150,
|
||||
actions: actions ??
|
||||
<Widget>[
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
child: const Text('OK'),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -77,11 +77,12 @@ class OnlineMultipleTimePasswordEvent extends VisitorPasswordEvent {
|
||||
|
||||
//offline password
|
||||
class OfflineOneTimePasswordEvent extends VisitorPasswordEvent {
|
||||
final BuildContext? context;
|
||||
final String? email;
|
||||
final String? passwordName;
|
||||
const OfflineOneTimePasswordEvent({this.email,this.passwordName});
|
||||
const OfflineOneTimePasswordEvent({this.email,this.passwordName,this.context});
|
||||
@override
|
||||
List<Object> get props => [email!,passwordName!,];
|
||||
List<Object> get props => [email!,passwordName!,context!,];
|
||||
}
|
||||
|
||||
class OfflineMultipleTimePasswordEvent extends VisitorPasswordEvent {
|
||||
@ -89,11 +90,12 @@ class OfflineMultipleTimePasswordEvent extends VisitorPasswordEvent {
|
||||
final String? passwordName;
|
||||
final String? invalidTime;
|
||||
final String? effectiveTime;
|
||||
final BuildContext? context;
|
||||
|
||||
const OfflineMultipleTimePasswordEvent({this.email,this.passwordName,this.invalidTime,this.effectiveTime});
|
||||
const OfflineMultipleTimePasswordEvent({this.context,this.email,this.passwordName,this.invalidTime,this.effectiveTime});
|
||||
|
||||
@override
|
||||
List<Object> get props => [email!,passwordName!,invalidTime!,effectiveTime!];
|
||||
List<Object> get props => [email!,passwordName!,invalidTime!,effectiveTime!,context!];
|
||||
}
|
||||
|
||||
|
||||
|
@ -43,7 +43,7 @@ class LoadingInitialState extends VisitorPasswordState {}
|
||||
class ChangeTimeState extends VisitorPasswordState {}
|
||||
class TimeSelectedState extends VisitorPasswordState {}
|
||||
class DeviceLoaded extends VisitorPasswordState {}
|
||||
class GeneratePasswordState extends VisitorPasswordState {}
|
||||
class SuccessState extends VisitorPasswordState {}
|
||||
|
||||
class FailedState extends VisitorPasswordState {
|
||||
final String message;
|
||||
|
@ -12,7 +12,6 @@ import 'package:syncrow_web/utils/constants/assets.dart';
|
||||
import 'package:syncrow_web/utils/constants/const.dart';
|
||||
import 'package:syncrow_web/utils/style.dart';
|
||||
|
||||
|
||||
class AddDeviceDialog extends StatelessWidget {
|
||||
const AddDeviceDialog({super.key});
|
||||
@override
|
||||
@ -54,7 +53,7 @@ class AddDeviceDialog extends StatelessWidget {
|
||||
width: 15,
|
||||
),
|
||||
),
|
||||
SizedBox(width: 10,),
|
||||
const SizedBox(width: 10,),
|
||||
Text('Only online accessible devices can be added',
|
||||
style: Theme.of(context).textTheme.bodySmall!.copyWith(
|
||||
fontWeight: FontWeight.w400,
|
||||
@ -63,13 +62,15 @@ class AddDeviceDialog extends StatelessWidget {
|
||||
],
|
||||
)
|
||||
),
|
||||
SizedBox(height: 20,),
|
||||
const SizedBox(height: 20,),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
mainAxisAlignment: MainAxisAlignment.end,
|
||||
crossAxisAlignment: CrossAxisAlignment.end,
|
||||
textBaseline: TextBaseline.alphabetic,
|
||||
|
||||
children: [
|
||||
Expanded(
|
||||
flex: 2,
|
||||
flex: 4,
|
||||
child: CustomWebTextField(
|
||||
controller: visitorBloc.deviceNameController,
|
||||
isRequired: true,
|
||||
@ -79,7 +80,7 @@ class AddDeviceDialog extends StatelessWidget {
|
||||
),
|
||||
const SizedBox(width: 10),
|
||||
Expanded(
|
||||
flex: 2,
|
||||
flex: 4,
|
||||
child: CustomWebTextField(
|
||||
controller: visitorBloc.deviceIdController,
|
||||
isRequired: true,
|
||||
@ -89,7 +90,7 @@ class AddDeviceDialog extends StatelessWidget {
|
||||
),
|
||||
const SizedBox(width: 10),
|
||||
Expanded(
|
||||
flex: 2,
|
||||
flex: 4,
|
||||
child: CustomWebTextField(
|
||||
controller: visitorBloc.unitNameController,
|
||||
isRequired: true,
|
||||
@ -97,67 +98,49 @@ class AddDeviceDialog extends StatelessWidget {
|
||||
description: '',
|
||||
),
|
||||
),
|
||||
|
||||
const SizedBox(width: 10),
|
||||
Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
const SizedBox(height: 25),
|
||||
Center(
|
||||
child: Container(
|
||||
height: 43,
|
||||
width: 100,
|
||||
decoration: containerDecoration,
|
||||
child: Center(
|
||||
child: DefaultButton(
|
||||
onPressed: () {
|
||||
visitorBloc.filterDevices(); // Call filter function
|
||||
},
|
||||
borderRadius: 9,
|
||||
child: const Text('Search'),
|
||||
),
|
||||
Expanded(
|
||||
flex: 2,
|
||||
child: Container(
|
||||
child: SizedBox(
|
||||
width: size.width * 0.06,
|
||||
child: Center(
|
||||
child: DefaultButton(
|
||||
onPressed: () {
|
||||
visitorBloc.filterDevices();
|
||||
},
|
||||
borderRadius: 9,
|
||||
child: const Text('Search'),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 10),
|
||||
Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
const SizedBox(height: 25),
|
||||
|
||||
Center(
|
||||
child: Container(
|
||||
height: 43,
|
||||
width: 100,
|
||||
decoration: containerDecoration,
|
||||
child: Center(
|
||||
child: DefaultButton(
|
||||
backgroundColor: ColorsManager.whiteColors,
|
||||
borderRadius: 9,
|
||||
child: Text(
|
||||
'Reset',
|
||||
style: Theme.of(context).textTheme.bodySmall!.copyWith(color: Colors.black),
|
||||
),
|
||||
onPressed: () {
|
||||
visitorBloc.deviceNameController.clear();
|
||||
visitorBloc.deviceIdController.clear();
|
||||
visitorBloc.unitNameController.clear();
|
||||
visitorBloc.add(FetchDevice()); // Reset to original list
|
||||
},
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
flex: 2,
|
||||
child: Container(
|
||||
width: size.width * 0.06,
|
||||
child: DefaultButton(
|
||||
backgroundColor: ColorsManager.whiteColors,
|
||||
borderRadius: 9,
|
||||
child: Text('Reset',
|
||||
style: Theme.of(context).textTheme.bodySmall!.copyWith(color: Colors.black),
|
||||
),
|
||||
onPressed: () {
|
||||
visitorBloc.deviceNameController.clear();
|
||||
visitorBloc.deviceIdController.clear();
|
||||
visitorBloc.unitNameController.clear();
|
||||
visitorBloc.add(FetchDevice()); // Reset to original list
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 20),
|
||||
Expanded(
|
||||
flex: 3,
|
||||
child: state is TableLoaded
|
||||
? DynamicTable(
|
||||
cellDecoration: containerDecoration,
|
||||
|
@ -1,11 +1,10 @@
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:flutter_svg/flutter_svg.dart';
|
||||
import 'package:flutter_svg/svg.dart';
|
||||
import 'package:syncrow_web/pages/common/custom_web_textfield.dart';
|
||||
import 'package:syncrow_web/pages/common/date_time_widget.dart';
|
||||
import 'package:syncrow_web/pages/common/default_button.dart';
|
||||
import 'package:syncrow_web/pages/common/info_dialog.dart';
|
||||
import 'package:syncrow_web/pages/visitor_password/bloc/visitor_password_bloc.dart';
|
||||
import 'package:syncrow_web/pages/visitor_password/bloc/visitor_password_event.dart';
|
||||
import 'package:syncrow_web/pages/visitor_password/bloc/visitor_password_state.dart';
|
||||
@ -21,441 +20,517 @@ class VisitorPasswordDialog extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
Size size = MediaQuery.of(context).size;
|
||||
var text = Theme.of(context).textTheme.bodySmall!.copyWith(
|
||||
color: Colors.black,fontSize: 13);
|
||||
return BlocProvider(
|
||||
create: (context) => VisitorPasswordBloc(),
|
||||
child: BlocBuilder<VisitorPasswordBloc, VisitorPasswordState>(
|
||||
builder: (BuildContext context, VisitorPasswordState state) {
|
||||
child: BlocListener<VisitorPasswordBloc, VisitorPasswordState>(
|
||||
listener: (context, state) {
|
||||
final visitorBloc = BlocProvider.of<VisitorPasswordBloc>(context);
|
||||
bool isRepeat =
|
||||
state is IsRepeatState ? state.repeat : visitorBloc.repeat;
|
||||
return AlertDialog(
|
||||
backgroundColor: Colors.white,
|
||||
title: Text(
|
||||
'Create visitor password',
|
||||
style: Theme.of(context).textTheme.headlineLarge!.copyWith(
|
||||
fontWeight: FontWeight.w400,
|
||||
fontSize: 24,
|
||||
color: Colors.black),
|
||||
),
|
||||
content: SingleChildScrollView(
|
||||
child: Form(
|
||||
key: visitorBloc.forgetFormKey,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(5.0),
|
||||
child: ListBody(
|
||||
children: <Widget>[
|
||||
Container(
|
||||
child: Row(
|
||||
children: [
|
||||
Expanded(
|
||||
flex: 2,
|
||||
child: CustomWebTextField(
|
||||
validator: visitorBloc.validate,
|
||||
controller: visitorBloc.userNameController,
|
||||
isRequired: true,
|
||||
textFieldName: 'Name',
|
||||
description: '',
|
||||
),
|
||||
),
|
||||
const Spacer(),
|
||||
Expanded(
|
||||
flex: 2,
|
||||
child: CustomWebTextField(
|
||||
validator: visitorBloc.validateEmail,
|
||||
controller: visitorBloc.emailController,
|
||||
isRequired: true,
|
||||
textFieldName: 'Email Address',
|
||||
description:
|
||||
'The password will be sent to the visitor’s email address.',
|
||||
),
|
||||
),
|
||||
const Spacer(),
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 15,
|
||||
),
|
||||
Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Row(
|
||||
if (state is SuccessState) {
|
||||
visitorBloc.stateDialog(
|
||||
context: context,
|
||||
message: 'Password Created Successfully',
|
||||
title: 'Send Success',
|
||||
);
|
||||
} else if (state is FailedState) {
|
||||
visitorBloc.stateDialog(
|
||||
context: context,
|
||||
message: state.message,
|
||||
title: 'Something Wrong',
|
||||
);
|
||||
}
|
||||
},
|
||||
child: BlocBuilder<VisitorPasswordBloc, VisitorPasswordState>(
|
||||
builder: (BuildContext context, VisitorPasswordState state) {
|
||||
final visitorBloc = BlocProvider.of<VisitorPasswordBloc>(context);
|
||||
bool isRepeat = state is IsRepeatState ? state.repeat : visitorBloc.repeat;
|
||||
return AlertDialog(
|
||||
backgroundColor: Colors.white,
|
||||
title: Text(
|
||||
'Create visitor password',
|
||||
style: Theme.of(context).textTheme.headlineLarge!.copyWith(
|
||||
fontWeight: FontWeight.w400,
|
||||
fontSize: 24,
|
||||
color: Colors.black),
|
||||
),
|
||||
content:
|
||||
state is LoadingInitialState ?const Center(child: CircularProgressIndicator()):
|
||||
SingleChildScrollView(
|
||||
child: Form(
|
||||
key: visitorBloc.forgetFormKey,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(5.0),
|
||||
child: ListBody(
|
||||
children: <Widget>[
|
||||
Container(
|
||||
child: Row(
|
||||
children: [
|
||||
Text(
|
||||
'* ',
|
||||
style: Theme.of(context)
|
||||
.textTheme
|
||||
.bodyMedium!
|
||||
.copyWith(color: Colors.red),
|
||||
Expanded(
|
||||
flex: 2,
|
||||
child: CustomWebTextField(
|
||||
validator: visitorBloc.validate,
|
||||
controller: visitorBloc.userNameController,
|
||||
isRequired: true,
|
||||
textFieldName: 'Name',
|
||||
description: '',
|
||||
),
|
||||
),
|
||||
Text('Access Type',
|
||||
style: Theme.of(context).textTheme.bodySmall!.copyWith(
|
||||
color: Colors.black,fontSize: 13),),
|
||||
const Spacer(),
|
||||
Expanded(
|
||||
flex: 2,
|
||||
child: CustomWebTextField(
|
||||
validator: visitorBloc.validateEmail,
|
||||
controller: visitorBloc.emailController,
|
||||
isRequired: true,
|
||||
textFieldName: 'Email Address',
|
||||
description:
|
||||
'The password will be sent to the visitor’s email address.',
|
||||
),
|
||||
),
|
||||
const Spacer(),
|
||||
],
|
||||
),
|
||||
Row(
|
||||
children: <Widget>[
|
||||
SizedBox(
|
||||
width: size.width * 0.15,
|
||||
child: RadioListTile<String>(
|
||||
title: Text('Online Password',
|
||||
style: Theme.of(context).textTheme.bodySmall!.copyWith(
|
||||
color: Colors.black,fontSize: 13),
|
||||
),
|
||||
value: 'Online Password',
|
||||
groupValue: (state is PasswordTypeSelected)
|
||||
? state.selectedType
|
||||
: visitorBloc.accessTypeSelected,
|
||||
onChanged: (String? value) {
|
||||
if (value != null) {
|
||||
print(value);
|
||||
context
|
||||
.read<VisitorPasswordBloc>()
|
||||
.add(SelectPasswordType(value));
|
||||
}
|
||||
},
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
width: size.width * 0.15,
|
||||
child: RadioListTile<String>(
|
||||
title: Text('Offline Password',
|
||||
style: Theme.of(context).textTheme.bodySmall!.copyWith(
|
||||
color: Colors.black,fontSize: 13),),
|
||||
value: 'Offline Password',
|
||||
groupValue: (state is PasswordTypeSelected)
|
||||
? state.selectedType
|
||||
: visitorBloc.accessTypeSelected,
|
||||
onChanged: (String? value) {
|
||||
if (value != null) {
|
||||
context.read<VisitorPasswordBloc>()
|
||||
.add(SelectPasswordType(value));
|
||||
}
|
||||
},
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
width: size.width * 0.15,
|
||||
child: RadioListTile<String>(
|
||||
title: Text('Dynamic Password',
|
||||
style: Theme.of(context).textTheme.bodySmall!.copyWith(
|
||||
color: Colors.black,fontSize: 13),),
|
||||
value: 'Dynamic Password',
|
||||
groupValue: (state is PasswordTypeSelected)
|
||||
? state.selectedType
|
||||
: visitorBloc.accessTypeSelected,
|
||||
onChanged: (String? value) {
|
||||
if (value != null) {
|
||||
context
|
||||
.read<VisitorPasswordBloc>()
|
||||
.add(SelectPasswordType(value));
|
||||
visitorBloc.usageFrequencySelected = '';
|
||||
}
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
Text(
|
||||
'Only currently online devices can be selected. It is recommended to use when the device network is stable, and the system randomly generates a digital password',
|
||||
style: Theme.of(context).textTheme.bodySmall!.copyWith(
|
||||
fontWeight: FontWeight.w400,
|
||||
color: ColorsManager.grayColor,fontSize: 9),),
|
||||
const SizedBox(
|
||||
height: 20,
|
||||
)
|
||||
],
|
||||
),
|
||||
visitorBloc.accessTypeSelected == 'Dynamic Password'
|
||||
? SizedBox()
|
||||
: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
),
|
||||
const SizedBox(
|
||||
height: 15,
|
||||
),
|
||||
Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
Text(
|
||||
'* ',
|
||||
style: Theme.of(context)
|
||||
.textTheme
|
||||
.bodyMedium!
|
||||
.copyWith(color: Colors.red),
|
||||
),
|
||||
Text('Usage Frequency',style: Theme.of(context).textTheme.bodySmall!.copyWith(
|
||||
color: Colors.black,fontSize: 13),),
|
||||
],
|
||||
Text(
|
||||
'* ',
|
||||
style: Theme.of(context).textTheme
|
||||
.bodyMedium!.copyWith(color: Colors.red),
|
||||
),
|
||||
Row(
|
||||
children: <Widget>[
|
||||
SizedBox(
|
||||
width: 200,
|
||||
child: RadioListTile<String>(
|
||||
title: Text('One-Time',
|
||||
style: Theme.of(context).textTheme.bodySmall!.copyWith(
|
||||
color: Colors.black,fontSize: 13),),
|
||||
value: 'One-Time',
|
||||
groupValue:
|
||||
(state is UsageFrequencySelected)
|
||||
? state.selectedFrequency
|
||||
: visitorBloc.usageFrequencySelected,
|
||||
onChanged: (String? value) {
|
||||
if (value != null) {
|
||||
context.read<VisitorPasswordBloc>()
|
||||
.add(SelectUsageFrequency(value));
|
||||
}
|
||||
},
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
width: 200,
|
||||
child: RadioListTile<String>(
|
||||
title: Text('Periodic',
|
||||
style: Theme.of(context).textTheme.bodySmall!.copyWith(
|
||||
color: Colors.black,fontSize: 13),),
|
||||
value: 'Periodic',
|
||||
groupValue: (state is UsageFrequencySelected)
|
||||
? state.selectedFrequency
|
||||
: visitorBloc.usageFrequencySelected,
|
||||
onChanged: (String? value) {
|
||||
if (value != null) {
|
||||
context
|
||||
.read<VisitorPasswordBloc>()
|
||||
.add(SelectUsageFrequency(value));
|
||||
}
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
Text('Within the validity period, each device can be unlocked only once.',
|
||||
style: Theme.of(context).textTheme.bodySmall!.copyWith(
|
||||
color: ColorsManager.grayColor,fontSize: 9),
|
||||
)
|
||||
Text('Access Type',
|
||||
style:text ),
|
||||
],
|
||||
),
|
||||
const SizedBox(
|
||||
height: 20,
|
||||
),
|
||||
if ((visitorBloc.usageFrequencySelected != 'One-Time' ||
|
||||
visitorBloc.accessTypeSelected != 'Offline Password') &&
|
||||
(visitorBloc.usageFrequencySelected != ''))
|
||||
DateTimeWebWidget(
|
||||
isTime: false,
|
||||
isRequired: true,
|
||||
title: 'Access Period',
|
||||
size: size,
|
||||
endTime: () {
|
||||
visitorBloc.add(SelectTimeVisitorPassword(
|
||||
context: context,
|
||||
isStart: false,
|
||||
isRepeat: false));
|
||||
},
|
||||
startTime: () {
|
||||
visitorBloc.add(SelectTimeVisitorPassword(
|
||||
context: context,
|
||||
isStart: true,
|
||||
isRepeat: false));
|
||||
},
|
||||
firstString: visitorBloc.startTimeAccess.toString(),
|
||||
secondString: visitorBloc.endTimeAccess.toString(),
|
||||
Row(
|
||||
children: <Widget>[
|
||||
SizedBox(
|
||||
width: size.width * 0.15,
|
||||
child: RadioListTile<String>(
|
||||
title: Text('Online Password',
|
||||
style: text,
|
||||
),
|
||||
value: 'Online Password',
|
||||
groupValue: (state is PasswordTypeSelected)
|
||||
? state.selectedType
|
||||
: visitorBloc.accessTypeSelected,
|
||||
onChanged: (String? value) {
|
||||
if (value != null) {
|
||||
context.read<VisitorPasswordBloc>()
|
||||
.add(SelectPasswordType(value));
|
||||
}
|
||||
},
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
width: size.width * 0.15,
|
||||
child: RadioListTile<String>(
|
||||
title: Text('Offline Password',
|
||||
style:text ),
|
||||
value: 'Offline Password',
|
||||
groupValue: (state is PasswordTypeSelected)
|
||||
? state.selectedType
|
||||
: visitorBloc.accessTypeSelected,
|
||||
onChanged: (String? value) {
|
||||
if (value != null) {
|
||||
context.read<VisitorPasswordBloc>().add(SelectPasswordType(value));
|
||||
}
|
||||
},
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
width: size.width * 0.15,
|
||||
child: RadioListTile<String>(
|
||||
title: Text('Dynamic Password',
|
||||
style: text,),
|
||||
value: 'Dynamic Password',
|
||||
groupValue: (state is PasswordTypeSelected)
|
||||
? state.selectedType
|
||||
: visitorBloc.accessTypeSelected,
|
||||
onChanged: (String? value) {
|
||||
if (value != null) {
|
||||
context.read<VisitorPasswordBloc>()
|
||||
.add(SelectPasswordType(value));
|
||||
visitorBloc.usageFrequencySelected = '';
|
||||
}
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
Text(
|
||||
'Only currently online devices can be selected. It is recommended to use when the device network is stable, and the system randomly generates a digital password',
|
||||
style: Theme.of(context).textTheme.bodySmall!.copyWith(
|
||||
fontWeight: FontWeight.w400,
|
||||
color: ColorsManager.grayColor,fontSize: 9),),
|
||||
const SizedBox(
|
||||
height: 20,
|
||||
)
|
||||
],
|
||||
),
|
||||
const SizedBox(
|
||||
height: 20,
|
||||
),
|
||||
Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
Text(
|
||||
'* ',
|
||||
style: Theme.of(context)
|
||||
.textTheme
|
||||
.bodyMedium!
|
||||
.copyWith(color: Colors.red),
|
||||
),
|
||||
Text('Access Devices',
|
||||
style: Theme.of(context).textTheme.bodySmall!.copyWith(
|
||||
color: Colors.black,fontSize: 13),),
|
||||
],
|
||||
visitorBloc.accessTypeSelected == 'Dynamic Password'
|
||||
? const SizedBox()
|
||||
: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
Text('* ',
|
||||
style: Theme.of(context).textTheme.bodyMedium!
|
||||
.copyWith(color: Colors.red),
|
||||
),
|
||||
Text('Usage Frequency',style:text ,),
|
||||
],
|
||||
),
|
||||
Row(
|
||||
children: <Widget>[
|
||||
SizedBox(
|
||||
width: 200,
|
||||
child: RadioListTile<String>(
|
||||
title: Text('One-Time',
|
||||
style:text ,),
|
||||
value: 'One-Time',
|
||||
groupValue:
|
||||
(state is UsageFrequencySelected)
|
||||
? state.selectedFrequency
|
||||
: visitorBloc.usageFrequencySelected,
|
||||
onChanged: (String? value) {
|
||||
if (value != null) {
|
||||
context.read<VisitorPasswordBloc>()
|
||||
.add(SelectUsageFrequency(value));
|
||||
}
|
||||
},
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
width: 200,
|
||||
child: RadioListTile<String>(
|
||||
title: Text('Periodic',
|
||||
style: text),
|
||||
value: 'Periodic',
|
||||
groupValue: (state is UsageFrequencySelected)
|
||||
? state.selectedFrequency
|
||||
: visitorBloc.usageFrequencySelected,
|
||||
onChanged: (String? value) {
|
||||
if (value != null) {
|
||||
context.read<VisitorPasswordBloc>()
|
||||
.add(SelectUsageFrequency(value));
|
||||
}
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
Text('Within the validity period, each device can be unlocked only once.',
|
||||
style: Theme.of(context).textTheme.bodySmall!.copyWith(
|
||||
color: ColorsManager.grayColor,fontSize: 9),
|
||||
)
|
||||
],
|
||||
),
|
||||
const SizedBox(
|
||||
height: 20,
|
||||
),
|
||||
if ((visitorBloc.usageFrequencySelected != 'One-Time' ||
|
||||
visitorBloc.accessTypeSelected != 'Offline Password') &&
|
||||
(visitorBloc.usageFrequencySelected != ''))
|
||||
DateTimeWebWidget(
|
||||
isTime: false,
|
||||
isRequired: true,
|
||||
title: 'Access Period',
|
||||
size: size,
|
||||
endTime: () {
|
||||
visitorBloc.add(SelectTimeVisitorPassword(
|
||||
context: context,
|
||||
isStart: false,
|
||||
isRepeat: false));
|
||||
},
|
||||
startTime: () {
|
||||
visitorBloc.add(SelectTimeVisitorPassword(
|
||||
context: context,
|
||||
isStart: true,
|
||||
isRepeat: false));
|
||||
},
|
||||
firstString: visitorBloc.startTimeAccess.toString(),
|
||||
secondString: visitorBloc.endTimeAccess.toString(),
|
||||
),
|
||||
Text(
|
||||
'Within the validity period, each device can be unlocked only once.',
|
||||
style: Theme.of(context).textTheme.bodySmall!.copyWith(
|
||||
fontWeight: FontWeight.w400,
|
||||
color: ColorsManager.grayColor,fontSize: 9),),
|
||||
const SizedBox(
|
||||
height: 20,
|
||||
),
|
||||
if (visitorBloc.usageFrequencySelected == 'Periodic' &&
|
||||
visitorBloc.accessTypeSelected == 'Online Password')
|
||||
SizedBox(
|
||||
width: 100,
|
||||
child: Column(
|
||||
children: [
|
||||
Text('Repeat',
|
||||
style: Theme.of(context).textTheme.bodySmall!.copyWith(
|
||||
color: Colors.black,fontSize: 13),),
|
||||
Transform.scale(
|
||||
scale: .8,
|
||||
child: CupertinoSwitch(
|
||||
value: visitorBloc.repeat,
|
||||
onChanged: (value) {
|
||||
visitorBloc.add(ToggleRepeatEvent());
|
||||
},
|
||||
applyTheme: true,
|
||||
),
|
||||
),
|
||||
],
|
||||
const SizedBox(
|
||||
height: 20,
|
||||
),
|
||||
Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
Text('* ',
|
||||
style: Theme.of(context).textTheme.bodyMedium!
|
||||
.copyWith(color: Colors.red),
|
||||
),
|
||||
Text('Access Devices',
|
||||
style:text ,),
|
||||
],
|
||||
),
|
||||
Text(
|
||||
'Within the validity period, each device can be unlocked only once.',
|
||||
style: Theme.of(context).textTheme.bodySmall!.copyWith(
|
||||
fontWeight: FontWeight.w400,
|
||||
color: ColorsManager.grayColor,fontSize: 9),),
|
||||
const SizedBox(
|
||||
height: 20,
|
||||
),
|
||||
if (visitorBloc.usageFrequencySelected == 'Periodic' &&
|
||||
visitorBloc.accessTypeSelected == 'Online Password')
|
||||
SizedBox(
|
||||
width: 100,
|
||||
child: Column(
|
||||
children: [
|
||||
Text('Repeat',
|
||||
style:text),
|
||||
Transform.scale(
|
||||
scale: .8,
|
||||
child: CupertinoSwitch(
|
||||
value: visitorBloc.repeat,
|
||||
onChanged: (value) {
|
||||
visitorBloc.add(ToggleRepeatEvent());
|
||||
},
|
||||
applyTheme: true,
|
||||
),
|
||||
),
|
||||
],
|
||||
|
||||
),
|
||||
),
|
||||
if (visitorBloc.usageFrequencySelected == 'Periodic' &&
|
||||
visitorBloc.accessTypeSelected == 'Online Password')
|
||||
isRepeat ? const RepeatWidget() : const SizedBox(),
|
||||
Container(
|
||||
decoration: containerDecoration,
|
||||
width: size.width * 0.08,
|
||||
child: DefaultButton(
|
||||
onPressed: () {
|
||||
showDialog(
|
||||
context: context,
|
||||
barrierDismissible: false,
|
||||
builder: (BuildContext context) {
|
||||
return const AddDeviceDialog();
|
||||
},
|
||||
).then((listDevice) {
|
||||
if(listDevice!=null){
|
||||
visitorBloc.selectedDevices = listDevice;
|
||||
}
|
||||
});
|
||||
},
|
||||
borderRadius: 8,
|
||||
child: Text('+ Add Device',style: Theme.of(context).textTheme.bodySmall!.copyWith(
|
||||
fontWeight: FontWeight.w400,
|
||||
color: ColorsManager.whiteColors,fontSize: 12),),
|
||||
),
|
||||
),
|
||||
if (visitorBloc.usageFrequencySelected == 'Periodic' &&
|
||||
visitorBloc.accessTypeSelected == 'Online Password')
|
||||
isRepeat ? const RepeatWidget() : const SizedBox(),
|
||||
Container(
|
||||
decoration: containerDecoration,
|
||||
width: size.width * 0.08,
|
||||
child: DefaultButton(
|
||||
onPressed: () {
|
||||
showDialog(
|
||||
context: context,
|
||||
barrierDismissible: false,
|
||||
builder: (BuildContext context) {
|
||||
return const AddDeviceDialog();
|
||||
},
|
||||
).then((listDevice) {
|
||||
if(listDevice!=null){
|
||||
print('selectedDevices==$listDevice');
|
||||
visitorBloc.selectedDevices = listDevice;
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
actionsAlignment: MainAxisAlignment.center,
|
||||
actions: <Widget>[
|
||||
Container(
|
||||
decoration: containerDecoration,
|
||||
width: size.width * 0.2,
|
||||
child: DefaultButton(
|
||||
borderRadius: 8,
|
||||
onPressed: () {
|
||||
Navigator.of(context).pop(); // Close the dialog
|
||||
},
|
||||
backgroundColor: Colors.white,
|
||||
child: Text(
|
||||
'Cancel',
|
||||
style: Theme.of(context).textTheme.bodySmall!.copyWith(
|
||||
fontWeight: FontWeight.w400,
|
||||
color: ColorsManager.blackColor,fontSize: 16),
|
||||
),
|
||||
),
|
||||
),
|
||||
Container(
|
||||
decoration: containerDecoration,
|
||||
width: size.width * 0.2,
|
||||
child: DefaultButton(
|
||||
onPressed: () {
|
||||
if (visitorBloc.forgetFormKey.currentState!.validate()) {
|
||||
if(visitorBloc.selectedDevices.isNotEmpty){
|
||||
if(visitorBloc.effectiveTimeTimeStamp!=null&&visitorBloc.expirationTimeTimeStamp!=null) {
|
||||
setPasswordFunction(context, size, visitorBloc);
|
||||
}
|
||||
else{
|
||||
visitorBloc.stateDialog(context:
|
||||
context,message: 'Please select Access Period to continue',title: 'Access Period');
|
||||
}
|
||||
}else{
|
||||
visitorBloc.stateDialog(context:
|
||||
context,message: 'Please select devices to continue',title: 'Select Devices');
|
||||
}
|
||||
}
|
||||
},
|
||||
borderRadius: 8,
|
||||
child: Text('Ok', style: Theme.of(context).textTheme.bodySmall!.copyWith(
|
||||
fontWeight: FontWeight.w400,
|
||||
color: ColorsManager.whiteColors,fontSize: 16),),
|
||||
),
|
||||
),
|
||||
],
|
||||
); },
|
||||
),
|
||||
),
|
||||
|
||||
}
|
||||
});
|
||||
);
|
||||
}
|
||||
|
||||
},
|
||||
borderRadius: 8,
|
||||
child: Text('+ Add Device',style: Theme.of(context).textTheme.bodySmall!.copyWith(
|
||||
fontWeight: FontWeight.w400,
|
||||
color: ColorsManager.whiteColors,fontSize: 12),),
|
||||
Future<void> setPasswordFunction(
|
||||
BuildContext context,
|
||||
Size size,
|
||||
VisitorPasswordBloc visitorBloc,
|
||||
) {
|
||||
return showDialog<void>(
|
||||
context: context,
|
||||
barrierDismissible: false,
|
||||
builder: (BuildContext context) {
|
||||
return BlocBuilder<VisitorPasswordBloc, VisitorPasswordState>(
|
||||
builder: (context, state) {
|
||||
if (state is LoadingInitialState) {
|
||||
// Show loading indicator while loading
|
||||
return AlertDialog(
|
||||
alignment: Alignment.center,
|
||||
content: SizedBox(
|
||||
height: size.height * 0.25,
|
||||
child: Center(
|
||||
child: CircularProgressIndicator(), // Display a loading spinner
|
||||
),
|
||||
),
|
||||
);
|
||||
}else{
|
||||
return AlertDialog(
|
||||
alignment: Alignment.center,
|
||||
content: SizedBox(
|
||||
height: size.height * 0.25,
|
||||
child: Column(
|
||||
children: [
|
||||
Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
SizedBox(
|
||||
child: SvgPicture.asset(
|
||||
Assets.deviceNoteIcon,
|
||||
height: 35,
|
||||
width: 35,
|
||||
),
|
||||
),
|
||||
Text(
|
||||
'Set Password',
|
||||
style: Theme.of(context).textTheme.headlineLarge!.copyWith(
|
||||
fontSize: 30,
|
||||
fontWeight: FontWeight.w400,
|
||||
color: Colors.black,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(width: 15),
|
||||
Text(
|
||||
'This action will update all of the selected\n door locks passwords in the property.\n\nAre you sure you want to continue?',
|
||||
textAlign: TextAlign.center,
|
||||
style: Theme.of(context).textTheme.bodyMedium!.copyWith(
|
||||
color: ColorsManager.grayColor,
|
||||
fontWeight: FontWeight.w400,
|
||||
fontSize: 18,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
actionsAlignment: MainAxisAlignment.center,
|
||||
actions: <Widget>[
|
||||
Container(
|
||||
decoration: containerDecoration,
|
||||
width: size.width * 0.2,
|
||||
child: DefaultButton(
|
||||
borderRadius: 8,
|
||||
onPressed: () {
|
||||
Navigator.of(context).pop(); // Close the dialog
|
||||
},
|
||||
backgroundColor: Colors.white,
|
||||
child: Text(
|
||||
'Cancel',
|
||||
style: Theme.of(context).textTheme.bodySmall!.copyWith(
|
||||
fontWeight: FontWeight.w400,
|
||||
color: ColorsManager.blackColor,fontSize: 16),
|
||||
actionsAlignment: MainAxisAlignment.center,
|
||||
actions: <Widget>[
|
||||
Container(
|
||||
decoration: containerDecoration,
|
||||
width: size.width * 0.1,
|
||||
child: DefaultButton(
|
||||
borderRadius: 8,
|
||||
onPressed: () {
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
backgroundColor: Colors.white,
|
||||
child: Text(
|
||||
'Cancel',
|
||||
style: Theme.of(context).textTheme.bodySmall!.copyWith(
|
||||
fontWeight: FontWeight.w400,
|
||||
color: ColorsManager.blackColor,
|
||||
fontSize: 16,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
Container(
|
||||
decoration: containerDecoration,
|
||||
width: size.width * 0.2,
|
||||
child: DefaultButton(
|
||||
onPressed: () {
|
||||
if (visitorBloc.forgetFormKey.currentState!.validate()) {
|
||||
showDialog(
|
||||
context: context,
|
||||
barrierDismissible: false,
|
||||
builder: (BuildContext context) {
|
||||
return InfoDialog(
|
||||
size: size,
|
||||
title: 'Set Password',
|
||||
content:
|
||||
'This action will update all of the selected\n door locks passwords in the property.\n\nAre you sure you want to continue?',
|
||||
actions: [
|
||||
Container(
|
||||
decoration: containerDecoration,
|
||||
width: size.width * 0.1,
|
||||
child: DefaultButton(
|
||||
borderRadius: 8,
|
||||
onPressed: () {
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
backgroundColor: Colors.white,
|
||||
child: Text(
|
||||
'Cancel',
|
||||
style: Theme.of(context).textTheme.bodySmall!.copyWith(
|
||||
fontWeight: FontWeight.w400,
|
||||
color: ColorsManager.blackColor,fontSize: 16),
|
||||
),
|
||||
),
|
||||
),
|
||||
Container(
|
||||
decoration: containerDecoration,
|
||||
width: size.width * 0.1,
|
||||
child: DefaultButton(
|
||||
borderRadius: 8,
|
||||
onPressed: () {
|
||||
if (visitorBloc.usageFrequencySelected == 'One-Time' &&
|
||||
visitorBloc.accessTypeSelected == 'Online Password') {
|
||||
visitorBloc.add(
|
||||
OnlineOneTimePasswordEvent(
|
||||
context: context,
|
||||
passwordName: visitorBloc.userNameController.text,
|
||||
email: visitorBloc.emailController.text));
|
||||
} else if (visitorBloc.usageFrequencySelected == 'Periodic' &&
|
||||
visitorBloc.accessTypeSelected == 'Online Password') {
|
||||
visitorBloc.add(OnlineMultipleTimePasswordEvent(
|
||||
passwordName: visitorBloc.userNameController.text,
|
||||
email: visitorBloc.emailController.text,
|
||||
effectiveTime: visitorBloc.effectiveTimeTimeStamp.toString(),
|
||||
invalidTime: visitorBloc.expirationTimeTimeStamp.toString()));
|
||||
} else if (visitorBloc.usageFrequencySelected == 'One-Time' &&
|
||||
visitorBloc.accessTypeSelected == 'Offline Password') {
|
||||
visitorBloc.add(OfflineOneTimePasswordEvent(
|
||||
passwordName: visitorBloc.userNameController.text,
|
||||
email: visitorBloc.emailController.text,
|
||||
));
|
||||
} else if (visitorBloc.usageFrequencySelected == 'Periodic' &&
|
||||
visitorBloc.accessTypeSelected == 'Offline Password') {
|
||||
visitorBloc.add(
|
||||
OfflineMultipleTimePasswordEvent(
|
||||
passwordName: visitorBloc.userNameController.text,
|
||||
email: visitorBloc.emailController.text,
|
||||
effectiveTime: visitorBloc.effectiveTimeTimeStamp.toString(),
|
||||
invalidTime: visitorBloc.expirationTimeTimeStamp.toString()));
|
||||
}
|
||||
},
|
||||
child: Text('Ok',
|
||||
style: Theme.of(context).textTheme.bodySmall!.copyWith(
|
||||
fontWeight: FontWeight.w400,
|
||||
color: ColorsManager.whiteColors,fontSize: 16),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
},
|
||||
borderRadius: 8,
|
||||
child: Text('Ok', style: Theme.of(context).textTheme.bodySmall!.copyWith(
|
||||
fontWeight: FontWeight.w400,
|
||||
color: ColorsManager.whiteColors,fontSize: 16),),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
),
|
||||
Container(
|
||||
decoration: containerDecoration,
|
||||
width: size.width * 0.1,
|
||||
child: DefaultButton(
|
||||
borderRadius: 8,
|
||||
onPressed: () {
|
||||
Navigator.pop(context);
|
||||
if (visitorBloc.usageFrequencySelected == 'One-Time' &&
|
||||
visitorBloc.accessTypeSelected == 'Online Password') {
|
||||
visitorBloc.add(OnlineOneTimePasswordEvent(
|
||||
context: context,
|
||||
passwordName: visitorBloc.userNameController.text,
|
||||
email: visitorBloc.emailController.text,
|
||||
));
|
||||
} else if (visitorBloc.usageFrequencySelected == 'Periodic' &&
|
||||
visitorBloc.accessTypeSelected == 'Online Password') {
|
||||
visitorBloc.add(OnlineMultipleTimePasswordEvent(
|
||||
passwordName: visitorBloc.userNameController.text,
|
||||
email: visitorBloc.emailController.text,
|
||||
effectiveTime: visitorBloc.effectiveTimeTimeStamp.toString(),
|
||||
invalidTime: visitorBloc.expirationTimeTimeStamp.toString(),
|
||||
));
|
||||
} else if (visitorBloc.usageFrequencySelected == 'One-Time' &&
|
||||
visitorBloc.accessTypeSelected == 'Offline Password') {
|
||||
visitorBloc.add(OfflineOneTimePasswordEvent(
|
||||
context: context,
|
||||
passwordName: visitorBloc.userNameController.text,
|
||||
email: visitorBloc.emailController.text,
|
||||
));
|
||||
} else if (visitorBloc.usageFrequencySelected == 'Periodic' &&
|
||||
visitorBloc.accessTypeSelected == 'Offline Password') {
|
||||
visitorBloc.add(OfflineMultipleTimePasswordEvent(
|
||||
passwordName: visitorBloc.userNameController.text,
|
||||
email: visitorBloc.emailController.text,
|
||||
effectiveTime: visitorBloc.effectiveTimeTimeStamp.toString(),
|
||||
invalidTime: visitorBloc.expirationTimeTimeStamp.toString(),
|
||||
));
|
||||
}
|
||||
},
|
||||
child: Text(
|
||||
'Ok',
|
||||
style: Theme.of(context).textTheme.bodySmall!.copyWith(
|
||||
fontWeight: FontWeight.w400,
|
||||
color: ColorsManager.whiteColors,
|
||||
fontSize: 16,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
},
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -2,12 +2,11 @@ import 'dart:convert';
|
||||
import 'package:dio/dio.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:syncrow_web/pages/access_management/model/password_model.dart';
|
||||
import 'package:syncrow_web/pages/visitor_password/model/device_model.dart';
|
||||
import 'package:syncrow_web/pages/visitor_password/model/schedule_model.dart';
|
||||
import 'package:syncrow_web/services/api/http_service.dart';
|
||||
import 'package:syncrow_web/utils/constants/api_const.dart';
|
||||
|
||||
import '../pages/visitor_password/model/device_model.dart';
|
||||
|
||||
class AccessMangApi{
|
||||
|
||||
Future<List<PasswordModel>> fetchVisitorPassword() async {
|
||||
@ -17,7 +16,6 @@ class AccessMangApi{
|
||||
showServerMessage: true,
|
||||
expectedResponseModel: (json) {
|
||||
List<dynamic> jsonData = json;
|
||||
print('Password List: $json');
|
||||
List<PasswordModel> passwordList = jsonData.map((jsonItem) {
|
||||
return PasswordModel.fromJson(jsonItem);
|
||||
}).toList();
|
||||
@ -38,7 +36,6 @@ class AccessMangApi{
|
||||
showServerMessage: true,
|
||||
expectedResponseModel: (json) {
|
||||
List<dynamic> jsonData = json;
|
||||
print('fetchDevices List: $json');
|
||||
List<DeviceModel> passwordList = jsonData.map((jsonItem) {
|
||||
return DeviceModel.fromJson(jsonItem);
|
||||
}).toList();
|
||||
@ -60,18 +57,6 @@ class AccessMangApi{
|
||||
String? invalidTime,
|
||||
List<String>? devicesUuid}) async {
|
||||
try {
|
||||
|
||||
print('postOfflineOneTime List: ${
|
||||
jsonEncode({
|
||||
"email": email,
|
||||
"passwordName": passwordName,
|
||||
"password": password,
|
||||
"devicesUuid": devicesUuid,
|
||||
"effectiveTime":effectiveTime ,
|
||||
"invalidTime": invalidTime
|
||||
})
|
||||
}');
|
||||
|
||||
final response = await HTTPService().post(
|
||||
path: ApiEndpoints.sendOnlineOneTime,
|
||||
body: jsonEncode({
|
||||
@ -84,7 +69,6 @@ class AccessMangApi{
|
||||
}),
|
||||
showServerMessage: true,
|
||||
expectedResponseModel: (json) {
|
||||
print('postOfflineOneTime List: $json');
|
||||
if(json['statusCode'].toString()=='201'){
|
||||
return true;
|
||||
}else{
|
||||
@ -93,9 +77,8 @@ class AccessMangApi{
|
||||
},
|
||||
);
|
||||
return response;
|
||||
} on DioException catch (e) {
|
||||
} on DioException catch (e) {
|
||||
debugPrint('Error: ${e.message}');
|
||||
|
||||
debugPrint('Error fetching ${e.response!.statusMessage}');
|
||||
return false;
|
||||
}
|
||||
@ -121,15 +104,11 @@ class AccessMangApi{
|
||||
if (scheduleList != null) {
|
||||
body["scheduleList"] = scheduleList.map((schedule) => schedule.toJson()).toList();
|
||||
}
|
||||
print('createPassword =${jsonEncode(body)}');
|
||||
|
||||
final response = await HTTPService().post(
|
||||
path: ApiEndpoints.sendOnlineMultipleTime,
|
||||
body: jsonEncode(body),
|
||||
showServerMessage: true,
|
||||
expectedResponseModel: (json) {
|
||||
print('createPassword =${json}');
|
||||
|
||||
if(json['data']['successOperations'][0]['success'].toString()=='true'){
|
||||
return true;
|
||||
}else{
|
||||
@ -138,7 +117,7 @@ class AccessMangApi{
|
||||
},
|
||||
);
|
||||
return response;
|
||||
} on DioException catch (e){
|
||||
} on DioException catch (e){
|
||||
debugPrint('Error fetching ${e.type.name}');
|
||||
debugPrint('Error fetching ${e.response!.statusMessage}');
|
||||
return false;
|
||||
@ -149,15 +128,6 @@ class AccessMangApi{
|
||||
|
||||
Future postOffLineOneTime({String? email,String? passwordName,List<String>? devicesUuid}) async {
|
||||
try {
|
||||
|
||||
print('postOfflineOneTime List: ${
|
||||
{
|
||||
"email": email,
|
||||
"passwordName": passwordName,
|
||||
"devicesUuid": devicesUuid
|
||||
}
|
||||
}');
|
||||
|
||||
final response = await HTTPService().post(
|
||||
path: ApiEndpoints.sendOffLineOneTime,
|
||||
body: jsonEncode({
|
||||
@ -166,10 +136,14 @@ class AccessMangApi{
|
||||
"devicesUuid": devicesUuid
|
||||
}),
|
||||
showServerMessage: true,
|
||||
expectedResponseModel: (json) {
|
||||
List<dynamic> jsonData = json;
|
||||
print('postOfflineOneTime List: $json');
|
||||
},
|
||||
expectedResponseModel: (json) {
|
||||
if (json['data']['successOperations'][0]['success'].toString() ==
|
||||
'true') {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
);
|
||||
return response;
|
||||
} catch (e) {
|
||||
@ -187,15 +161,6 @@ class AccessMangApi{
|
||||
|
||||
}) async {
|
||||
try {
|
||||
|
||||
print('postOfflineOneTime List: ${
|
||||
{
|
||||
"email": email,
|
||||
"passwordName": passwordName,
|
||||
"devicesUuid": devicesUuid
|
||||
}
|
||||
}');
|
||||
|
||||
final response = await HTTPService().post(
|
||||
path: ApiEndpoints.sendOffLineOneTime,
|
||||
body: jsonEncode({
|
||||
@ -206,10 +171,14 @@ class AccessMangApi{
|
||||
"invalidTime": invalidTime
|
||||
}),
|
||||
showServerMessage: true,
|
||||
expectedResponseModel: (json) {
|
||||
List<dynamic> jsonData = json;
|
||||
print('postOfflineOneTime List: $json');
|
||||
},
|
||||
expectedResponseModel: (json) {
|
||||
if (json['data']['successOperations'][0]['success'].toString() ==
|
||||
'true') {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
);
|
||||
return response;
|
||||
} catch (e) {
|
||||
|
@ -1,4 +1,3 @@
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:dio/dio.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
@ -8,9 +7,7 @@ import 'package:syncrow_web/services/api/http_service.dart';
|
||||
import 'package:syncrow_web/utils/constants/api_const.dart';
|
||||
|
||||
class AuthenticationAPI {
|
||||
|
||||
static Future<Token> loginWithEmail({required var model}) async {
|
||||
print('model=$model');
|
||||
final response = await HTTPService().post(
|
||||
path: ApiEndpoints.login,
|
||||
body: model.toJson(),
|
||||
@ -46,19 +43,15 @@ class AuthenticationAPI {
|
||||
},
|
||||
showServerMessage: true,
|
||||
expectedResponseModel: (json) {
|
||||
print('object==$json');
|
||||
return 30;
|
||||
}
|
||||
|
||||
);
|
||||
return 30;
|
||||
} on DioException catch (e) {
|
||||
if (e.response != null) {
|
||||
if (e.response!.statusCode == 400) {
|
||||
// Handle 400 Bad Request
|
||||
final errorData = e.response!.data;
|
||||
String errorMessage = errorData['message'];
|
||||
debugPrint('Unexpected Error: $errorMessage');
|
||||
if(errorMessage=='User not found'){
|
||||
return 1;
|
||||
}else{
|
||||
@ -87,8 +80,6 @@ class AuthenticationAPI {
|
||||
body: {"email": email, "type": "PASSWORD", "otpCode": otpCode},
|
||||
showServerMessage: true,
|
||||
expectedResponseModel: (json) {
|
||||
print('json=$json');
|
||||
|
||||
if (json['message'] == 'Otp Verified Successfully') {
|
||||
return true;
|
||||
} else {
|
||||
@ -99,12 +90,9 @@ class AuthenticationAPI {
|
||||
}on DioException catch (e){
|
||||
if (e.response != null) {
|
||||
if (e.response!.statusCode == 400) {
|
||||
// Handle 400 Bad Request
|
||||
final errorData = e.response!.data;
|
||||
String errorMessage = errorData['message'];
|
||||
debugPrint('Unexpected Error: $errorMessage');
|
||||
return errorMessage;
|
||||
|
||||
}
|
||||
} else {
|
||||
debugPrint('Error: ${e.message}');
|
||||
|
@ -3,14 +3,12 @@ import 'package:flutter_svg/svg.dart';
|
||||
import 'package:syncrow_web/utils/constants/assets.dart';
|
||||
import 'package:syncrow_web/web_layout/web_app_bar.dart';
|
||||
import 'menu_sidebar.dart';
|
||||
|
||||
class WebScaffold extends StatelessWidget {
|
||||
final bool enableMenuSideba;
|
||||
final Widget? appBarTitle;
|
||||
final List<Widget>? appBarBody;
|
||||
final Widget? scaffoldBody;
|
||||
const WebScaffold({super.key,this.appBarTitle,this.appBarBody,this.scaffoldBody,this.enableMenuSideba=true});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
|
Reference in New Issue
Block a user