On access management page Create visitor password dialog is not responsive (#289)

<!--
  Thanks for contributing!

Provide a description of your changes below and a general summary in the
title

Please look at the following checklist to ensure that your PR can be
accepted quickly:
-->

## Jira Ticket
[SP-1474](https://syncrow.atlassian.net/browse/SP-1474)

## Description

<!--- Describe your changes in detail -->
Add responsive input fields and radio groups for visitor password setup

## Type of Change

<!--- Put an `x` in all the boxes that apply: -->

- [ ]  New feature (non-breaking change which adds functionality)
- [x] 🛠️ Bug fix (non-breaking change which fixes an issue)
- [ ]  Breaking change (fix or feature that would cause existing
functionality to change)
- [ ] 🧹 Code refactor
- [ ]  Build configuration change
- [ ] 📝 Documentation
- [ ] 🗑️ Chore 


[SP-1474]:
https://syncrow.atlassian.net/browse/SP-1474?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ
This commit is contained in:
mohammadnemer1
2025-06-24 12:27:39 +03:00
committed by GitHub
4 changed files with 574 additions and 299 deletions

View File

@ -0,0 +1,120 @@
import 'package:flutter/material.dart';
import 'package:syncrow_web/pages/visitor_password/bloc/visitor_password_bloc.dart';
class AccessTypeRadioGroup extends StatelessWidget {
final String? selectedType;
final String? accessTypeSelected;
final Function(String) onTypeSelected;
final VisitorPasswordBloc visitorBloc;
const AccessTypeRadioGroup({
super.key,
required this.selectedType,
required this.accessTypeSelected,
required this.onTypeSelected,
required this.visitorBloc,
});
@override
Widget build(BuildContext context) {
Size size = MediaQuery.of(context).size;
final text = Theme.of(context)
.textTheme
.bodySmall!
.copyWith(color: Colors.black, fontSize: 13);
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [
Text(
'* ',
style: Theme.of(context)
.textTheme
.bodyMedium!
.copyWith(color: Colors.red),
),
Text('Access Type', style: text),
],
),
const SizedBox(height: 8),
if (size.width < 800)
Column(
children: [
_buildRadioTile(
context,
'Online Password',
selectedType ?? accessTypeSelected,
onTypeSelected,
),
const SizedBox(height: 8),
_buildRadioTile(
context,
'Offline Password',
selectedType ?? accessTypeSelected,
onTypeSelected,
),
],
)
else
Row(
children: [
Expanded(
flex: 2,
child: Row(
children: [
_buildRadioTile(
context,
'Online Password',
selectedType ?? accessTypeSelected,
onTypeSelected,
width: size.width * 0.12,
),
_buildRadioTile(
context,
'Offline Password',
selectedType ?? accessTypeSelected,
onTypeSelected,
width: size.width * 0.12,
),
],
),
),
const Spacer(flex: 2),
],
),
],
);
}
Widget _buildRadioTile(
BuildContext context,
String value,
String? groupValue,
Function(String) onChanged, {
double? width,
}) {
return SizedBox(
width: width,
child: RadioListTile<String>(
contentPadding: EdgeInsets.zero,
title: Text(value,
style: Theme.of(context).textTheme.bodySmall!.copyWith(
color: Colors.black,
fontSize: 13,
)),
value: value,
groupValue: groupValue,
onChanged: (value) {
if (value != null) {
onChanged(value);
if (value == 'Dynamic Password') {
visitorBloc.usageFrequencySelected = '';
}
}
},
),
);
}
}

View File

@ -0,0 +1,73 @@
import 'package:flutter/material.dart';
import 'package:syncrow_web/pages/common/text_field/custom_web_textfield.dart';
class NameAndEmailFields extends StatelessWidget {
final TextEditingController nameController;
final TextEditingController emailController;
final String? Function(String?)? nameValidator;
final String? Function(String?)? emailValidator;
const NameAndEmailFields({
super.key,
required this.nameController,
required this.emailController,
required this.nameValidator,
required this.emailValidator,
});
@override
Widget build(BuildContext context) {
Size size = MediaQuery.of(context).size;
return Container(
width: size.width,
child: size.width < 800
? Column(
children: [
CustomWebTextField(
validator: nameValidator,
controller: nameController,
isRequired: true,
textFieldName: 'Name',
description: '',
),
const SizedBox(height: 15),
CustomWebTextField(
validator: emailValidator,
controller: emailController,
isRequired: true,
textFieldName: 'Email Address',
description:
'The password will be sent to the visitors email address.',
),
],
)
: Row(
children: [
Expanded(
flex: 2,
child: CustomWebTextField(
validator: nameValidator,
controller: nameController,
isRequired: true,
textFieldName: 'Name',
description: '',
),
),
const Spacer(),
Expanded(
flex: 2,
child: CustomWebTextField(
validator: emailValidator,
controller: emailController,
isRequired: true,
textFieldName: 'Email Address',
description:
'The password will be sent to the visitors email address.',
),
),
const Spacer(),
],
),
);
}
}

View File

@ -0,0 +1,91 @@
import 'package:flutter/material.dart';
class UsageFrequencyRadioGroup extends StatelessWidget {
final String? selectedFrequency;
final String? usageFrequencySelected;
final Function(String) onFrequencySelected;
const UsageFrequencyRadioGroup({
super.key,
required this.selectedFrequency,
required this.usageFrequencySelected,
required this.onFrequencySelected,
});
@override
Widget build(BuildContext context) {
Size size = MediaQuery.of(context).size;
final text = Theme.of(context)
.textTheme
.bodySmall!
.copyWith(color: Colors.black, fontSize: 13);
return size.width < 600
? Column(
children: [
_buildRadioTile(
context,
'One-Time',
selectedFrequency ?? usageFrequencySelected,
onFrequencySelected,
text: text,
fullWidth: true,
),
const SizedBox(height: 8),
_buildRadioTile(
context,
'Periodic',
selectedFrequency ?? usageFrequencySelected,
onFrequencySelected,
text: text,
fullWidth: true,
),
],
)
: Row(
children: [
_buildRadioTile(
context,
'One-Time',
selectedFrequency ?? usageFrequencySelected,
onFrequencySelected,
width: size.width * 0.12,
text: text,
),
_buildRadioTile(
context,
'Periodic',
selectedFrequency ?? usageFrequencySelected,
onFrequencySelected,
width: size.width * 0.12,
text: text,
),
],
);
}
Widget _buildRadioTile(
BuildContext context,
String value,
String? groupValue,
Function(String) onChanged, {
double? width,
required TextStyle text,
bool fullWidth = false,
}) {
return SizedBox(
width: fullWidth ? double.infinity : width,
child: RadioListTile<String>(
contentPadding: EdgeInsets.zero,
title: Text(value, style: text),
value: value,
groupValue: groupValue,
onChanged: (String? value) {
if (value != null) {
onChanged(value);
}
},
),
);
}
}

View File

@ -9,8 +9,11 @@ import 'package:syncrow_web/pages/common/text_field/custom_web_textfield.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';
import 'package:syncrow_web/pages/visitor_password/view/access_type_radio_group.dart';
import 'package:syncrow_web/pages/visitor_password/view/add_device_dialog.dart'; import 'package:syncrow_web/pages/visitor_password/view/add_device_dialog.dart';
import 'package:syncrow_web/pages/visitor_password/view/repeat_widget.dart'; import 'package:syncrow_web/pages/visitor_password/view/repeat_widget.dart';
import 'package:syncrow_web/pages/visitor_password/view/responsive_fields_row.dart';
import 'package:syncrow_web/pages/visitor_password/view/usage_frequency_radio_group.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/constants/assets.dart';
import 'package:syncrow_web/utils/style.dart'; import 'package:syncrow_web/utils/style.dart';
@ -21,7 +24,10 @@ 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); var text = Theme.of(context)
.textTheme
.bodySmall!
.copyWith(color: Colors.black, fontSize: 13);
return BlocProvider( return BlocProvider(
create: (context) => VisitorPasswordBloc(), create: (context) => VisitorPasswordBloc(),
child: BlocListener<VisitorPasswordBloc, VisitorPasswordState>( child: BlocListener<VisitorPasswordBloc, VisitorPasswordState>(
@ -35,7 +41,8 @@ class VisitorPasswordDialog extends StatelessWidget {
title: 'Sent Successfully', title: 'Sent Successfully',
widgeta: Column( widgeta: Column(
children: [ children: [
if (visitorBloc.passwordStatus!.failedOperations.isNotEmpty) if (visitorBloc
.passwordStatus!.failedOperations.isNotEmpty)
Column( Column(
children: [ children: [
const Text('Failed Devices'), const Text('Failed Devices'),
@ -45,7 +52,8 @@ class VisitorPasswordDialog extends StatelessWidget {
child: ListView.builder( child: ListView.builder(
scrollDirection: Axis.horizontal, scrollDirection: Axis.horizontal,
shrinkWrap: true, shrinkWrap: true,
itemCount: visitorBloc.passwordStatus!.failedOperations.length, itemCount: visitorBloc
.passwordStatus!.failedOperations.length,
itemBuilder: (context, index) { itemBuilder: (context, index) {
return Container( return Container(
margin: EdgeInsets.all(5), margin: EdgeInsets.all(5),
@ -53,14 +61,17 @@ class VisitorPasswordDialog extends StatelessWidget {
height: 45, height: 45,
child: Center( child: Center(
child: Text(visitorBloc child: Text(visitorBloc
.passwordStatus!.failedOperations[index].deviceUuid)), .passwordStatus!
.failedOperations[index]
.deviceUuid)),
); );
}, },
), ),
), ),
], ],
), ),
if (visitorBloc.passwordStatus!.successOperations.isNotEmpty) if (visitorBloc
.passwordStatus!.successOperations.isNotEmpty)
Column( Column(
children: [ children: [
const Text('Success Devices'), const Text('Success Devices'),
@ -70,15 +81,18 @@ class VisitorPasswordDialog extends StatelessWidget {
child: ListView.builder( child: ListView.builder(
scrollDirection: Axis.horizontal, scrollDirection: Axis.horizontal,
shrinkWrap: true, shrinkWrap: true,
itemCount: visitorBloc.passwordStatus!.successOperations.length, itemCount: visitorBloc
.passwordStatus!.successOperations.length,
itemBuilder: (context, index) { itemBuilder: (context, index) {
return Container( return Container(
margin: EdgeInsets.all(5), margin: EdgeInsets.all(5),
decoration: containerDecoration, decoration: containerDecoration,
height: 45, height: 45,
child: Center( child: Center(
child: Text(visitorBloc.passwordStatus! child: Text(visitorBloc
.successOperations[index].deviceUuid)), .passwordStatus!
.successOperations[index]
.deviceUuid)),
); );
}, },
), ),
@ -89,7 +103,6 @@ class VisitorPasswordDialog extends StatelessWidget {
)) ))
.then((v) { .then((v) {
Navigator.of(context).pop(true); Navigator.of(context).pop(true);
}); });
} else if (state is FailedState) { } else if (state is FailedState) {
visitorBloc.stateDialog( visitorBloc.stateDialog(
@ -102,15 +115,16 @@ class VisitorPasswordDialog extends StatelessWidget {
child: BlocBuilder<VisitorPasswordBloc, VisitorPasswordState>( child: BlocBuilder<VisitorPasswordBloc, VisitorPasswordState>(
builder: (BuildContext context, VisitorPasswordState state) { builder: (BuildContext context, VisitorPasswordState state) {
final visitorBloc = BlocProvider.of<VisitorPasswordBloc>(context); final visitorBloc = BlocProvider.of<VisitorPasswordBloc>(context);
bool isRepeat = state is IsRepeatState ? state.repeat : visitorBloc.repeat; bool isRepeat =
state is IsRepeatState ? state.repeat : visitorBloc.repeat;
return AlertDialog( return AlertDialog(
backgroundColor: Colors.white, backgroundColor: Colors.white,
title: Text( title: Text(
'Create visitor password', 'Create visitor password',
style: Theme.of(context) style: Theme.of(context).textTheme.headlineLarge!.copyWith(
.textTheme fontWeight: FontWeight.w400,
.headlineLarge! fontSize: 24,
.copyWith(fontWeight: FontWeight.w400, fontSize: 24, color: Colors.black), color: Colors.black),
), ),
content: state is LoadingInitialState content: state is LoadingInitialState
? const Center(child: CircularProgressIndicator()) ? const Center(child: CircularProgressIndicator())
@ -121,34 +135,11 @@ class VisitorPasswordDialog extends StatelessWidget {
padding: const EdgeInsets.all(5.0), padding: const EdgeInsets.all(5.0),
child: ListBody( child: ListBody(
children: <Widget>[ children: <Widget>[
Container( NameAndEmailFields(
child: Row( nameController: visitorBloc.userNameController,
children: [ emailController: visitorBloc.emailController,
Expanded( nameValidator: visitorBloc.validate,
flex: 2, emailValidator: visitorBloc.validateEmail,
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 visitors email address.',
),
),
const Spacer(),
],
),
), ),
const SizedBox( const SizedBox(
height: 15, height: 15,
@ -156,104 +147,40 @@ class VisitorPasswordDialog extends StatelessWidget {
Column( Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
Row( AccessTypeRadioGroup(
children: [ selectedType: state is PasswordTypeSelected
Text(
'* ',
style: Theme.of(context)
.textTheme
.bodyMedium!
.copyWith(color: Colors.red),
),
Text('Access Type', style: text),
],
),
Row(
children: <Widget>[
Expanded(
flex: 2,
child: Row(
children: [
SizedBox(
width: size.width * 0.12,
child: RadioListTile<String>(
contentPadding: EdgeInsets.zero,
title: Text(
'Online Password',
style: text,
),
value: 'Online Password',
groupValue: (state is PasswordTypeSelected)
? state.selectedType ? state.selectedType
: visitorBloc.accessTypeSelected, : null,
onChanged: (String? value) { accessTypeSelected:
if (value != null) { visitorBloc.accessTypeSelected,
onTypeSelected: (value) {
context context
.read<VisitorPasswordBloc>() .read<VisitorPasswordBloc>()
.add(SelectPasswordType(value)); .add(SelectPasswordType(value));
}
}, },
visitorBloc: visitorBloc,
), ),
),
SizedBox( if (visitorBloc.accessTypeSelected ==
width: size.width * 0.12, 'Online Password')
child: RadioListTile<String>(
contentPadding: EdgeInsets.zero,
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.12,
// child: RadioListTile<String>(
// contentPadding: EdgeInsets.zero,
// 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 = '';
// }
// },
// ),
// ),
],
)),
const Spacer(
flex: 2,
),
],
),
if (visitorBloc.accessTypeSelected == 'Online Password')
Text( 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', '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( style: Theme.of(context)
.textTheme
.bodySmall!
.copyWith(
fontWeight: FontWeight.w400, fontWeight: FontWeight.w400,
color: ColorsManager.grayColor, color: ColorsManager.grayColor,
fontSize: 9), fontSize: 9),
), ),
if (visitorBloc.accessTypeSelected == 'Offline Password') if (visitorBloc.accessTypeSelected ==
'Offline Password')
Text( Text(
'Unaffected by the online status of the device, you can select online or offline device, and the system randomly generates a digital password', 'Unaffected by the online status of the device, you can select online or offline device, and the system randomly generates a digital password',
style: Theme.of(context).textTheme.bodySmall!.copyWith( style: Theme.of(context)
.textTheme
.bodySmall!
.copyWith(
fontWeight: FontWeight.w400, fontWeight: FontWeight.w400,
color: ColorsManager.grayColor, color: ColorsManager.grayColor,
fontSize: 9), fontSize: 9),
@ -271,9 +198,11 @@ class VisitorPasswordDialog extends StatelessWidget {
) )
], ],
), ),
visitorBloc.accessTypeSelected == 'Dynamic Password' if (visitorBloc.accessTypeSelected ==
? const SizedBox() 'Dynamic Password')
: Column( const SizedBox()
else
Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
Row( Row(
@ -291,123 +220,148 @@ class VisitorPasswordDialog extends StatelessWidget {
), ),
], ],
), ),
Row( UsageFrequencyRadioGroup(
children: <Widget>[ selectedFrequency:
SizedBox( state is UsageFrequencySelected
width: size.width * 0.12,
child: RadioListTile<String>(
contentPadding: EdgeInsets.zero,
title: Text(
'One-Time',
style: text,
),
value: 'One-Time',
groupValue: (state is UsageFrequencySelected)
? state.selectedFrequency ? state.selectedFrequency
: visitorBloc.usageFrequencySelected, : null,
onChanged: (String? value) { usageFrequencySelected:
if (value != null) { visitorBloc.usageFrequencySelected,
onFrequencySelected: (value) {
context context
.read<VisitorPasswordBloc>() .read<VisitorPasswordBloc>()
.add(SelectUsageFrequency(value)); .add(SelectUsageFrequency(value));
}
}, },
), ),
),
SizedBox(
width: size.width * 0.12,
child: RadioListTile<String>(
contentPadding: EdgeInsets.zero,
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));
}
},
),
),
],
),
//One-Time //One-Time
if (visitorBloc.usageFrequencySelected == 'One-Time' && if (visitorBloc.usageFrequencySelected ==
visitorBloc.accessTypeSelected == 'Online Password') 'One-Time' &&
visitorBloc.accessTypeSelected ==
'Online Password')
Text( Text(
'Within the validity period, each device can be unlocked only once.', 'Within the validity period, each device can be unlocked only once.',
style: Theme.of(context).textTheme.bodySmall!.copyWith( style: Theme.of(context)
color: ColorsManager.grayColor, fontSize: 9), .textTheme
.bodySmall!
.copyWith(
color: ColorsManager.grayColor,
fontSize: 9),
), ),
if (visitorBloc.usageFrequencySelected == 'One-Time' && if (visitorBloc.usageFrequencySelected ==
visitorBloc.accessTypeSelected == 'Offline Password') 'One-Time' &&
visitorBloc.accessTypeSelected ==
'Offline Password')
Text( Text(
'Within the validity period, each device can be unlocked only once, and the maximum validity period is 6 hours', 'Within the validity period, each device can be unlocked only once, and the maximum validity period is 6 hours',
style: Theme.of(context).textTheme.bodySmall!.copyWith( style: Theme.of(context)
color: ColorsManager.grayColor, fontSize: 9), .textTheme
.bodySmall!
.copyWith(
color: ColorsManager.grayColor,
fontSize: 9),
), ),
// Periodic // Periodic
if (visitorBloc.usageFrequencySelected == 'Periodic' && if (visitorBloc.usageFrequencySelected ==
visitorBloc.accessTypeSelected == 'Offline Password') 'Periodic' &&
visitorBloc.accessTypeSelected ==
'Offline Password')
Text( Text(
'Within the validity period, there is no limit to the number of times each device can be unlocked, and it should be used at least once within 24 hours after the entry into force.', 'Within the validity period, there is no limit to the number of times each device can be unlocked, and it should be used at least once within 24 hours after the entry into force.',
style: Theme.of(context).textTheme.bodySmall!.copyWith( style: Theme.of(context)
color: ColorsManager.grayColor, fontSize: 9), .textTheme
.bodySmall!
.copyWith(
color: ColorsManager.grayColor,
fontSize: 9),
), ),
if (visitorBloc.usageFrequencySelected == 'Periodic' && if (visitorBloc.usageFrequencySelected ==
visitorBloc.accessTypeSelected == 'Online Password') 'Periodic' &&
visitorBloc.accessTypeSelected ==
'Online Password')
Text( Text(
'Within the validity period, there is no limit to the number of times each device can be unlocked.', 'Within the validity period, there is no limit to the number of times each device can be unlocked.',
style: Theme.of(context).textTheme.bodySmall!.copyWith( style: Theme.of(context)
color: ColorsManager.grayColor, fontSize: 9), .textTheme
.bodySmall!
.copyWith(
color: ColorsManager.grayColor,
fontSize: 9),
), ),
], ],
), ),
const SizedBox( const SizedBox(
height: 20, height: 20,
), ),
if ((visitorBloc.usageFrequencySelected != 'One-Time' || if ((visitorBloc.usageFrequencySelected !=
visitorBloc.accessTypeSelected != 'Offline Password') && 'One-Time' ||
visitorBloc.accessTypeSelected !=
'Offline Password') &&
(visitorBloc.usageFrequencySelected != '')) (visitorBloc.usageFrequencySelected != ''))
DateTimeWebWidget( DateTimeWebWidget(
isRequired: true, isRequired: true,
title: 'Access Period', title: 'Access Period',
size: size, size: size,
endTime: () { endTime: () {
if (visitorBloc.usageFrequencySelected == 'Periodic' && if (visitorBloc.usageFrequencySelected ==
visitorBloc.accessTypeSelected == 'Offline Password') { 'Periodic' &&
visitorBloc.add(SelectTimeEvent(context: context, isEffective: false)); visitorBloc.accessTypeSelected ==
'Offline Password') {
visitorBloc.add(SelectTimeEvent(
context: context,
isEffective: false));
} else { } else {
visitorBloc.add(SelectTimeVisitorPassword(context: context, isStart: false, isRepeat: false)); visitorBloc.add(
SelectTimeVisitorPassword(
context: context,
isStart: false,
isRepeat: false));
} }
}, },
startTime: () { startTime: () {
if (visitorBloc.usageFrequencySelected == 'Periodic' && if (visitorBloc.usageFrequencySelected ==
visitorBloc.accessTypeSelected == 'Offline Password') { 'Periodic' &&
visitorBloc.add( visitorBloc.accessTypeSelected ==
SelectTimeEvent(context: context, isEffective: true)); 'Offline Password') {
visitorBloc.add(SelectTimeEvent(
context: context,
isEffective: true));
} else { } else {
visitorBloc.add(SelectTimeVisitorPassword( visitorBloc.add(
context: context, isStart: true, isRepeat: false)); SelectTimeVisitorPassword(
context: context,
isStart: true,
isRepeat: false));
} }
}, },
firstString: (visitorBloc.usageFrequencySelected == firstString: (visitorBloc
'Periodic' && visitorBloc.accessTypeSelected == 'Offline Password') .usageFrequencySelected ==
'Periodic' &&
visitorBloc.accessTypeSelected ==
'Offline Password')
? visitorBloc.effectiveTime ? visitorBloc.effectiveTime
: visitorBloc.startTimeAccess.toString(), : visitorBloc.startTimeAccess
secondString: (visitorBloc.usageFrequencySelected == .toString(),
'Periodic' && visitorBloc.accessTypeSelected == 'Offline Password') secondString: (visitorBloc
.usageFrequencySelected ==
'Periodic' &&
visitorBloc.accessTypeSelected ==
'Offline Password')
? visitorBloc.expirationTime ? visitorBloc.expirationTime
: visitorBloc.endTimeAccess.toString(), : visitorBloc.endTimeAccess.toString(),
icon: Assets.calendarIcon), icon: Assets.calendarIcon),
const SizedBox(height: 10,), const SizedBox(
Text(visitorBloc.accessPeriodValidate, height: 10,
style: Theme.of(context).textTheme.bodyMedium!.copyWith(color: ColorsManager.red),), ),
Text(
visitorBloc.accessPeriodValidate,
style: Theme.of(context)
.textTheme
.bodyMedium!
.copyWith(color: ColorsManager.red),
),
const SizedBox( const SizedBox(
height: 20, height: 20,
), ),
@ -431,7 +385,10 @@ class VisitorPasswordDialog extends StatelessWidget {
), ),
Text( Text(
'Within the validity period, each device can be unlocked only once.', 'Within the validity period, each device can be unlocked only once.',
style: Theme.of(context).textTheme.bodySmall!.copyWith( style: Theme.of(context)
.textTheme
.bodySmall!
.copyWith(
fontWeight: FontWeight.w400, fontWeight: FontWeight.w400,
color: ColorsManager.grayColor, color: ColorsManager.grayColor,
fontSize: 9), fontSize: 9),
@ -439,8 +396,10 @@ class VisitorPasswordDialog extends StatelessWidget {
const SizedBox( const SizedBox(
height: 20, height: 20,
), ),
if (visitorBloc.usageFrequencySelected == 'Periodic' && if (visitorBloc.usageFrequencySelected ==
visitorBloc.accessTypeSelected == 'Online Password') 'Periodic' &&
visitorBloc.accessTypeSelected ==
'Online Password')
SizedBox( SizedBox(
width: 100, width: 100,
child: Column( child: Column(
@ -451,7 +410,8 @@ class VisitorPasswordDialog extends StatelessWidget {
child: CupertinoSwitch( child: CupertinoSwitch(
value: visitorBloc.repeat, value: visitorBloc.repeat,
onChanged: (value) { onChanged: (value) {
visitorBloc.add(ToggleRepeatEvent()); visitorBloc
.add(ToggleRepeatEvent());
}, },
applyTheme: true, applyTheme: true,
), ),
@ -459,12 +419,16 @@ class VisitorPasswordDialog extends StatelessWidget {
], ],
), ),
), ),
if (visitorBloc.usageFrequencySelected == 'Periodic' && if (visitorBloc.usageFrequencySelected ==
visitorBloc.accessTypeSelected == 'Online Password') 'Periodic' &&
isRepeat ? const RepeatWidget() : const SizedBox(), visitorBloc.accessTypeSelected ==
'Online Password')
isRepeat
? const RepeatWidget()
: const SizedBox(),
Container( Container(
decoration: containerDecoration, decoration: containerDecoration,
width: size.width / 9, width: size.width / 6,
child: DefaultButton( child: DefaultButton(
onPressed: () { onPressed: () {
showDialog( showDialog(
@ -472,21 +436,27 @@ class VisitorPasswordDialog extends StatelessWidget {
barrierDismissible: false, barrierDismissible: false,
builder: (BuildContext context) { builder: (BuildContext context) {
return AddDeviceDialog( return AddDeviceDialog(
selectedDeviceIds: visitorBloc.selectedDevices, selectedDeviceIds:
visitorBloc.selectedDevices,
); );
}, },
).then((listDevice) { ).then((listDevice) {
if (listDevice != null) { if (listDevice != null) {
visitorBloc.selectedDevices = listDevice; visitorBloc.selectedDevices =
listDevice;
} }
}); });
}, },
borderRadius: 8, borderRadius: 8,
child: Text( child: Text(
'+ Add Device', '+ Add Device',
style: Theme.of(context).textTheme.bodySmall!.copyWith( style: Theme.of(context)
.textTheme
.bodySmall!
.copyWith(
fontWeight: FontWeight.w400, fontWeight: FontWeight.w400,
color: ColorsManager.whiteColors, color:
ColorsManager.whiteColors,
fontSize: 12), fontSize: 12),
), ),
), ),
@ -525,30 +495,37 @@ class VisitorPasswordDialog extends StatelessWidget {
onPressed: () { onPressed: () {
if (visitorBloc.forgetFormKey.currentState!.validate()) { if (visitorBloc.forgetFormKey.currentState!.validate()) {
if (visitorBloc.selectedDevices.isNotEmpty) { if (visitorBloc.selectedDevices.isNotEmpty) {
if (visitorBloc.usageFrequencySelected == 'One-Time' && if (visitorBloc.usageFrequencySelected ==
visitorBloc.accessTypeSelected == 'Offline Password') { 'One-Time' &&
visitorBloc.accessTypeSelected ==
'Offline Password') {
setPasswordFunction(context, size, visitorBloc); setPasswordFunction(context, size, visitorBloc);
} else if (visitorBloc.usageFrequencySelected == 'Periodic' && } else if (visitorBloc.usageFrequencySelected ==
visitorBloc.accessTypeSelected == 'Offline Password') { 'Periodic' &&
visitorBloc.accessTypeSelected ==
'Offline Password') {
if (visitorBloc.expirationTime != 'End Time' && if (visitorBloc.expirationTime != 'End Time' &&
visitorBloc.effectiveTime != 'Start Time' ) { visitorBloc.effectiveTime != 'Start Time') {
setPasswordFunction(context, size, visitorBloc); setPasswordFunction(context, size, visitorBloc);
}else{ } else {
visitorBloc.stateDialog( visitorBloc.stateDialog(
context: context, context: context,
message: 'Please select Access Period to continue', message:
'Please select Access Period to continue',
title: 'Access Period'); title: 'Access Period');
} }
} else if( } else if (visitorBloc.endTimeAccess.toString() !=
visitorBloc.endTimeAccess.toString()!='End Time' 'End Time' &&
&&visitorBloc.startTimeAccess.toString()!='Start Time') { visitorBloc.startTimeAccess.toString() !=
'Start Time') {
if (visitorBloc.effectiveTimeTimeStamp != null && if (visitorBloc.effectiveTimeTimeStamp != null &&
visitorBloc.expirationTimeTimeStamp != null) { visitorBloc.expirationTimeTimeStamp != null) {
if (isRepeat == true) { if (isRepeat == true) {
if (visitorBloc.expirationTime != 'End Time' && if (visitorBloc.expirationTime != 'End Time' &&
visitorBloc.effectiveTime != 'Start Time' && visitorBloc.effectiveTime != 'Start Time' &&
visitorBloc.selectedDays.isNotEmpty) { visitorBloc.selectedDays.isNotEmpty) {
setPasswordFunction(context, size, visitorBloc); setPasswordFunction(
context, size, visitorBloc);
} else { } else {
visitorBloc.stateDialog( visitorBloc.stateDialog(
context: context, context: context,
@ -562,13 +539,15 @@ class VisitorPasswordDialog extends StatelessWidget {
} else { } else {
visitorBloc.stateDialog( visitorBloc.stateDialog(
context: context, context: context,
message: 'Please select Access Period to continue', message:
'Please select Access Period to continue',
title: 'Access Period'); title: 'Access Period');
} }
}else{ } else {
visitorBloc.stateDialog( visitorBloc.stateDialog(
context: context, context: context,
message: 'Please select Access Period to continue', message:
'Please select Access Period to continue',
title: 'Access Period'); title: 'Access Period');
} }
} else { } else {
@ -615,7 +594,8 @@ class VisitorPasswordDialog extends StatelessWidget {
content: SizedBox( content: SizedBox(
height: size.height * 0.25, height: size.height * 0.25,
child: Center( child: Center(
child: CircularProgressIndicator(), // Display a loading spinner child:
CircularProgressIndicator(), // Display a loading spinner
), ),
), ),
); );
@ -639,7 +619,10 @@ class VisitorPasswordDialog extends StatelessWidget {
), ),
Text( Text(
'Set Password', 'Set Password',
style: Theme.of(context).textTheme.headlineLarge!.copyWith( style: Theme.of(context)
.textTheme
.headlineLarge!
.copyWith(
fontSize: 30, fontSize: 30,
fontWeight: FontWeight.w400, fontWeight: FontWeight.w400,
color: Colors.black, color: Colors.black,
@ -689,37 +672,45 @@ class VisitorPasswordDialog extends StatelessWidget {
onPressed: () { onPressed: () {
Navigator.pop(context); Navigator.pop(context);
if (visitorBloc.usageFrequencySelected == 'One-Time' && if (visitorBloc.usageFrequencySelected == 'One-Time' &&
visitorBloc.accessTypeSelected == 'Online Password') { visitorBloc.accessTypeSelected ==
'Online Password') {
visitorBloc.add(OnlineOneTimePasswordEvent( visitorBloc.add(OnlineOneTimePasswordEvent(
context: context, context: context,
passwordName: visitorBloc.userNameController.text, passwordName: visitorBloc.userNameController.text,
email: visitorBloc.emailController.text, email: visitorBloc.emailController.text,
)); ));
} } else if (visitorBloc.usageFrequencySelected ==
else if (visitorBloc.usageFrequencySelected == 'Periodic' && 'Periodic' &&
visitorBloc.accessTypeSelected == 'Online Password') { visitorBloc.accessTypeSelected ==
'Online Password') {
visitorBloc.add(OnlineMultipleTimePasswordEvent( visitorBloc.add(OnlineMultipleTimePasswordEvent(
passwordName: visitorBloc.userNameController.text, passwordName: visitorBloc.userNameController.text,
email: visitorBloc.emailController.text, email: visitorBloc.emailController.text,
effectiveTime: visitorBloc.effectiveTimeTimeStamp.toString(), effectiveTime:
invalidTime: visitorBloc.expirationTimeTimeStamp.toString(), visitorBloc.effectiveTimeTimeStamp.toString(),
invalidTime:
visitorBloc.expirationTimeTimeStamp.toString(),
)); ));
} } else if (visitorBloc.usageFrequencySelected ==
else if (visitorBloc.usageFrequencySelected == 'One-Time' && 'One-Time' &&
visitorBloc.accessTypeSelected == 'Offline Password') { visitorBloc.accessTypeSelected ==
'Offline Password') {
visitorBloc.add(OfflineOneTimePasswordEvent( visitorBloc.add(OfflineOneTimePasswordEvent(
context: context, context: context,
passwordName: visitorBloc.userNameController.text, passwordName: visitorBloc.userNameController.text,
email: visitorBloc.emailController.text, email: visitorBloc.emailController.text,
)); ));
} } else if (visitorBloc.usageFrequencySelected ==
else if (visitorBloc.usageFrequencySelected == 'Periodic' && 'Periodic' &&
visitorBloc.accessTypeSelected == 'Offline Password') { visitorBloc.accessTypeSelected ==
'Offline Password') {
visitorBloc.add(OfflineMultipleTimePasswordEvent( visitorBloc.add(OfflineMultipleTimePasswordEvent(
passwordName: visitorBloc.userNameController.text, passwordName: visitorBloc.userNameController.text,
email: visitorBloc.emailController.text, email: visitorBloc.emailController.text,
effectiveTime: visitorBloc.effectiveTimeTimeStamp.toString(), effectiveTime:
invalidTime: visitorBloc.expirationTimeTimeStamp.toString(), visitorBloc.effectiveTimeTimeStamp.toString(),
invalidTime:
visitorBloc.expirationTimeTimeStamp.toString(),
)); ));
} }
}, },