Success dialog and Failed dialog changes with VisitorPasswordDialog

This commit is contained in:
mohammad
2024-08-23 22:16:48 +03:00
parent f5a7441b3c
commit cf1a21e121
19 changed files with 792 additions and 785 deletions

View File

@ -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"
}
]

View File

@ -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/auth/view/login_page.dart';
import 'package:syncrow_web/pages/home/bloc/home_bloc.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/home/view/home_page.dart';
import 'package:syncrow_web/pages/visitor_password/view/add_device_dialog.dart'; import 'package:syncrow_web/pages/visitor_password/bloc/visitor_password_bloc.dart';
import 'package:syncrow_web/pages/visitor_password/view/visitor_password_dialog.dart';
import 'package:syncrow_web/services/locator.dart'; import 'package:syncrow_web/services/locator.dart';
import 'package:syncrow_web/utils/color_manager.dart'; import 'package:syncrow_web/utils/color_manager.dart';
@ -30,6 +29,8 @@ class MyApp extends StatelessWidget {
return MultiBlocProvider( return MultiBlocProvider(
providers: [ providers: [
BlocProvider(create: (context) => HomeBloc()), BlocProvider(create: (context) => HomeBloc()),
BlocProvider<VisitorPasswordBloc>(
create: (context) => VisitorPasswordBloc(),)
], ],
child: MaterialApp( child: MaterialApp(
debugShowCheckedModeBanner: false, // Hide debug banner debugShowCheckedModeBanner: false, // Hide debug banner

View File

@ -39,12 +39,9 @@ class AccessBloc extends Bloc<AccessEvent, AccessState> {
} }
} }
void updateTabsCount() { void updateTabsCount() {
// Count occurrences based on the type field
int toBeEffectiveCount = data.where((item) => item.passwordStatus.value== 'To Be Effective').length; int toBeEffectiveCount = data.where((item) => item.passwordStatus.value== 'To Be Effective').length;
int effectiveCount = data.where((item) => item.passwordStatus.value == 'Effective').length; int effectiveCount = data.where((item) => item.passwordStatus.value == 'Effective').length;
int expiredCount = data.where((item) => item.passwordStatus.value == 'Expired').length; int expiredCount = data.where((item) => item.passwordStatus.value == 'Expired').length;
// Update tab labels with counts
tabs[1] = 'To Be Effective ($toBeEffectiveCount)'; tabs[1] = 'To Be Effective ($toBeEffectiveCount)';
tabs[2] = 'Effective ($effectiveCount)'; tabs[2] = 'Effective ($effectiveCount)';
tabs[3] = 'Expired ($expiredCount)'; tabs[3] = 'Expired ($expiredCount)';
@ -53,7 +50,6 @@ class AccessBloc extends Bloc<AccessEvent, AccessState> {
int selectedIndex = 0; int selectedIndex = 0;
final List<String> tabs = [ final List<String> tabs = [
'All', 'All',
'To Be Effective (0)', 'To Be Effective (0)',
@ -76,7 +72,6 @@ class AccessBloc extends Bloc<AccessEvent, AccessState> {
Future<void> selectTime(SelectTime event, Emitter<AccessState> emit) async { Future<void> selectTime(SelectTime event, Emitter<AccessState> emit) async {
final DateTime? picked = await showDatePicker( final DateTime? picked = await showDatePicker(
context: event.context, context: event.context,
initialDate: DateTime.now(), initialDate: DateTime.now(),
@ -146,8 +141,6 @@ class AccessBloc extends Bloc<AccessEvent, AccessState> {
try { try {
filteredData = data.where((item) { filteredData = data.where((item) {
bool matchesCriteria = true; bool matchesCriteria = true;
// Filter by password name if provided
if (event.passwordName != null && event.passwordName!.isNotEmpty) { if (event.passwordName != null && event.passwordName!.isNotEmpty) {
final bool matchesName = item.passwordName != null && final bool matchesName = item.passwordName != null &&
item.passwordName.contains(event.passwordName); item.passwordName.contains(event.passwordName);
@ -155,8 +148,6 @@ class AccessBloc extends Bloc<AccessEvent, AccessState> {
matchesCriteria = false; matchesCriteria = false;
} }
} }
// Filter by date range if provided
if (event.startTime != null && event.endTime != null) { if (event.startTime != null && event.endTime != null) {
final int? effectiveTime = int.tryParse(item.effectiveTime.toString()); final int? effectiveTime = int.tryParse(item.effectiveTime.toString());
final int? invalidTime = int.tryParse(item.invalidTime.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') { if (event.selectedTabIndex == 1 && item.passwordStatus.value != 'To Be Effective') {
matchesCriteria = false; matchesCriteria = false;
} else if (event.selectedTabIndex == 2 && item.passwordStatus.value != 'Effective') { } 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') { } else if (event.selectedTabIndex == 3 && item.passwordStatus.value != 'Expired') {
matchesCriteria = false; matchesCriteria = false;
} }
return matchesCriteria; return matchesCriteria;
}).toList(); }).toList();
emit(TableLoaded(filteredData)); emit(TableLoaded(filteredData));
@ -206,7 +194,6 @@ class AccessBloc extends Bloc<AccessEvent, AccessState> {
try { try {
emit(AccessLoaded()); emit(AccessLoaded());
selectedIndex = event.selectedIndex; selectedIndex = event.selectedIndex;
// Apply filtering based on selected tab
switch (selectedIndex) { switch (selectedIndex) {
case 0: // All case 0: // All
filteredData = data; filteredData = data;
@ -216,7 +203,6 @@ class AccessBloc extends Bloc<AccessEvent, AccessState> {
break; break;
case 2: // Effective case 2: // Effective
filteredData = data.where((item) => item.passwordStatus.value == "Effective").toList(); filteredData = data.where((item) => item.passwordStatus.value == "Effective").toList();
break; break;
case 3: // Expired case 3: // Expired
filteredData = data.where((item) => item.passwordStatus.value == "Expired").toList(); filteredData = data.where((item) => item.passwordStatus.value == "Expired").toList();
@ -225,7 +211,7 @@ class AccessBloc extends Bloc<AccessEvent, AccessState> {
filteredData = data; filteredData = data;
} }
add(FilterDataEvent( add(FilterDataEvent(
selectedTabIndex: selectedIndex, // Pass the selected tab index selectedTabIndex: selectedIndex,
passwordName: passwordName.text.toLowerCase(), passwordName: passwordName.text.toLowerCase(),
startTime: effectiveTimeTimeStamp, startTime: effectiveTimeTimeStamp,
endTime: expirationTimeTimeStamp endTime: expirationTimeTimeStamp

View File

@ -21,17 +21,14 @@ class AccessManagementPage extends StatelessWidget {
enableMenuSideba: false, enableMenuSideba: false,
appBarTitle: Row( appBarTitle: Row(
children: [ children: [
Text( Text('Access Management',
'Access Management',
style: Theme.of(context).textTheme.headlineLarge, style: Theme.of(context).textTheme.headlineLarge,
) )
], ],
), ),
appBarBody: [ appBarBody: [
Text( Text('Physical Access',
'Physical Access', style: Theme.of(context).textTheme
style: Theme.of(context)
.textTheme
.headlineMedium! .headlineMedium!
.copyWith(color: Colors.white), .copyWith(color: Colors.white),
), ),
@ -101,7 +98,9 @@ class AccessManagementPage extends StatelessWidget {
height: 20, height: 20,
), ),
Row( Row(
children: [ mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.end,
textBaseline: TextBaseline.ideographic, children: [
Column( Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment: MainAxisAlignment.spaceBetween,
@ -111,7 +110,7 @@ class AccessManagementPage extends StatelessWidget {
color: Colors.black,fontSize: 13),), color: Colors.black,fontSize: 13),),
const SizedBox(height: 5,), const SizedBox(height: 5,),
Container( Container(
height:size.height * 0.053, height:43,
width: size.width * 0.15, width: size.width * 0.15,
decoration: containerDecoration, decoration: containerDecoration,
child: TextFormField( child: TextFormField(
@ -145,51 +144,44 @@ class AccessManagementPage extends StatelessWidget {
), ),
SizedBox( SizedBox(
height:45,
width: size.width * 0.06, width: size.width * 0.06,
child: Column( child:Container(
children: [ decoration: containerDecoration,
Text(''), child: DefaultButton(
Container( onPressed: () {
decoration: containerDecoration, accessBloc.add(FilterDataEvent(
child: DefaultButton( selectedTabIndex: BlocProvider.of<AccessBloc>(context).selectedIndex, // Pass the selected tab index
onPressed: () { passwordName: accessBloc.passwordName.text.toLowerCase(),
accessBloc.add(FilterDataEvent( startTime: accessBloc.effectiveTimeTimeStamp,
selectedTabIndex: BlocProvider.of<AccessBloc>(context).selectedIndex, // Pass the selected tab index endTime: accessBloc.expirationTimeTimeStamp
passwordName: accessBloc.passwordName.text.toLowerCase(), ));
startTime: accessBloc.effectiveTimeTimeStamp, }, borderRadius: 9,
endTime: accessBloc.expirationTimeTimeStamp child: const Text('Search'))),
));
}, borderRadius: 9,
child: const Text('Search'))),
],
),
), ),
const SizedBox( const SizedBox(
width: 10, width: 10,
), ),
SizedBox( SizedBox(
height:45,
width: size.width * 0.06, width: size.width * 0.06,
child: Column( child: Container(
children: [ decoration: containerDecoration,
Text(''), child: DefaultButton(
Container( onPressed: () {
decoration: containerDecoration, accessBloc.add(ResetSearch());
child: DefaultButton( },
onPressed: () { backgroundColor: ColorsManager.whiteColors,
accessBloc.add(ResetSearch()); borderRadius: 9,
}, child: Text(
backgroundColor: ColorsManager.whiteColors, 'Reset',
borderRadius: 9, style: Theme.of(context)
child: Text( .textTheme
'Reset', .bodySmall!
style: Theme.of(context) .copyWith(color: Colors.black),
.textTheme
.bodySmall!
.copyWith(color: Colors.black),
),
),
), ),
], ),
), ),
), ),
], ],

View File

@ -146,7 +146,6 @@ class LoginMobilePage extends StatelessWidget {
textAlign: TextAlign.center, textAlign: TextAlign.center,
), ),
), ),
isDense: true, isDense: true,
style: const TextStyle(color: Colors.black), style: const TextStyle(color: Colors.black),
items:loginBloc.regionList!.map((RegionModel region) { items:loginBloc.regionList!.map((RegionModel region) {
@ -156,7 +155,6 @@ class LoginMobilePage extends StatelessWidget {
); );
}).toList(), }).toList(),
onChanged: (String? value) { onChanged: (String? value) {
print(value);
}, },
), ),
) )

View 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),
),
),
],
);
},
);
}

View File

@ -15,7 +15,7 @@ class DynamicTable extends StatefulWidget {
final void Function(int, bool?)? onRowCheckboxChanged; final void Function(int, bool?)? onRowCheckboxChanged;
const DynamicTable({ const DynamicTable({
Key? key, super.key,
required this.headers, required this.headers,
required this.data, required this.data,
required this.size, required this.size,
@ -25,7 +25,7 @@ class DynamicTable extends StatefulWidget {
this.cellDecoration, this.cellDecoration,
this.selectAll, this.selectAll,
this.onRowCheckboxChanged, this.onRowCheckboxChanged,
}) : super(key: key); });
@override @override
_DynamicTableState createState() => _DynamicTableState(); _DynamicTableState createState() => _DynamicTableState();
@ -66,7 +66,7 @@ class _DynamicTableState extends State<DynamicTable> {
return Container( return Container(
decoration: widget.cellDecoration, decoration: widget.cellDecoration,
child: Padding( child: Padding(
padding: const EdgeInsets.all(10.0), padding: const EdgeInsets.all(2.0),
child: child:
ListView( ListView(
scrollDirection: Axis.horizontal, scrollDirection: Axis.horizontal,
@ -102,7 +102,7 @@ class _DynamicTableState extends State<DynamicTable> {
SvgPicture.asset( SvgPicture.asset(
Assets.emptyTable Assets.emptyTable
), ),
SizedBox(height: 15,), const SizedBox(height: 15,),
Text('No Passwords',style: Theme.of(context).textTheme.bodySmall!.copyWith(color:ColorsManager.grayColor ),) Text('No Passwords',style: Theme.of(context).textTheme.bodySmall!.copyWith(color:ColorsManager.grayColor ),)
], ],
), ),
@ -122,9 +122,9 @@ class _DynamicTableState extends State<DynamicTable> {
return Row( return Row(
children: [ children: [
if (widget.withCheckBox) if (widget.withCheckBox)
_buildRowCheckbox(index), _buildRowCheckbox(index,widget.size.height*0.10),
...row.map((cell) => ...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() { Widget _buildSelectAllCheckbox() {
return SizedBox( return Container(
width: 50, padding: const EdgeInsets.all(8.0),
decoration: const BoxDecoration(
border: Border.symmetric(
vertical: BorderSide(color: ColorsManager.boxDivider))),
child: Checkbox( child: Checkbox(
value: _selectAll, value: _selectAll,
onChanged: _toggleSelectAll, onChanged: _toggleSelectAll,
@ -150,16 +154,27 @@ class _DynamicTableState extends State<DynamicTable> {
); );
} }
Widget _buildRowCheckbox(int index) { Widget _buildRowCheckbox(int index,size) {
return SizedBox( return Container(
width: 50, padding: const EdgeInsets.all(8.0),
child: Checkbox(
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], value: _selected[index],
onChanged: (bool? value) { onChanged: (bool? value) {
_toggleRowSelection(index, value); _toggleRowSelection(index, value);
}, },
), ),)
); );
} }
Widget _buildTableHeaderCell(String title) { Widget _buildTableHeaderCell(String title) {
@ -177,11 +192,11 @@ class _DynamicTableState extends State<DynamicTable> {
); );
} }
Widget _buildTableCell(String content) { Widget _buildTableCell(String content,size) {
return Expanded( return Expanded(
child: Container( child: Container(
height: 80, height:size ,
padding: const EdgeInsets.all(15.0), padding: const EdgeInsets.all(5.0),
decoration: const BoxDecoration( decoration: const BoxDecoration(
border: Border( border: Border(
bottom: BorderSide( bottom: BorderSide(

View File

@ -33,8 +33,7 @@ class CustomWebTextField extends StatelessWidget {
children: [ children: [
Text('* ', Text('* ',
style: Theme.of(context) style: Theme.of(context)
.textTheme .textTheme.bodyMedium!
.bodyMedium!
.copyWith(color: Colors.red), .copyWith(color: Colors.red),
), ),
Text(textFieldName, style: Theme.of(context).textTheme.bodySmall!.copyWith( Text(textFieldName, style: Theme.of(context).textTheme.bodySmall!.copyWith(
@ -46,10 +45,8 @@ class CustomWebTextField extends StatelessWidget {
child: Text( child: Text(
description??'', description??'',
style: Theme.of(context) style: Theme.of(context)
.textTheme .textTheme.bodySmall!
.bodySmall! .copyWith(fontSize: 9,
.copyWith(
fontSize: 9,
fontWeight: FontWeight.w400, fontWeight: FontWeight.w400,
color: ColorsManager.textGray), color: ColorsManager.textGray),
), ),
@ -65,21 +62,19 @@ class CustomWebTextField extends StatelessWidget {
color: Colors.grey.withOpacity(0.3), color: Colors.grey.withOpacity(0.3),
spreadRadius:2, spreadRadius:2,
blurRadius: 3, blurRadius: 3,
offset: Offset(1, 1), // changes position of shadow offset: const Offset(1, 1), // changes position of shadow
), ),
] ]
), ),
child: Container( child: TextFormField(
child: TextFormField( validator: validator,
validator: validator, controller: controller,
controller: controller, style: const TextStyle(color: Colors.black),
style: const TextStyle(color: Colors.black), decoration: textBoxDecoration()!
decoration: textBoxDecoration()! .copyWith(
.copyWith( errorStyle: const TextStyle(height: 0), // Hide the error text space
errorStyle: const TextStyle(height: 0), // Hide the error text space
hintText: 'Please enter'), hintText: 'Please enter'),
),
), ),
), ),
], ],

View File

@ -4,7 +4,7 @@ import 'package:flutter/material.dart';
class HourPickerDialog extends StatefulWidget { class HourPickerDialog extends StatefulWidget {
final TimeOfDay initialTime; final TimeOfDay initialTime;
HourPickerDialog({required this.initialTime}); const HourPickerDialog({super.key, required this.initialTime});
@override @override
_HourPickerDialogState createState() => _HourPickerDialogState(); _HourPickerDialogState createState() => _HourPickerDialogState();
@ -24,7 +24,7 @@ class _HourPickerDialogState extends State<HourPickerDialog> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return AlertDialog( return AlertDialog(
title: Text('Select Hour'), title: const Text('Select Hour'),
content: Row( content: Row(
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
children: [ children: [
@ -46,7 +46,7 @@ class _HourPickerDialogState extends State<HourPickerDialog> {
SizedBox(width: 16.0), SizedBox(width: 16.0),
DropdownButton<bool>( DropdownButton<bool>(
value: _isPm, value: _isPm,
items: [ items: const [
DropdownMenuItem( DropdownMenuItem(
value: false, value: false,
child: Text('AM'), child: Text('AM'),
@ -67,14 +67,14 @@ class _HourPickerDialogState extends State<HourPickerDialog> {
actions: [ actions: [
TextButton( TextButton(
onPressed: () => Navigator.of(context).pop(null), onPressed: () => Navigator.of(context).pop(null),
child: Text('Cancel'), child: const Text('Cancel'),
), ),
TextButton( TextButton(
onPressed: () { onPressed: () {
int hour = _isPm ? _selectedHour + 12 : _selectedHour; int hour = _isPm ? _selectedHour + 12 : _selectedHour;
Navigator.of(context).pop(TimeOfDay(hour: hour, minute: 0)); Navigator.of(context).pop(TimeOfDay(hour: hour, minute: 0));
}, },
child: Text('OK'), child: const Text('OK'),
), ),
], ],
); );

View File

@ -66,7 +66,7 @@ class InfoDialog extends StatelessWidget {
onPressed: () { onPressed: () {
Navigator.of(context).pop(); Navigator.of(context).pop();
}, },
child: Text('OK'), child: const Text('OK'),
), ),
], ],
); );

View File

@ -2,13 +2,11 @@ import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_svg/svg.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_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/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/utils/constants/assets.dart';
import 'package:syncrow_web/web_layout/web_scaffold.dart'; import 'package:syncrow_web/web_layout/web_scaffold.dart';
import '../bloc/home_state.dart';
class HomeWebPage extends StatelessWidget { class HomeWebPage extends StatelessWidget {
HomeWebPage({super.key}); HomeWebPage({super.key});
@override @override

View File

@ -2,6 +2,7 @@ import 'dart:math';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:intl/intl.dart'; import 'package:intl/intl.dart';
import 'package:syncrow_web/pages/common/custom_dialog.dart';
import 'package:syncrow_web/pages/common/hour_picker_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_event.dart';
import 'package:syncrow_web/pages/visitor_password/bloc/visitor_password_state.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/pages/visitor_password/model/schedule_model.dart';
import 'package:syncrow_web/services/access_mang_api.dart'; import 'package:syncrow_web/services/access_mang_api.dart';
import 'package:syncrow_web/utils/color_manager.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'; import 'package:syncrow_web/utils/snack_bar.dart';
class VisitorPasswordBloc class VisitorPasswordBloc
extends Bloc<VisitorPasswordEvent, VisitorPasswordState> { extends Bloc<VisitorPasswordEvent, VisitorPasswordState> {
VisitorPasswordBloc() : super(VisitorPasswordInitial()) { VisitorPasswordBloc() : super(VisitorPasswordInitial()) {
@ -23,10 +24,8 @@ class VisitorPasswordBloc
on<ToggleDaySelectionEvent>(toggleDaySelection); on<ToggleDaySelectionEvent>(toggleDaySelection);
on<SelectDeviceEvent>(selectDevice); on<SelectDeviceEvent>(selectDevice);
on<UpdateFilteredDevicesEvent>(_onUpdateFilteredDevices); on<UpdateFilteredDevicesEvent>(_onUpdateFilteredDevices);
on<OnlineOneTimePasswordEvent>(postOnlineOneTimePassword); on<OnlineOneTimePasswordEvent>(postOnlineOneTimePassword);
on<OnlineMultipleTimePasswordEvent>(postOnlineMultipleTimePassword); on<OnlineMultipleTimePasswordEvent>(postOnlineMultipleTimePassword);
on<OfflineMultipleTimePasswordEvent>(postOfflineMultipleTimePassword); on<OfflineMultipleTimePasswordEvent>(postOfflineMultipleTimePassword);
on<OfflineOneTimePasswordEvent>(postOfflineOneTimePassword); on<OfflineOneTimePasswordEvent>(postOfflineOneTimePassword);
on<SelectTimeEvent>(selectTimeOfLinePassword); on<SelectTimeEvent>(selectTimeOfLinePassword);
@ -58,16 +57,12 @@ class VisitorPasswordBloc
int? effectiveTimeTimeStamp; int? effectiveTimeTimeStamp;
int? expirationTimeTimeStamp; int? expirationTimeTimeStamp;
int? repeatEffectiveTimeTimeStamp;
int? repeatExpirationTimeTimeStamp;
DateTime? startTime = DateTime.now(); DateTime? startTime = DateTime.now();
DateTime? endTime; DateTime? endTime;
String startTimeAccess = 'Start Time'; String startTimeAccess = 'Start Time';
String endTimeAccess = 'End Time'; String endTimeAccess = 'End Time';
selectAccessType( selectAccessType(
SelectPasswordType event, Emitter<VisitorPasswordState> emit) { SelectPasswordType event, Emitter<VisitorPasswordState> emit) {
accessTypeSelected = event.type; accessTypeSelected = event.type;
@ -81,9 +76,9 @@ class VisitorPasswordBloc
} }
Future<void> selectTimeVisitorPassword( Future<void> selectTimeVisitorPassword(
SelectTimeVisitorPassword event, SelectTimeVisitorPassword event,
Emitter<VisitorPasswordState> emit, Emitter<VisitorPasswordState> emit,
) async { ) async {
final DateTime? picked = await showDatePicker( final DateTime? picked = await showDatePicker(
context: event.context, context: event.context,
initialDate: DateTime.now(), initialDate: DateTime.now(),
@ -122,7 +117,8 @@ class VisitorPasswordBloc
timePicked.minute, timePicked.minute,
); );
final selectedTimestamp = selectedDateTime.millisecondsSinceEpoch ~/ 1000; final selectedTimestamp =
selectedDateTime.millisecondsSinceEpoch ~/ 1000;
if (event.isStart) { if (event.isStart) {
if (expirationTimeTimeStamp != null && if (expirationTimeTimeStamp != null &&
@ -133,9 +129,7 @@ class VisitorPasswordBloc
return; return;
} }
effectiveTimeTimeStamp = selectedTimestamp; effectiveTimeTimeStamp = selectedTimestamp;
startTimeAccess = selectedDateTime.toString().split('.').first;
startTimeAccess = selectedDateTime.toString().split('.').first;
} else { } else {
if (effectiveTimeTimeStamp != null && if (effectiveTimeTimeStamp != null &&
selectedTimestamp < effectiveTimeTimeStamp!) { selectedTimestamp < effectiveTimeTimeStamp!) {
@ -145,11 +139,8 @@ class VisitorPasswordBloc
return; return;
} }
expirationTimeTimeStamp = selectedTimestamp; expirationTimeTimeStamp = selectedTimestamp;
endTimeAccess = selectedDateTime.toString().split('.').first;
endTimeAccess = selectedDateTime.toString().split('.').first;
} }
emit(ChangeTimeState()); emit(ChangeTimeState());
emit(VisitorPasswordInitial()); emit(VisitorPasswordInitial());
} }
@ -201,10 +192,10 @@ class VisitorPasswordBloc
} }
//online password //online password
Future<void> postOnlineOneTimePassword(OnlineOneTimePasswordEvent event, Future<void> postOnlineOneTimePassword(OnlineOneTimePasswordEvent event,
Emitter<VisitorPasswordState> emit) async { Emitter<VisitorPasswordState> emit) async {
try { try {
emit(LoadingInitialState());
generate7DigitNumber(); generate7DigitNumber();
bool res = await AccessMangApi().postOnlineOneTime( bool res = await AccessMangApi().postOnlineOneTime(
email: event.email, email: event.email,
@ -213,27 +204,37 @@ class VisitorPasswordBloc
passwordName: event.passwordName, passwordName: event.passwordName,
effectiveTime: effectiveTimeTimeStamp.toString(), effectiveTime: effectiveTimeTimeStamp.toString(),
invalidTime: expirationTimeTimeStamp.toString()); invalidTime: expirationTimeTimeStamp.toString());
if (res = true) { if (res == true) {
Navigator.pop(event.context!); emit(SuccessState());
} else {
throw Exception('Failed to create password');
} }
emit(TableLoaded(data)); emit(TableLoaded(data));
} catch (e) { } catch (e) {
emit(FailedState(e.toString())); emit(FailedState(e.toString()));
Navigator.pop(event.context!);
stateDialog(
context: event.context!,
message: e.toString(),
title: 'Something Wrong');
} }
} }
Future<void> postOnlineMultipleTimePassword( Future<void> postOnlineMultipleTimePassword(
OnlineMultipleTimePasswordEvent event, OnlineMultipleTimePasswordEvent event,
Emitter<VisitorPasswordState> emit) async { Emitter<VisitorPasswordState> emit) async {
try { try {
generate7DigitNumber(); emit(LoadingInitialState());
bool res = await AccessMangApi().postOnlineMultipleTime(
await generate7DigitNumber();
bool res = await AccessMangApi().postOnlineMultipleTime(
scheduleList: [ scheduleList: [
if (repeat) if (repeat)
Schedule( Schedule(
effectiveTime: getTimeFromDateTimeString(expirationTime), effectiveTime: getTimeFromDateTimeString(expirationTime),
invalidTime: getTimeFromDateTimeString(effectiveTime).toString(), invalidTime:
getTimeFromDateTimeString(effectiveTime).toString(),
workingDay: selectedDays, workingDay: selectedDays,
), ),
], ],
@ -243,9 +244,11 @@ class VisitorPasswordBloc
email: event.email, email: event.email,
devicesUuid: selectedDevices, devicesUuid: selectedDevices,
passwordName: event.passwordName); passwordName: event.passwordName);
if(res==true){ if (res == true) {
Navigator.pop(event.context!); emit(SuccessState());
emit(TableLoaded(data));
} }
} catch (e) { } catch (e) {
emit(FailedState(e.toString())); emit(FailedState(e.toString()));
} }
@ -255,11 +258,16 @@ class VisitorPasswordBloc
Future<void> postOfflineOneTimePassword(OfflineOneTimePasswordEvent event, Future<void> postOfflineOneTimePassword(OfflineOneTimePasswordEvent event,
Emitter<VisitorPasswordState> emit) async { Emitter<VisitorPasswordState> emit) async {
try { try {
generate7DigitNumber(); emit(LoadingInitialState());
await AccessMangApi().postOffLineOneTime( await generate7DigitNumber();
bool res = await AccessMangApi().postOffLineOneTime(
email: event.email, email: event.email,
devicesUuid: selectedDevices, devicesUuid: selectedDevices,
passwordName: event.passwordName); passwordName: event.passwordName);
if (res == true) {
emit(SuccessState());
emit(TableLoaded(data));
}
} catch (e) { } catch (e) {
emit(FailedState(e.toString())); emit(FailedState(e.toString()));
} }
@ -269,15 +277,19 @@ class VisitorPasswordBloc
OfflineMultipleTimePasswordEvent event, OfflineMultipleTimePasswordEvent event,
Emitter<VisitorPasswordState> emit) async { Emitter<VisitorPasswordState> emit) async {
try { try {
generate7DigitNumber(); emit(LoadingInitialState());
await AccessMangApi().postOffLineMultipleTime( await generate7DigitNumber();
email: event.email, bool res = await AccessMangApi().postOffLineMultipleTime(
devicesUuid: selectedDevices, email: event.email,
passwordName: event.passwordName, devicesUuid: selectedDevices,
passwordName: event.passwordName,
invalidTime: expirationTimeTimeStamp.toString(), invalidTime: expirationTimeTimeStamp.toString(),
effectiveTime: effectiveTimeTimeStamp.toString(), effectiveTime: effectiveTimeTimeStamp.toString(),
); );
if (res == true) {
emit(SuccessState());
emit(TableLoaded(data));
}
} catch (e) { } catch (e) {
emit(FailedState(e.toString())); emit(FailedState(e.toString()));
} }
@ -300,13 +312,11 @@ class VisitorPasswordBloc
} }
Future generate7DigitNumber() async { Future generate7DigitNumber() async {
emit(LoadingInitialState());
passwordController = ''; passwordController = '';
Random random = Random(); Random random = Random();
int min = 1000000; int min = 1000000;
int max = 9999999; int max = 9999999;
passwordController = (min + random.nextInt(max - min + 1)).toString(); passwordController = (min + random.nextInt(max - min + 1)).toString();
emit(GeneratePasswordState());
return passwordController; return passwordController;
} }
@ -319,12 +329,10 @@ class VisitorPasswordBloc
final deviceName = deviceNameController.text.toLowerCase(); final deviceName = deviceNameController.text.toLowerCase();
final deviceId = deviceIdController.text.toLowerCase(); final deviceId = deviceIdController.text.toLowerCase();
final unitName = unitNameController.text.toLowerCase(); final unitName = unitNameController.text.toLowerCase();
final filteredData = data.where((device) { final filteredData = data.where((device) {
final matchesDeviceName = device.name.toLowerCase().contains(deviceName); final matchesDeviceName = device.name.toLowerCase().contains(deviceName);
final matchesDeviceId = device.uuid.toLowerCase().contains(deviceId); final matchesDeviceId = device.uuid.toLowerCase().contains(deviceId);
// final matchesUnitName = device.unitName.toLowerCase().contains(unitName); // Assuming unitName is a property of the device // final matchesUnitName = device.unitName.toLowerCase().contains(unitName); // Assuming unitName is a property of the device
return matchesDeviceName && matchesDeviceId; return matchesDeviceName && matchesDeviceId;
}).toList(); }).toList();
add(UpdateFilteredDevicesEvent(filteredData)); add(UpdateFilteredDevicesEvent(filteredData));
@ -334,7 +342,6 @@ class VisitorPasswordBloc
Stream<VisitorPasswordState> mapEventToState( Stream<VisitorPasswordState> mapEventToState(
VisitorPasswordEvent event) async* { VisitorPasswordEvent event) async* {
if (event is FetchDevice) { if (event is FetchDevice) {
// Fetching logic...
} else if (event is UpdateFilteredDevicesEvent) { } else if (event is UpdateFilteredDevicesEvent) {
yield TableLoaded(event.filteredData); yield TableLoaded(event.filteredData);
} }
@ -347,10 +354,11 @@ class VisitorPasswordBloc
addDeviceToList(context) { addDeviceToList(context) {
selectedDevices = selectedDeviceIds; 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()); emit(ChangeTimeState());
final DateTime? picked = await showDatePicker( final DateTime? picked = await showDatePicker(
context: event.context, context: event.context,
@ -416,11 +424,10 @@ class VisitorPasswordBloc
endTime = event.val; endTime = event.val;
} }
} }
DateTime? convertStringToDateTime(String dateTimeString) { DateTime? convertStringToDateTime(String dateTimeString) {
try { try {
// Define the input format. Adjust this pattern based on your input string format.
final DateFormat inputFormat = DateFormat('yyyy-MM-dd HH:mm:ss'); final DateFormat inputFormat = DateFormat('yyyy-MM-dd HH:mm:ss');
// Convert the string to a DateTime object.
DateTime dateTime = inputFormat.parse(dateTimeString); DateTime dateTime = inputFormat.parse(dateTimeString);
return dateTime; return dateTime;
} catch (e) { } catch (e) {
@ -432,8 +439,6 @@ class VisitorPasswordBloc
String getTimeFromDateTimeString(String dateTimeString) { String getTimeFromDateTimeString(String dateTimeString) {
DateTime? dateTime = convertStringToDateTime(dateTimeString); DateTime? dateTime = convertStringToDateTime(dateTimeString);
if (dateTime == null) return ''; if (dateTime == null) return '';
// Extract the time component from the DateTime object.
return DateFormat('HH:mm').format(dateTime); return DateFormat('HH:mm').format(dateTime);
} }
@ -444,4 +449,27 @@ class VisitorPasswordBloc
return null; 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'),
),
],
);
}
} }

View File

@ -77,11 +77,12 @@ class OnlineMultipleTimePasswordEvent extends VisitorPasswordEvent {
//offline password //offline password
class OfflineOneTimePasswordEvent extends VisitorPasswordEvent { class OfflineOneTimePasswordEvent extends VisitorPasswordEvent {
final BuildContext? context;
final String? email; final String? email;
final String? passwordName; final String? passwordName;
const OfflineOneTimePasswordEvent({this.email,this.passwordName}); const OfflineOneTimePasswordEvent({this.email,this.passwordName,this.context});
@override @override
List<Object> get props => [email!,passwordName!,]; List<Object> get props => [email!,passwordName!,context!,];
} }
class OfflineMultipleTimePasswordEvent extends VisitorPasswordEvent { class OfflineMultipleTimePasswordEvent extends VisitorPasswordEvent {
@ -89,11 +90,12 @@ class OfflineMultipleTimePasswordEvent extends VisitorPasswordEvent {
final String? passwordName; final String? passwordName;
final String? invalidTime; final String? invalidTime;
final String? effectiveTime; 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 @override
List<Object> get props => [email!,passwordName!,invalidTime!,effectiveTime!]; List<Object> get props => [email!,passwordName!,invalidTime!,effectiveTime!,context!];
} }

View File

@ -43,7 +43,7 @@ class LoadingInitialState extends VisitorPasswordState {}
class ChangeTimeState extends VisitorPasswordState {} class ChangeTimeState extends VisitorPasswordState {}
class TimeSelectedState extends VisitorPasswordState {} class TimeSelectedState extends VisitorPasswordState {}
class DeviceLoaded extends VisitorPasswordState {} class DeviceLoaded extends VisitorPasswordState {}
class GeneratePasswordState extends VisitorPasswordState {} class SuccessState extends VisitorPasswordState {}
class FailedState extends VisitorPasswordState { class FailedState extends VisitorPasswordState {
final String message; final String message;

View File

@ -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/constants/const.dart';
import 'package:syncrow_web/utils/style.dart'; import 'package:syncrow_web/utils/style.dart';
class AddDeviceDialog extends StatelessWidget { class AddDeviceDialog extends StatelessWidget {
const AddDeviceDialog({super.key}); const AddDeviceDialog({super.key});
@override @override
@ -54,7 +53,7 @@ class AddDeviceDialog extends StatelessWidget {
width: 15, width: 15,
), ),
), ),
SizedBox(width: 10,), const SizedBox(width: 10,),
Text('Only online accessible devices can be added', Text('Only online accessible devices can be added',
style: Theme.of(context).textTheme.bodySmall!.copyWith( style: Theme.of(context).textTheme.bodySmall!.copyWith(
fontWeight: FontWeight.w400, fontWeight: FontWeight.w400,
@ -63,13 +62,15 @@ class AddDeviceDialog extends StatelessWidget {
], ],
) )
), ),
SizedBox(height: 20,), const SizedBox(height: 20,),
Row( Row(
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.end,
crossAxisAlignment: CrossAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.end,
textBaseline: TextBaseline.alphabetic,
children: [ children: [
Expanded( Expanded(
flex: 2, flex: 4,
child: CustomWebTextField( child: CustomWebTextField(
controller: visitorBloc.deviceNameController, controller: visitorBloc.deviceNameController,
isRequired: true, isRequired: true,
@ -79,7 +80,7 @@ class AddDeviceDialog extends StatelessWidget {
), ),
const SizedBox(width: 10), const SizedBox(width: 10),
Expanded( Expanded(
flex: 2, flex: 4,
child: CustomWebTextField( child: CustomWebTextField(
controller: visitorBloc.deviceIdController, controller: visitorBloc.deviceIdController,
isRequired: true, isRequired: true,
@ -89,7 +90,7 @@ class AddDeviceDialog extends StatelessWidget {
), ),
const SizedBox(width: 10), const SizedBox(width: 10),
Expanded( Expanded(
flex: 2, flex: 4,
child: CustomWebTextField( child: CustomWebTextField(
controller: visitorBloc.unitNameController, controller: visitorBloc.unitNameController,
isRequired: true, isRequired: true,
@ -97,67 +98,49 @@ class AddDeviceDialog extends StatelessWidget {
description: '', description: '',
), ),
), ),
const SizedBox(width: 10), const SizedBox(width: 10),
Column( Expanded(
crossAxisAlignment: CrossAxisAlignment.center, flex: 2,
children: [ child: Container(
const SizedBox(height: 25), child: SizedBox(
Center( width: size.width * 0.06,
child: Container( child: Center(
height: 43, child: DefaultButton(
width: 100, onPressed: () {
decoration: containerDecoration, visitorBloc.filterDevices();
child: Center( },
child: DefaultButton( borderRadius: 9,
onPressed: () { child: const Text('Search'),
visitorBloc.filterDevices(); // Call filter function
},
borderRadius: 9,
child: const Text('Search'),
),
), ),
), ),
), ),
),
],
), ),
const SizedBox(width: 10), const SizedBox(width: 10),
Column( Expanded(
crossAxisAlignment: CrossAxisAlignment.center, flex: 2,
children: [ child: Container(
const SizedBox(height: 25), width: size.width * 0.06,
child: DefaultButton(
Center( backgroundColor: ColorsManager.whiteColors,
child: Container( borderRadius: 9,
height: 43, child: Text('Reset',
width: 100, style: Theme.of(context).textTheme.bodySmall!.copyWith(color: Colors.black),
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
},
),
),
), ),
onPressed: () {
visitorBloc.deviceNameController.clear();
visitorBloc.deviceIdController.clear();
visitorBloc.unitNameController.clear();
visitorBloc.add(FetchDevice()); // Reset to original list
},
), ),
], ),
), )
], ],
), ),
const SizedBox(height: 20), const SizedBox(height: 20),
Expanded( Expanded(
flex: 3,
child: state is TableLoaded child: state is TableLoaded
? DynamicTable( ? DynamicTable(
cellDecoration: containerDecoration, cellDecoration: containerDecoration,

View File

@ -1,11 +1,10 @@
import 'package:flutter/cupertino.dart'; import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_bloc/flutter_bloc.dart';
import 'package: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/custom_web_textfield.dart';
import 'package:syncrow_web/pages/common/date_time_widget.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/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_bloc.dart';
import 'package:syncrow_web/pages/visitor_password/bloc/visitor_password_event.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'; import 'package:syncrow_web/pages/visitor_password/bloc/visitor_password_state.dart';
@ -21,441 +20,517 @@ class VisitorPasswordDialog extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
Size size = MediaQuery.of(context).size; Size size = MediaQuery.of(context).size;
var text = Theme.of(context).textTheme.bodySmall!.copyWith(
color: Colors.black,fontSize: 13);
return BlocProvider( return BlocProvider(
create: (context) => VisitorPasswordBloc(), create: (context) => VisitorPasswordBloc(),
child: BlocBuilder<VisitorPasswordBloc, VisitorPasswordState>( child: BlocListener<VisitorPasswordBloc, VisitorPasswordState>(
builder: (BuildContext context, VisitorPasswordState state) { listener: (context, state) {
final visitorBloc = BlocProvider.of<VisitorPasswordBloc>(context); final visitorBloc = BlocProvider.of<VisitorPasswordBloc>(context);
bool isRepeat = if (state is SuccessState) {
state is IsRepeatState ? state.repeat : visitorBloc.repeat; visitorBloc.stateDialog(
return AlertDialog( context: context,
backgroundColor: Colors.white, message: 'Password Created Successfully',
title: Text( title: 'Send Success',
'Create visitor password', );
style: Theme.of(context).textTheme.headlineLarge!.copyWith( } else if (state is FailedState) {
fontWeight: FontWeight.w400, visitorBloc.stateDialog(
fontSize: 24, context: context,
color: Colors.black), message: state.message,
), title: 'Something Wrong',
content: SingleChildScrollView( );
child: Form( }
key: visitorBloc.forgetFormKey, },
child: Padding( child: BlocBuilder<VisitorPasswordBloc, VisitorPasswordState>(
padding: const EdgeInsets.all(5.0), builder: (BuildContext context, VisitorPasswordState state) {
child: ListBody( final visitorBloc = BlocProvider.of<VisitorPasswordBloc>(context);
children: <Widget>[ bool isRepeat = state is IsRepeatState ? state.repeat : visitorBloc.repeat;
Container( return AlertDialog(
child: Row( backgroundColor: Colors.white,
children: [ title: Text(
Expanded( 'Create visitor password',
flex: 2, style: Theme.of(context).textTheme.headlineLarge!.copyWith(
child: CustomWebTextField( fontWeight: FontWeight.w400,
validator: visitorBloc.validate, fontSize: 24,
controller: visitorBloc.userNameController, color: Colors.black),
isRequired: true, ),
textFieldName: 'Name', content:
description: '', state is LoadingInitialState ?const Center(child: CircularProgressIndicator()):
), SingleChildScrollView(
), child: Form(
const Spacer(), key: visitorBloc.forgetFormKey,
Expanded( child: Padding(
flex: 2, padding: const EdgeInsets.all(5.0),
child: CustomWebTextField( child: ListBody(
validator: visitorBloc.validateEmail, children: <Widget>[
controller: visitorBloc.emailController, Container(
isRequired: true, child: Row(
textFieldName: 'Email Address',
description:
'The password will be sent to the visitors email address.',
),
),
const Spacer(),
],
),
),
const SizedBox(
height: 15,
),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [ children: [
Text( Expanded(
'* ', flex: 2,
style: Theme.of(context) child: CustomWebTextField(
.textTheme validator: visitorBloc.validate,
.bodyMedium! controller: visitorBloc.userNameController,
.copyWith(color: Colors.red), isRequired: true,
textFieldName: 'Name',
description: '',
),
), ),
Text('Access Type', const Spacer(),
style: Theme.of(context).textTheme.bodySmall!.copyWith( Expanded(
color: Colors.black,fontSize: 13),), flex: 2,
child: CustomWebTextField(
validator: visitorBloc.validateEmail,
controller: visitorBloc.emailController,
isRequired: true,
textFieldName: 'Email Address',
description:
'The password will be sent to the visitors email address.',
),
),
const Spacer(),
], ],
), ),
Row( ),
children: <Widget>[ const SizedBox(
SizedBox( height: 15,
width: size.width * 0.15, ),
child: RadioListTile<String>( Column(
title: Text('Online Password', crossAxisAlignment: CrossAxisAlignment.start,
style: Theme.of(context).textTheme.bodySmall!.copyWith( children: [
color: Colors.black,fontSize: 13), Row(
),
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,
children: [ children: [
Row( Text(
children: [ '* ',
Text( style: Theme.of(context).textTheme
'* ', .bodyMedium!.copyWith(color: Colors.red),
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),),
],
), ),
Row( Text('Access Type',
children: <Widget>[ style:text ),
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),
)
], ],
), ),
const SizedBox( Row(
height: 20, children: <Widget>[
), SizedBox(
if ((visitorBloc.usageFrequencySelected != 'One-Time' || width: size.width * 0.15,
visitorBloc.accessTypeSelected != 'Offline Password') && child: RadioListTile<String>(
(visitorBloc.usageFrequencySelected != '')) title: Text('Online Password',
DateTimeWebWidget( style: text,
isTime: false, ),
isRequired: true, value: 'Online Password',
title: 'Access Period', groupValue: (state is PasswordTypeSelected)
size: size, ? state.selectedType
endTime: () { : visitorBloc.accessTypeSelected,
visitorBloc.add(SelectTimeVisitorPassword( onChanged: (String? value) {
context: context, if (value != null) {
isStart: false, context.read<VisitorPasswordBloc>()
isRepeat: false)); .add(SelectPasswordType(value));
}, }
startTime: () { },
visitorBloc.add(SelectTimeVisitorPassword( ),
context: context, ),
isStart: true, SizedBox(
isRepeat: false)); width: size.width * 0.15,
}, child: RadioListTile<String>(
firstString: visitorBloc.startTimeAccess.toString(), title: Text('Offline Password',
secondString: visitorBloc.endTimeAccess.toString(), 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( visitorBloc.accessTypeSelected == 'Dynamic Password'
height: 20, ? const SizedBox()
), : Column(
Column( crossAxisAlignment: CrossAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start, children: [
children: [ Row(
Row( children: [
children: [ Text('* ',
Text( style: Theme.of(context).textTheme.bodyMedium!
'* ', .copyWith(color: Colors.red),
style: Theme.of(context) ),
.textTheme Text('Usage Frequency',style:text ,),
.bodyMedium! ],
.copyWith(color: Colors.red), ),
), Row(
Text('Access Devices', children: <Widget>[
style: Theme.of(context).textTheme.bodySmall!.copyWith( SizedBox(
color: Colors.black,fontSize: 13),), 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( const SizedBox(
'Within the validity period, each device can be unlocked only once.', height: 20,
style: Theme.of(context).textTheme.bodySmall!.copyWith( ),
fontWeight: FontWeight.w400, Column(
color: ColorsManager.grayColor,fontSize: 9),), crossAxisAlignment: CrossAxisAlignment.start,
const SizedBox( children: [
height: 20, Row(
), children: [
if (visitorBloc.usageFrequencySelected == 'Periodic' && Text('* ',
visitorBloc.accessTypeSelected == 'Online Password') style: Theme.of(context).textTheme.bodyMedium!
SizedBox( .copyWith(color: Colors.red),
width: 100, ),
child: Column( Text('Access Devices',
children: [ style:text ,),
Text('Repeat', ],
style: Theme.of(context).textTheme.bodySmall!.copyWith( ),
color: Colors.black,fontSize: 13),), Text(
Transform.scale( 'Within the validity period, each device can be unlocked only once.',
scale: .8, style: Theme.of(context).textTheme.bodySmall!.copyWith(
child: CupertinoSwitch( fontWeight: FontWeight.w400,
value: visitorBloc.repeat, color: ColorsManager.grayColor,fontSize: 9),),
onChanged: (value) { const SizedBox(
visitorBloc.add(ToggleRepeatEvent()); height: 20,
}, ),
applyTheme: true, 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: () { actionsAlignment: MainAxisAlignment.center,
showDialog( actions: <Widget>[
context: context, Container(
barrierDismissible: false, decoration: containerDecoration,
builder: (BuildContext context) { width: size.width * 0.2,
return const AddDeviceDialog(); child: DefaultButton(
}, borderRadius: 8,
).then((listDevice) { onPressed: () {
if(listDevice!=null){ Navigator.of(context).pop(); // Close the dialog
print('selectedDevices==$listDevice'); },
visitorBloc.selectedDevices = listDevice; 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),),
),
),
],
); },
),
),
} );
}); }
}, Future<void> setPasswordFunction(
borderRadius: 8, BuildContext context,
child: Text('+ Add Device',style: Theme.of(context).textTheme.bodySmall!.copyWith( Size size,
fontWeight: FontWeight.w400, VisitorPasswordBloc visitorBloc,
color: ColorsManager.whiteColors,fontSize: 12),), ) {
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>[
actionsAlignment: MainAxisAlignment.center, Container(
actions: <Widget>[ decoration: containerDecoration,
Container( width: size.width * 0.1,
decoration: containerDecoration, child: DefaultButton(
width: size.width * 0.2, borderRadius: 8,
child: DefaultButton( onPressed: () {
borderRadius: 8, Navigator.of(context).pop();
onPressed: () { },
Navigator.of(context).pop(); // Close the dialog backgroundColor: Colors.white,
}, child: Text(
backgroundColor: Colors.white, 'Cancel',
child: Text( style: Theme.of(context).textTheme.bodySmall!.copyWith(
'Cancel', fontWeight: FontWeight.w400,
style: Theme.of(context).textTheme.bodySmall!.copyWith( color: ColorsManager.blackColor,
fontWeight: FontWeight.w400, fontSize: 16,
color: ColorsManager.blackColor,fontSize: 16), ),
),
),
), ),
), Container(
), decoration: containerDecoration,
Container( width: size.width * 0.1,
decoration: containerDecoration, child: DefaultButton(
width: size.width * 0.2, borderRadius: 8,
child: DefaultButton( onPressed: () {
onPressed: () { Navigator.pop(context);
if (visitorBloc.forgetFormKey.currentState!.validate()) { if (visitorBloc.usageFrequencySelected == 'One-Time' &&
showDialog( visitorBloc.accessTypeSelected == 'Online Password') {
context: context, visitorBloc.add(OnlineOneTimePasswordEvent(
barrierDismissible: false, context: context,
builder: (BuildContext context) { passwordName: visitorBloc.userNameController.text,
return InfoDialog( email: visitorBloc.emailController.text,
size: size, ));
title: 'Set Password', } else if (visitorBloc.usageFrequencySelected == 'Periodic' &&
content: visitorBloc.accessTypeSelected == 'Online Password') {
'This action will update all of the selected\n door locks passwords in the property.\n\nAre you sure you want to continue?', visitorBloc.add(OnlineMultipleTimePasswordEvent(
actions: [ passwordName: visitorBloc.userNameController.text,
Container( email: visitorBloc.emailController.text,
decoration: containerDecoration, effectiveTime: visitorBloc.effectiveTimeTimeStamp.toString(),
width: size.width * 0.1, invalidTime: visitorBloc.expirationTimeTimeStamp.toString(),
child: DefaultButton( ));
borderRadius: 8, } else if (visitorBloc.usageFrequencySelected == 'One-Time' &&
onPressed: () { visitorBloc.accessTypeSelected == 'Offline Password') {
Navigator.of(context).pop(); visitorBloc.add(OfflineOneTimePasswordEvent(
}, context: context,
backgroundColor: Colors.white, passwordName: visitorBloc.userNameController.text,
child: Text( email: visitorBloc.emailController.text,
'Cancel', ));
style: Theme.of(context).textTheme.bodySmall!.copyWith( } else if (visitorBloc.usageFrequencySelected == 'Periodic' &&
fontWeight: FontWeight.w400, visitorBloc.accessTypeSelected == 'Offline Password') {
color: ColorsManager.blackColor,fontSize: 16), visitorBloc.add(OfflineMultipleTimePasswordEvent(
), passwordName: visitorBloc.userNameController.text,
), email: visitorBloc.emailController.text,
), effectiveTime: visitorBloc.effectiveTimeTimeStamp.toString(),
Container( invalidTime: visitorBloc.expirationTimeTimeStamp.toString(),
decoration: containerDecoration, ));
width: size.width * 0.1, }
child: DefaultButton( },
borderRadius: 8, child: Text(
onPressed: () { 'Ok',
if (visitorBloc.usageFrequencySelected == 'One-Time' && style: Theme.of(context).textTheme.bodySmall!.copyWith(
visitorBloc.accessTypeSelected == 'Online Password') { fontWeight: FontWeight.w400,
visitorBloc.add( color: ColorsManager.whiteColors,
OnlineOneTimePasswordEvent( fontSize: 16,
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),),
),
),
],
);
},
),
); );
} }
} }

View File

@ -2,12 +2,11 @@ import 'dart:convert';
import 'package:dio/dio.dart'; import 'package:dio/dio.dart';
import 'package:flutter/cupertino.dart'; import 'package:flutter/cupertino.dart';
import 'package:syncrow_web/pages/access_management/model/password_model.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/pages/visitor_password/model/schedule_model.dart';
import 'package:syncrow_web/services/api/http_service.dart'; import 'package:syncrow_web/services/api/http_service.dart';
import 'package:syncrow_web/utils/constants/api_const.dart'; import 'package:syncrow_web/utils/constants/api_const.dart';
import '../pages/visitor_password/model/device_model.dart';
class AccessMangApi{ class AccessMangApi{
Future<List<PasswordModel>> fetchVisitorPassword() async { Future<List<PasswordModel>> fetchVisitorPassword() async {
@ -17,7 +16,6 @@ class AccessMangApi{
showServerMessage: true, showServerMessage: true,
expectedResponseModel: (json) { expectedResponseModel: (json) {
List<dynamic> jsonData = json; List<dynamic> jsonData = json;
print('Password List: $json');
List<PasswordModel> passwordList = jsonData.map((jsonItem) { List<PasswordModel> passwordList = jsonData.map((jsonItem) {
return PasswordModel.fromJson(jsonItem); return PasswordModel.fromJson(jsonItem);
}).toList(); }).toList();
@ -38,7 +36,6 @@ class AccessMangApi{
showServerMessage: true, showServerMessage: true,
expectedResponseModel: (json) { expectedResponseModel: (json) {
List<dynamic> jsonData = json; List<dynamic> jsonData = json;
print('fetchDevices List: $json');
List<DeviceModel> passwordList = jsonData.map((jsonItem) { List<DeviceModel> passwordList = jsonData.map((jsonItem) {
return DeviceModel.fromJson(jsonItem); return DeviceModel.fromJson(jsonItem);
}).toList(); }).toList();
@ -60,18 +57,6 @@ class AccessMangApi{
String? invalidTime, String? invalidTime,
List<String>? devicesUuid}) async { List<String>? devicesUuid}) async {
try { try {
print('postOfflineOneTime List: ${
jsonEncode({
"email": email,
"passwordName": passwordName,
"password": password,
"devicesUuid": devicesUuid,
"effectiveTime":effectiveTime ,
"invalidTime": invalidTime
})
}');
final response = await HTTPService().post( final response = await HTTPService().post(
path: ApiEndpoints.sendOnlineOneTime, path: ApiEndpoints.sendOnlineOneTime,
body: jsonEncode({ body: jsonEncode({
@ -84,7 +69,6 @@ class AccessMangApi{
}), }),
showServerMessage: true, showServerMessage: true,
expectedResponseModel: (json) { expectedResponseModel: (json) {
print('postOfflineOneTime List: $json');
if(json['statusCode'].toString()=='201'){ if(json['statusCode'].toString()=='201'){
return true; return true;
}else{ }else{
@ -93,9 +77,8 @@ class AccessMangApi{
}, },
); );
return response; return response;
} on DioException catch (e) { } on DioException catch (e) {
debugPrint('Error: ${e.message}'); debugPrint('Error: ${e.message}');
debugPrint('Error fetching ${e.response!.statusMessage}'); debugPrint('Error fetching ${e.response!.statusMessage}');
return false; return false;
} }
@ -121,15 +104,11 @@ class AccessMangApi{
if (scheduleList != null) { if (scheduleList != null) {
body["scheduleList"] = scheduleList.map((schedule) => schedule.toJson()).toList(); body["scheduleList"] = scheduleList.map((schedule) => schedule.toJson()).toList();
} }
print('createPassword =${jsonEncode(body)}');
final response = await HTTPService().post( final response = await HTTPService().post(
path: ApiEndpoints.sendOnlineMultipleTime, path: ApiEndpoints.sendOnlineMultipleTime,
body: jsonEncode(body), body: jsonEncode(body),
showServerMessage: true, showServerMessage: true,
expectedResponseModel: (json) { expectedResponseModel: (json) {
print('createPassword =${json}');
if(json['data']['successOperations'][0]['success'].toString()=='true'){ if(json['data']['successOperations'][0]['success'].toString()=='true'){
return true; return true;
}else{ }else{
@ -138,7 +117,7 @@ class AccessMangApi{
}, },
); );
return response; return response;
} on DioException catch (e){ } on DioException catch (e){
debugPrint('Error fetching ${e.type.name}'); debugPrint('Error fetching ${e.type.name}');
debugPrint('Error fetching ${e.response!.statusMessage}'); debugPrint('Error fetching ${e.response!.statusMessage}');
return false; return false;
@ -149,15 +128,6 @@ class AccessMangApi{
Future postOffLineOneTime({String? email,String? passwordName,List<String>? devicesUuid}) async { Future postOffLineOneTime({String? email,String? passwordName,List<String>? devicesUuid}) async {
try { try {
print('postOfflineOneTime List: ${
{
"email": email,
"passwordName": passwordName,
"devicesUuid": devicesUuid
}
}');
final response = await HTTPService().post( final response = await HTTPService().post(
path: ApiEndpoints.sendOffLineOneTime, path: ApiEndpoints.sendOffLineOneTime,
body: jsonEncode({ body: jsonEncode({
@ -166,10 +136,14 @@ class AccessMangApi{
"devicesUuid": devicesUuid "devicesUuid": devicesUuid
}), }),
showServerMessage: true, showServerMessage: true,
expectedResponseModel: (json) { expectedResponseModel: (json) {
List<dynamic> jsonData = json; if (json['data']['successOperations'][0]['success'].toString() ==
print('postOfflineOneTime List: $json'); 'true') {
}, return true;
} else {
return false;
}
}
); );
return response; return response;
} catch (e) { } catch (e) {
@ -187,15 +161,6 @@ class AccessMangApi{
}) async { }) async {
try { try {
print('postOfflineOneTime List: ${
{
"email": email,
"passwordName": passwordName,
"devicesUuid": devicesUuid
}
}');
final response = await HTTPService().post( final response = await HTTPService().post(
path: ApiEndpoints.sendOffLineOneTime, path: ApiEndpoints.sendOffLineOneTime,
body: jsonEncode({ body: jsonEncode({
@ -206,10 +171,14 @@ class AccessMangApi{
"invalidTime": invalidTime "invalidTime": invalidTime
}), }),
showServerMessage: true, showServerMessage: true,
expectedResponseModel: (json) { expectedResponseModel: (json) {
List<dynamic> jsonData = json; if (json['data']['successOperations'][0]['success'].toString() ==
print('postOfflineOneTime List: $json'); 'true') {
}, return true;
} else {
return false;
}
}
); );
return response; return response;
} catch (e) { } catch (e) {

View File

@ -1,4 +1,3 @@
import 'dart:convert';
import 'package:dio/dio.dart'; import 'package:dio/dio.dart';
import 'package:flutter/foundation.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'; import 'package:syncrow_web/utils/constants/api_const.dart';
class AuthenticationAPI { class AuthenticationAPI {
static Future<Token> loginWithEmail({required var model}) async { static Future<Token> loginWithEmail({required var model}) async {
print('model=$model');
final response = await HTTPService().post( final response = await HTTPService().post(
path: ApiEndpoints.login, path: ApiEndpoints.login,
body: model.toJson(), body: model.toJson(),
@ -46,19 +43,15 @@ class AuthenticationAPI {
}, },
showServerMessage: true, showServerMessage: true,
expectedResponseModel: (json) { expectedResponseModel: (json) {
print('object==$json');
return 30; return 30;
} }
); );
return 30; return 30;
} on DioException catch (e) { } on DioException catch (e) {
if (e.response != null) { if (e.response != null) {
if (e.response!.statusCode == 400) { if (e.response!.statusCode == 400) {
// Handle 400 Bad Request
final errorData = e.response!.data; final errorData = e.response!.data;
String errorMessage = errorData['message']; String errorMessage = errorData['message'];
debugPrint('Unexpected Error: $errorMessage');
if(errorMessage=='User not found'){ if(errorMessage=='User not found'){
return 1; return 1;
}else{ }else{
@ -87,8 +80,6 @@ class AuthenticationAPI {
body: {"email": email, "type": "PASSWORD", "otpCode": otpCode}, body: {"email": email, "type": "PASSWORD", "otpCode": otpCode},
showServerMessage: true, showServerMessage: true,
expectedResponseModel: (json) { expectedResponseModel: (json) {
print('json=$json');
if (json['message'] == 'Otp Verified Successfully') { if (json['message'] == 'Otp Verified Successfully') {
return true; return true;
} else { } else {
@ -99,12 +90,9 @@ class AuthenticationAPI {
}on DioException catch (e){ }on DioException catch (e){
if (e.response != null) { if (e.response != null) {
if (e.response!.statusCode == 400) { if (e.response!.statusCode == 400) {
// Handle 400 Bad Request
final errorData = e.response!.data; final errorData = e.response!.data;
String errorMessage = errorData['message']; String errorMessage = errorData['message'];
debugPrint('Unexpected Error: $errorMessage');
return errorMessage; return errorMessage;
} }
} else { } else {
debugPrint('Error: ${e.message}'); debugPrint('Error: ${e.message}');

View File

@ -3,14 +3,12 @@ import 'package:flutter_svg/svg.dart';
import 'package:syncrow_web/utils/constants/assets.dart'; import 'package:syncrow_web/utils/constants/assets.dart';
import 'package:syncrow_web/web_layout/web_app_bar.dart'; import 'package:syncrow_web/web_layout/web_app_bar.dart';
import 'menu_sidebar.dart'; import 'menu_sidebar.dart';
class WebScaffold extends StatelessWidget { class WebScaffold extends StatelessWidget {
final bool enableMenuSideba; final bool enableMenuSideba;
final Widget? appBarTitle; final Widget? appBarTitle;
final List<Widget>? appBarBody; final List<Widget>? appBarBody;
final Widget? scaffoldBody; final Widget? scaffoldBody;
const WebScaffold({super.key,this.appBarTitle,this.appBarBody,this.scaffoldBody,this.enableMenuSideba=true}); const WebScaffold({super.key,this.appBarTitle,this.appBarBody,this.scaffoldBody,this.enableMenuSideba=true});
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Scaffold( return Scaffold(