create visitor password

This commit is contained in:
mohammad
2024-08-15 17:01:15 +03:00
parent 20ed718c64
commit 213fa48741
7 changed files with 241 additions and 86 deletions

View File

@ -56,8 +56,8 @@ class MyApp extends StatelessWidget {
colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple), // Set up color scheme colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple), // Set up color scheme
useMaterial3: true, // Enable Material 3 useMaterial3: true, // Enable Material 3
), ),
// home: VisitorPasswordDialog() home: VisitorPasswordDialog()
home:isLoggedIn == 'Success' ? const HomePage() : const LoginPage(), // home:isLoggedIn == 'Success' ? const HomePage() : const LoginPage(),
)); ));
} }
} }

View File

@ -222,7 +222,7 @@ class ForgetPasswordWebPage extends StatelessWidget {
width: 100, width: 100,
child: Center( child: Center(
child: InkWell( child: InkWell(
onTap: () { onTap:state is TimerState && !state.isButtonEnabled && state.remainingTime!=1?null: () {
forgetBloc.add(StartTimerEvent()); forgetBloc.add(StartTimerEvent());
}, },
child: Text( child: Text(
@ -326,13 +326,6 @@ class ForgetPasswordWebPage extends StatelessWidget {
), ),
), ),
const SizedBox(height: 15.0), const SizedBox(height: 15.0),
Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: [ SizedBox(child: Text(forgetBloc.forgetValidate,
style: const TextStyle(fontWeight: FontWeight.w700,color: ColorsManager.red ),),)
],
)
], ],
), ),
), ),

View File

@ -11,13 +11,17 @@ class VisitorPasswordBloc extends Bloc<VisitorPasswordEvent, VisitorPasswordStat
on<SelectUsageFrequency>(selectUsageFrequency); on<SelectUsageFrequency>(selectUsageFrequency);
on<SelectPasswordType>(selectAccessType); on<SelectPasswordType>(selectAccessType);
on<SelectTimeVisitorPassword>(selectTimeVisitorPassword); on<SelectTimeVisitorPassword>(selectTimeVisitorPassword);
on<ToggleRepeatEvent>(toggleRepeat);
on<ToggleDaySelectionEvent>(toggleDaySelection);
} }
final TextEditingController userNameController = TextEditingController(); final TextEditingController userNameController = TextEditingController();
final TextEditingController emailController = TextEditingController(); final TextEditingController emailController = TextEditingController();
String accessTypeSelected=''; String accessTypeSelected='Offline Password';
String usageFrequencySelected=''; String usageFrequencySelected='One-Time';
bool repeat = false;
int? effectiveTimeTimeStamp; int? effectiveTimeTimeStamp;
int? expirationTimeTimeStamp; int? expirationTimeTimeStamp;
@ -27,13 +31,11 @@ class VisitorPasswordBloc extends Bloc<VisitorPasswordEvent, VisitorPasswordStat
selectAccessType(SelectPasswordType event, Emitter<VisitorPasswordState> emit) { selectAccessType(SelectPasswordType event, Emitter<VisitorPasswordState> emit) {
accessTypeSelected=event.type; accessTypeSelected=event.type;
print(accessTypeSelected);
emit(PasswordTypeSelected(event.type)); emit(PasswordTypeSelected(event.type));
} }
selectUsageFrequency(SelectUsageFrequency event, Emitter<VisitorPasswordState> emit) { selectUsageFrequency(SelectUsageFrequency event, Emitter<VisitorPasswordState> emit) {
usageFrequencySelected=event.usageType; usageFrequencySelected=event.usageType;
print(usageFrequencySelected);
emit(UsageFrequencySelected(event.usageType)); emit(UsageFrequencySelected(event.usageType));
} }
@ -104,4 +106,36 @@ class VisitorPasswordBloc extends Bloc<VisitorPasswordEvent, VisitorPasswordStat
} }
bool toggleRepeat(ToggleRepeatEvent event, Emitter<VisitorPasswordState> emit) {
emit(LoadingInitialState());
repeat = !repeat;
emit(IsRepeatState(repeat: repeat));
return repeat;
}
List<Map<String, String>> days = [
{"day": "Sun", "key": "Sun"},
{"day": "Mon", "key": "Mon"},
{"day": "Tue", "key": "Tue"},
{"day": "Wed", "key": "Wed"},
{"day": "Thu", "key": "Thu"},
{"day": "Fri", "key": "Fri"},
{"day": "Sat", "key": "Sat"},
];
List<String> selectedDays = [];
Future<void> toggleDaySelection(ToggleDaySelectionEvent event, Emitter<VisitorPasswordState> emit,)async {
emit(LoadingInitialState());
if (selectedDays.contains(event.key)) {
selectedDays.remove(event.key);
} else {
selectedDays.add(event.key);
}
emit(ChangeTimeState());
}
} }

View File

@ -34,3 +34,16 @@ class SelectTimeVisitorPassword extends VisitorPasswordEvent {
@override @override
List<Object> get props => [context,isStart]; List<Object> get props => [context,isStart];
} }
class ToggleDaySelectionEvent extends VisitorPasswordEvent {
final String key;
const ToggleDaySelectionEvent({required this.key});
@override
List<Object> get props => [key];
}
class ToggleRepeatEvent extends VisitorPasswordEvent {}

View File

@ -29,4 +29,16 @@ class UsageFrequencySelected extends VisitorPasswordState {
@override @override
List<Object> get props => [selectedFrequency]; List<Object> get props => [selectedFrequency];
} }
class IsRepeatState extends VisitorPasswordState {
final bool repeat;
const IsRepeatState({required this.repeat});
@override
List<Object> get props => [repeat];
}
class LoadingInitialState extends VisitorPasswordState {}
class ChangeTimeState extends VisitorPasswordState {}

View File

@ -0,0 +1,81 @@
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:syncrow_web/pages/common/date_time_widget.dart';
import 'package:syncrow_web/pages/visitor_password/bloc/visitor_password_bloc.dart';
import 'package:syncrow_web/pages/visitor_password/bloc/visitor_password_event.dart';
import 'package:syncrow_web/pages/visitor_password/bloc/visitor_password_state.dart';
import 'package:syncrow_web/utils/color_manager.dart';
class RepeatWidget extends StatelessWidget {
const RepeatWidget({
super.key,
});
@override
Widget build(BuildContext context) {
Size size = MediaQuery.of(context).size;
return BlocBuilder<VisitorPasswordBloc, VisitorPasswordState>(
builder: (context, state) {
final smartDoorBloc = BlocProvider.of<VisitorPasswordBloc>(context);
return Column(
children: <Widget>[
Padding(
padding: const EdgeInsets.all(8.0),
child: DateTimeWebWidget(
isRequired: true,
title: 'Access Period',
size: size,
endTime: () {
smartDoorBloc.add(SelectTimeVisitorPassword(context: context, isStart: false));
},
startTime: () {
smartDoorBloc.add(SelectTimeVisitorPassword(context: context, isStart: true));
},
firstString: smartDoorBloc.startTime,
secondString: smartDoorBloc.endTime,
),
),
const Divider(
color: ColorsManager.graysColor,
),
const Divider(
color: ColorsManager.graysColor,
),
const SizedBox(height: 20),
Container(
width: size.width * 0.8,
height: size.height * 0.06, // Adjust height as needed
child: ListView(
scrollDirection: Axis.horizontal,
children: smartDoorBloc.days.map((day) {
return Container(
width: size.width* 0.09,
child: CheckboxListTile(
title: Text(
day['day']!,
style: TextStyle(
fontSize: 18,
color: smartDoorBloc.selectedDays.contains(day['key'])
? Colors.black
: ColorsManager.grayColor,
),
),
value: smartDoorBloc.selectedDays.contains(day['key']),
onChanged: (bool? value) {
if (value != null) {
smartDoorBloc.add(ToggleDaySelectionEvent(key: day['key']!));
}
},
),
);
}).toList(),
),
),
const SizedBox(height: 20),
],
);
});
}
}

View File

@ -1,3 +1,4 @@
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:syncrow_web/pages/common/custom_web_textfield.dart'; import 'package:syncrow_web/pages/common/custom_web_textfield.dart';
@ -6,9 +7,10 @@ import 'package:syncrow_web/pages/common/default_button.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/repeat_widget.dart';
import 'package:syncrow_web/utils/snack_bar.dart';
import 'package:syncrow_web/utils/style.dart'; import 'package:syncrow_web/utils/style.dart';
class VisitorPasswordDialog extends StatelessWidget { class VisitorPasswordDialog extends StatelessWidget {
const VisitorPasswordDialog({super.key}); const VisitorPasswordDialog({super.key});
@ -18,19 +20,20 @@ class VisitorPasswordDialog extends StatelessWidget {
return BlocProvider( return BlocProvider(
create: (context) => VisitorPasswordBloc(), create: (context) => VisitorPasswordBloc(),
child: BlocBuilder<VisitorPasswordBloc, VisitorPasswordState>( child: BlocBuilder<VisitorPasswordBloc, VisitorPasswordState>(
builder: (context, 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;
return AlertDialog( return AlertDialog(
title: const Text('Create visitor password'), title: const Text('Create visitor password'),
content: SingleChildScrollView( content: SingleChildScrollView(
child: ListBody( child: ListBody(
children: <Widget>[ children: <Widget>[
Row( Row(
children: [ children: [
Expanded( Expanded(
flex: 2, flex: 2,
child: CustomWebTextField( child: CustomWebTextField(
controller:visitorBloc.userNameController , controller: visitorBloc.userNameController,
isRequired: true, isRequired: true,
textFieldName: 'User Name', textFieldName: 'User Name',
description: '', description: '',
@ -40,7 +43,7 @@ class VisitorPasswordDialog extends StatelessWidget {
Expanded( Expanded(
flex: 2, flex: 2,
child: CustomWebTextField( child: CustomWebTextField(
controller:visitorBloc.emailController , controller: visitorBloc.emailController,
isRequired: true, isRequired: true,
textFieldName: 'Email Address', textFieldName: 'Email Address',
description: 'The password will be sent to the visitors email address.', description: 'The password will be sent to the visitors email address.',
@ -48,11 +51,9 @@ class VisitorPasswordDialog extends StatelessWidget {
), ),
], ],
), ),
SizedBox(height: size.height * 0.02), // Add spacing SizedBox(height: size.height * 0.02), // Add spacing
Column( Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.start,
children: [ children: [
Row( Row(
children: [ children: [
@ -69,13 +70,13 @@ class VisitorPasswordDialog extends StatelessWidget {
Row( Row(
children: <Widget>[ children: <Widget>[
SizedBox( SizedBox(
width: size.width*0.15, width: size.width * 0.15,
child: RadioListTile<String>( child: RadioListTile<String>(
title: const Text('Offline Password'), title: const Text('Offline Password'),
value: 'Offline Password', value: 'Offline Password',
groupValue: (state is PasswordTypeSelected) groupValue: (state is PasswordTypeSelected)
? state.selectedType ? state.selectedType
: 'Offline Password', : visitorBloc.accessTypeSelected,
onChanged: (String? value) { onChanged: (String? value) {
if (value != null) { if (value != null) {
context.read<VisitorPasswordBloc>().add(SelectPasswordType(value)); context.read<VisitorPasswordBloc>().add(SelectPasswordType(value));
@ -84,46 +85,43 @@ class VisitorPasswordDialog extends StatelessWidget {
), ),
), ),
SizedBox( SizedBox(
width: size.width*0.15, width: size.width * 0.15,
child: RadioListTile<String>( child: RadioListTile<String>(
title: const Text('Online Password'), title: const Text('Online Password'),
value: 'Online Password', value: 'Online Password',
groupValue: (state is PasswordTypeSelected) groupValue: (state is PasswordTypeSelected)
? state.selectedType ? state.selectedType
: 'Offline Password', : visitorBloc.accessTypeSelected,
onChanged: (String? value) { onChanged: (String? value) {
if (value != null) { if (value != null) {
context context.read<VisitorPasswordBloc>().add(SelectPasswordType(value));
.read<VisitorPasswordBloc>()
.add(SelectPasswordType(value));
} }
}, },
), ),
), ),
SizedBox( SizedBox(
width: size.width*0.15, width: size.width * 0.15,
child: RadioListTile<String>( child: RadioListTile<String>(
title: const Text('Dynamic Password'), title: const Text('Dynamic Password'),
value: 'Dynamic Password', value: 'Dynamic Password',
groupValue: (state is PasswordTypeSelected) groupValue: (state is PasswordTypeSelected)
? state.selectedType ? state.selectedType
: 'Offline Password', : visitorBloc.accessTypeSelected,
onChanged: (String? value) { onChanged: (String? value) {
if (value != null) { if (value != null) {
context context.read<VisitorPasswordBloc>().add(SelectPasswordType(value));
.read<VisitorPasswordBloc>()
.add(SelectPasswordType(value));
} }
}, },
), ),
), ),
], ],
) ),
], ],
), ),
visitorBloc.accessTypeSelected=='Dynamic Password' ?
SizedBox():
Column( Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.start,
children: [ children: [
Row( Row(
children: [ children: [
@ -146,11 +144,10 @@ class VisitorPasswordDialog extends StatelessWidget {
value: 'One-Time', value: 'One-Time',
groupValue: (state is UsageFrequencySelected) groupValue: (state is UsageFrequencySelected)
? state.selectedFrequency ? state.selectedFrequency
: 'One-Time', : visitorBloc.usageFrequencySelected,
onChanged: (String? value) { onChanged: (String? value) {
if (value != null) { if (value != null) {
context.read<VisitorPasswordBloc>() context.read<VisitorPasswordBloc>().add(SelectUsageFrequency(value));
.add(SelectUsageFrequency(value));
} }
}, },
), ),
@ -162,59 +159,80 @@ class VisitorPasswordDialog extends StatelessWidget {
value: 'Periodic', value: 'Periodic',
groupValue: (state is UsageFrequencySelected) groupValue: (state is UsageFrequencySelected)
? state.selectedFrequency ? state.selectedFrequency
: 'Periodic1', : visitorBloc.usageFrequencySelected,
onChanged: (String? value) { onChanged: (String? value) {
if (value != null) { if (value != null) {
context.read<VisitorPasswordBloc>() context.read<VisitorPasswordBloc>().add(SelectUsageFrequency(value));
.add(SelectUsageFrequency(value));
} }
}, },
), ),
), ),
], ],
) ),
], ],
), ),
visitorBloc.accessTypeSelected=='Dynamic Password' ?
SizedBox():
DateTimeWebWidget( DateTimeWebWidget(
isRequired: true, isRequired: true,
title: 'Access Period', title: 'Access Period',
size: size, size: size,
endTime: () { endTime: () {
visitorBloc.add(SelectTimeVisitorPassword(context: context, isStart: false)); visitorBloc.add(SelectTimeVisitorPassword(context: context, isStart: false));
}, },
startTime: () { startTime: () {
visitorBloc.add(SelectTimeVisitorPassword(context: context, isStart: true)); visitorBloc.add(SelectTimeVisitorPassword(context: context, isStart: true));
}, },
firstString:BlocProvider.of<VisitorPasswordBloc>(context).startTime , firstString: visitorBloc.startTime,
secondString:BlocProvider.of<VisitorPasswordBloc>(context).endTime , secondString: visitorBloc.endTime,
) , ),
Column( Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
Row( Row(
children: [ children: [
Text( Text(
'* ', '* ',
style: Theme.of(context) style: Theme.of(context)
.textTheme .textTheme
.bodyMedium! .bodyMedium!
.copyWith(color: Colors.red), .copyWith(color: Colors.red),
), ),
const Text('Access Devices'), const Text('Access Devices'),
], ],
), ),
const Text('Within the validity period, each device can be unlocked only once.'), const Text('Within the validity period, each device can be unlocked only once.'),
visitorBloc.usageFrequencySelected=='Periodic'&&visitorBloc.accessTypeSelected=='Offline Password'?
SizedBox(
width: 100,
child: ListTile(
contentPadding: EdgeInsets.zero,
leading: const Text('Repeat'),
trailing: Transform.scale(
scale: .8,
child: CupertinoSwitch(
value: visitorBloc.repeat,
onChanged: (value) {
visitorBloc.add(ToggleRepeatEvent());
},
applyTheme: true,
),
),
),
):const SizedBox(),
isRepeat ? const RepeatWidget() : const SizedBox(),
Container( Container(
decoration: containerDecoration, decoration: containerDecoration,
width: size.width*0.2, width: size.width * 0.2,
child: const DefaultButton( child: const DefaultButton(
borderRadius: 8, borderRadius: 8,
child:Text('+ Add Device'),)), child: Text('+ Add Device'),
),
),
], ],
) ),
], ],
), ),
), ),
@ -222,22 +240,27 @@ class VisitorPasswordDialog extends StatelessWidget {
actions: <Widget>[ actions: <Widget>[
Container( Container(
decoration: containerDecoration, decoration: containerDecoration,
width: size.width*0.2, width: size.width * 0.2,
child: DefaultButton( child: DefaultButton(
borderRadius: 8, borderRadius: 8,
onPressed:() {}, onPressed: () {
backgroundColor: Colors.white, Navigator.of(context).pop(); // Close the dialog
child:Text('Cancel',style: Theme.of(context) },
.textTheme backgroundColor: Colors.white,
.bodyMedium!,),)), child: Text(
'Cancel',
style: Theme.of(context).textTheme.bodyMedium!,
),
),
),
Container( Container(
decoration: containerDecoration, decoration: containerDecoration,
width: size.width*0.2, width: size.width * 0.2,
child: const DefaultButton( child: const DefaultButton(
borderRadius: 8, borderRadius: 8,
child:Text('Ok'),)), child: Text('Ok'),
),
),
], ],
); );
}, },
@ -245,4 +268,3 @@ class VisitorPasswordDialog extends StatelessWidget {
); );
} }
} }