diff --git a/lib/main.dart b/lib/main.dart index 92b8684c..e5d2c22b 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -56,8 +56,8 @@ class MyApp extends StatelessWidget { colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple), // Set up color scheme useMaterial3: true, // Enable Material 3 ), - // home: VisitorPasswordDialog() - home:isLoggedIn == 'Success' ? const HomePage() : const LoginPage(), + home: VisitorPasswordDialog() + // home:isLoggedIn == 'Success' ? const HomePage() : const LoginPage(), )); } } diff --git a/lib/pages/auth/view/forget_password_web_page.dart b/lib/pages/auth/view/forget_password_web_page.dart index 8485f976..5b97684c 100644 --- a/lib/pages/auth/view/forget_password_web_page.dart +++ b/lib/pages/auth/view/forget_password_web_page.dart @@ -222,7 +222,7 @@ class ForgetPasswordWebPage extends StatelessWidget { width: 100, child: Center( child: InkWell( - onTap: () { + onTap:state is TimerState && !state.isButtonEnabled && state.remainingTime!=1?null: () { forgetBloc.add(StartTimerEvent()); }, child: Text( @@ -326,13 +326,6 @@ class ForgetPasswordWebPage extends StatelessWidget { ), ), 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 ),),) - ], - ) ], ), ), diff --git a/lib/pages/visitor_password/bloc/visitor_password_bloc.dart b/lib/pages/visitor_password/bloc/visitor_password_bloc.dart index cb4c5a01..668d082e 100644 --- a/lib/pages/visitor_password/bloc/visitor_password_bloc.dart +++ b/lib/pages/visitor_password/bloc/visitor_password_bloc.dart @@ -11,13 +11,17 @@ class VisitorPasswordBloc extends Bloc(selectUsageFrequency); on(selectAccessType); on(selectTimeVisitorPassword); + on(toggleRepeat); + on(toggleDaySelection); + } final TextEditingController userNameController = TextEditingController(); final TextEditingController emailController = TextEditingController(); - String accessTypeSelected=''; - String usageFrequencySelected=''; + String accessTypeSelected='Offline Password'; + String usageFrequencySelected='One-Time'; + bool repeat = false; int? effectiveTimeTimeStamp; int? expirationTimeTimeStamp; @@ -27,13 +31,11 @@ class VisitorPasswordBloc extends Bloc emit) { accessTypeSelected=event.type; - print(accessTypeSelected); emit(PasswordTypeSelected(event.type)); } selectUsageFrequency(SelectUsageFrequency event, Emitter emit) { usageFrequencySelected=event.usageType; - print(usageFrequencySelected); emit(UsageFrequencySelected(event.usageType)); } @@ -104,4 +106,36 @@ class VisitorPasswordBloc extends Bloc emit) { + emit(LoadingInitialState()); + repeat = !repeat; + emit(IsRepeatState(repeat: repeat)); + return repeat; + } + + + + List> 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 selectedDays = []; + + Future toggleDaySelection(ToggleDaySelectionEvent event, Emitter emit,)async { + emit(LoadingInitialState()); + if (selectedDays.contains(event.key)) { + selectedDays.remove(event.key); + } else { + selectedDays.add(event.key); + } + emit(ChangeTimeState()); + } + + } diff --git a/lib/pages/visitor_password/bloc/visitor_password_event.dart b/lib/pages/visitor_password/bloc/visitor_password_event.dart index a01a702c..b0a51ca0 100644 --- a/lib/pages/visitor_password/bloc/visitor_password_event.dart +++ b/lib/pages/visitor_password/bloc/visitor_password_event.dart @@ -34,3 +34,16 @@ class SelectTimeVisitorPassword extends VisitorPasswordEvent { @override List get props => [context,isStart]; } + + + +class ToggleDaySelectionEvent extends VisitorPasswordEvent { + final String key; + + const ToggleDaySelectionEvent({required this.key}); + @override + List get props => [key]; +} + + +class ToggleRepeatEvent extends VisitorPasswordEvent {} diff --git a/lib/pages/visitor_password/bloc/visitor_password_state.dart b/lib/pages/visitor_password/bloc/visitor_password_state.dart index b12232f4..8a5525d3 100644 --- a/lib/pages/visitor_password/bloc/visitor_password_state.dart +++ b/lib/pages/visitor_password/bloc/visitor_password_state.dart @@ -29,4 +29,16 @@ class UsageFrequencySelected extends VisitorPasswordState { @override List get props => [selectedFrequency]; -} \ No newline at end of file +} + +class IsRepeatState extends VisitorPasswordState { + final bool repeat; + const IsRepeatState({required this.repeat}); + + @override + List get props => [repeat]; + +} + +class LoadingInitialState extends VisitorPasswordState {} +class ChangeTimeState extends VisitorPasswordState {} diff --git a/lib/pages/visitor_password/view/repeat_widget.dart b/lib/pages/visitor_password/view/repeat_widget.dart new file mode 100644 index 00000000..24199b65 --- /dev/null +++ b/lib/pages/visitor_password/view/repeat_widget.dart @@ -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( + builder: (context, state) { + final smartDoorBloc = BlocProvider.of(context); + return Column( + children: [ + 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), + + ], + ); + }); + } +} diff --git a/lib/pages/visitor_password/view/visitor_password_dialog.dart b/lib/pages/visitor_password/view/visitor_password_dialog.dart index 160ab9b7..140ded0b 100644 --- a/lib/pages/visitor_password/view/visitor_password_dialog.dart +++ b/lib/pages/visitor_password/view/visitor_password_dialog.dart @@ -1,3 +1,4 @@ +import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.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_event.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'; - class VisitorPasswordDialog extends StatelessWidget { const VisitorPasswordDialog({super.key}); @@ -18,19 +20,20 @@ class VisitorPasswordDialog extends StatelessWidget { return BlocProvider( create: (context) => VisitorPasswordBloc(), child: BlocBuilder( - builder: (context, state) { + builder: (BuildContext context, VisitorPasswordState state) { final visitorBloc = BlocProvider.of(context); + bool isRepeat = state is IsRepeatState ? state.repeat : visitorBloc.repeat; return AlertDialog( title: const Text('Create visitor password'), content: SingleChildScrollView( child: ListBody( children: [ - Row( + Row( children: [ Expanded( flex: 2, child: CustomWebTextField( - controller:visitorBloc.userNameController , + controller: visitorBloc.userNameController, isRequired: true, textFieldName: 'User Name', description: '', @@ -40,7 +43,7 @@ class VisitorPasswordDialog extends StatelessWidget { Expanded( flex: 2, child: CustomWebTextField( - controller:visitorBloc.emailController , + controller: visitorBloc.emailController, isRequired: true, textFieldName: 'Email Address', description: 'The password will be sent to the visitor’s email address.', @@ -48,11 +51,9 @@ class VisitorPasswordDialog extends StatelessWidget { ), ], ), - SizedBox(height: size.height * 0.02), // Add spacing Column( crossAxisAlignment: CrossAxisAlignment.start, - mainAxisAlignment: MainAxisAlignment.start, children: [ Row( children: [ @@ -69,13 +70,13 @@ class VisitorPasswordDialog extends StatelessWidget { Row( children: [ SizedBox( - width: size.width*0.15, + width: size.width * 0.15, child: RadioListTile( title: const Text('Offline Password'), value: 'Offline Password', groupValue: (state is PasswordTypeSelected) ? state.selectedType - : 'Offline Password', + : visitorBloc.accessTypeSelected, onChanged: (String? value) { if (value != null) { context.read().add(SelectPasswordType(value)); @@ -84,46 +85,43 @@ class VisitorPasswordDialog extends StatelessWidget { ), ), SizedBox( - width: size.width*0.15, + width: size.width * 0.15, child: RadioListTile( title: const Text('Online Password'), value: 'Online Password', groupValue: (state is PasswordTypeSelected) ? state.selectedType - : 'Offline Password', + : visitorBloc.accessTypeSelected, onChanged: (String? value) { if (value != null) { - context - .read() - .add(SelectPasswordType(value)); + context.read().add(SelectPasswordType(value)); } }, ), ), SizedBox( - width: size.width*0.15, + width: size.width * 0.15, child: RadioListTile( title: const Text('Dynamic Password'), value: 'Dynamic Password', groupValue: (state is PasswordTypeSelected) ? state.selectedType - : 'Offline Password', + : visitorBloc.accessTypeSelected, onChanged: (String? value) { if (value != null) { - context - .read() - .add(SelectPasswordType(value)); + context.read().add(SelectPasswordType(value)); } }, ), ), ], - ) + ), ], ), + visitorBloc.accessTypeSelected=='Dynamic Password' ? + SizedBox(): Column( crossAxisAlignment: CrossAxisAlignment.start, - mainAxisAlignment: MainAxisAlignment.start, children: [ Row( children: [ @@ -146,11 +144,10 @@ class VisitorPasswordDialog extends StatelessWidget { value: 'One-Time', groupValue: (state is UsageFrequencySelected) ? state.selectedFrequency - : 'One-Time', + : visitorBloc.usageFrequencySelected, onChanged: (String? value) { if (value != null) { - context.read() - .add(SelectUsageFrequency(value)); + context.read().add(SelectUsageFrequency(value)); } }, ), @@ -162,59 +159,80 @@ class VisitorPasswordDialog extends StatelessWidget { value: 'Periodic', groupValue: (state is UsageFrequencySelected) ? state.selectedFrequency - : 'Periodic1', + : visitorBloc.usageFrequencySelected, onChanged: (String? value) { if (value != null) { - context.read() - .add(SelectUsageFrequency(value)); + context.read().add(SelectUsageFrequency(value)); } }, ), ), ], - ) + ), ], ), + visitorBloc.accessTypeSelected=='Dynamic Password' ? + SizedBox(): + DateTimeWebWidget( isRequired: true, - title: 'Access Period', - size: size, - endTime: () { - visitorBloc.add(SelectTimeVisitorPassword(context: context, isStart: false)); - }, - startTime: () { - visitorBloc.add(SelectTimeVisitorPassword(context: context, isStart: true)); - }, - firstString:BlocProvider.of(context).startTime , - secondString:BlocProvider.of(context).endTime , - ) , - + title: 'Access Period', + size: size, + endTime: () { + visitorBloc.add(SelectTimeVisitorPassword(context: context, isStart: false)); + }, + startTime: () { + visitorBloc.add(SelectTimeVisitorPassword(context: context, isStart: true)); + }, + firstString: visitorBloc.startTime, + secondString: visitorBloc.endTime, + ), Column( - mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( children: [ - Text( - '* ', - style: Theme.of(context) - .textTheme - .bodyMedium! - .copyWith(color: Colors.red), - ), + Text( + '* ', + style: Theme.of(context) + .textTheme + .bodyMedium! + .copyWith(color: Colors.red), + ), const Text('Access Devices'), ], ), 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( - decoration: containerDecoration, - width: size.width*0.2, - child: const DefaultButton( - borderRadius: 8, - child:Text('+ Add Device'),)), - + decoration: containerDecoration, + width: size.width * 0.2, + child: const DefaultButton( + borderRadius: 8, + child: Text('+ Add Device'), + ), + ), ], - ) + ), + ], ), ), @@ -222,22 +240,27 @@ class VisitorPasswordDialog extends StatelessWidget { actions: [ Container( decoration: containerDecoration, - width: size.width*0.2, - child: DefaultButton( - borderRadius: 8, - onPressed:() {}, - backgroundColor: Colors.white, - child:Text('Cancel',style: Theme.of(context) - .textTheme - .bodyMedium!,),)), - + width: size.width * 0.2, + child: DefaultButton( + borderRadius: 8, + onPressed: () { + Navigator.of(context).pop(); // Close the dialog + }, + backgroundColor: Colors.white, + child: Text( + 'Cancel', + style: Theme.of(context).textTheme.bodyMedium!, + ), + ), + ), Container( - decoration: containerDecoration, - width: size.width*0.2, - child: const DefaultButton( - borderRadius: 8, - child:Text('Ok'),)), - + decoration: containerDecoration, + width: size.width * 0.2, + child: const DefaultButton( + borderRadius: 8, + child: Text('Ok'), + ), + ), ], ); }, @@ -245,4 +268,3 @@ class VisitorPasswordDialog extends StatelessWidget { ); } } -