diff --git a/lib/features/devices/bloc/smart_door_bloc/smart_door_bloc.dart b/lib/features/devices/bloc/smart_door_bloc/smart_door_bloc.dart index a98dd01..605e907 100644 --- a/lib/features/devices/bloc/smart_door_bloc/smart_door_bloc.dart +++ b/lib/features/devices/bloc/smart_door_bloc/smart_door_bloc.dart @@ -1,5 +1,5 @@ import 'dart:math'; -import 'package:day_picker/model/day_in_week.dart'; +import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:intl/intl.dart'; @@ -13,7 +13,6 @@ import 'package:syncrow_app/features/devices/model/temporary_password_model.dart import 'package:syncrow_app/services/api/devices_api.dart'; import 'package:syncrow_app/utils/helpers/snack_bar.dart'; import 'package:syncrow_app/utils/resource_manager/color_manager.dart'; - class SmartDoorBloc extends Bloc { final String deviceId; late SmartDoorModel deviceStatus; @@ -33,6 +32,7 @@ class SmartDoorBloc extends Bloc { on(deletePassword); on(generateAndSavePasswordTimeLimited); on(generateAndSavePasswordOneTime); + on(toggleDaySelection); } TextEditingController passwordController = TextEditingController(); @@ -43,7 +43,6 @@ class SmartDoorBloc extends Bloc { int? expirationTimeTimeStamp; bool repeat = false; bool isStartEndTime = true; - List? selectedDay; DateTime? startTime; DateTime? endTime; List? temporaryPasswords = []; @@ -63,19 +62,15 @@ class SmartDoorBloc extends Bloc { Future generateAndSavePasswordOneTime (GenerateAndSavePasswordOneTimeEvent event, Emitter emit) async { try { - if (passwordNameController.text.isEmpty) { - CustomSnackBar.displaySnackBar('Password name required'); - }else { - if (isSavingPassword) return; - isSavingPassword = true; - emit(LoadingInitialState()); - Future.delayed(const Duration(milliseconds: 800), () { - add(GeneratePasswordEvent()); - CustomSnackBar.displaySnackBar('Save Successfully'); - }); - emit(const GeneratePasswordOneTimestate(generated: true)); + if (isSavingPassword) return; + isSavingPassword = true; + emit(LoadingInitialState()); + Future.delayed(const Duration(milliseconds: 800), () { + add(GeneratePasswordEvent()); + CustomSnackBar.displaySnackBar('Save Successfully'); + }); + emit(const GeneratePasswordOneTimestate(generated: true)); - } } catch (_) {}finally { isSavingPassword = false; } @@ -115,13 +110,11 @@ class SmartDoorBloc extends Bloc { } changeTime(ChangeTimeEvent event, Emitter emit) { - emit(LoadingInitialState()); if (event.isStartEndTime == true) { startTime = event.val; } else { endTime = event.val; } - emit(ChangeTimeState()); } bool toggleRepeat(ToggleRepeatEvent event, Emitter emit) { @@ -191,7 +184,6 @@ class SmartDoorBloc extends Bloc { timePicked.hour, timePicked.minute, ); - // Convert selectedDateTime to a timestamp without seconds and milliseconds final selectedTimestamp = DateTime( selectedDateTime.year, selectedDateTime.month, @@ -239,7 +231,7 @@ class SmartDoorBloc extends Bloc { Schedule( effectiveTime: getTimeOnly(startTime), invalidTime: getTimeOnly(endTime).toString(), - workingDay: selectedDay!, + workingDay: selectedDays, ), ], ); @@ -305,25 +297,39 @@ class SmartDoorBloc extends Bloc { CustomSnackBar.displaySnackBar('Select expiration time'); return true; } - if (repeat == true && (endTime == null || startTime == null || selectedDay == null)) { + if (repeat == true && (endTime == null || startTime == null || selectedDays == null)) { CustomSnackBar.displaySnackBar('Start Time and End time and the days required '); return true; } return false; } - List days = [ - DayInWeek("S", dayKey: 'Sun'), - DayInWeek("M", dayKey: 'Mon'), - DayInWeek("T", dayKey: 'Tue'), - DayInWeek("W", dayKey: 'Wed'), - DayInWeek("T", dayKey: 'Thu'), - DayInWeek("F", dayKey: 'Fri'), - DayInWeek("S", dayKey: 'Sat'), + + 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()); + } String getTimeOnly(DateTime? dateTime) { if (dateTime == null) return ''; return DateFormat('HH:mm').format(dateTime); } } + + diff --git a/lib/features/devices/bloc/smart_door_bloc/smart_door_event.dart b/lib/features/devices/bloc/smart_door_bloc/smart_door_event.dart index 67d5e98..892f3de 100644 --- a/lib/features/devices/bloc/smart_door_bloc/smart_door_event.dart +++ b/lib/features/devices/bloc/smart_door_bloc/smart_door_event.dart @@ -71,6 +71,14 @@ class DeletePasswordEvent extends SmartDoorEvent { List get props => [passwordId]; } +class ToggleDaySelectionEvent extends SmartDoorEvent { + final String key; + + const ToggleDaySelectionEvent({required this.key}); + @override + List get props => [key]; +} + class ChangeTimeEvent extends SmartDoorEvent { final dynamic val; final bool isStartEndTime; diff --git a/lib/features/devices/view/widgets/name_time_widget.dart b/lib/features/devices/view/widgets/name_time_widget.dart index 9302ced..d54ecf4 100644 --- a/lib/features/devices/view/widgets/name_time_widget.dart +++ b/lib/features/devices/view/widgets/name_time_widget.dart @@ -7,8 +7,7 @@ import 'package:syncrow_app/features/shared_widgets/text_widgets/body_medium.dar import 'package:syncrow_app/utils/resource_manager/color_manager.dart'; class NameTimeWidget extends StatelessWidget { - final String type; - const NameTimeWidget({super.key,required this.type}); + const NameTimeWidget({super.key}); @override Widget build(BuildContext context) { @@ -40,7 +39,6 @@ class NameTimeWidget extends StatelessWidget { )), ], ), - if(type!='One-Time') Column( children: [ const Divider( @@ -61,6 +59,7 @@ class NameTimeWidget extends StatelessWidget { width: MediaQuery.of(context).size.width / 3.5, child: InkWell( onTap: () { + BlocProvider.of(context).add(SelectTimeEvent(context: context, isEffective: true)); }, child: Text( diff --git a/lib/features/devices/view/widgets/offline_one_time_password_page.dart b/lib/features/devices/view/widgets/offline_one_time_password_page.dart new file mode 100644 index 0000000..3bfc334 --- /dev/null +++ b/lib/features/devices/view/widgets/offline_one_time_password_page.dart @@ -0,0 +1,226 @@ + + + +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:syncrow_app/features/devices/bloc/smart_door_bloc/smart_door_bloc.dart'; +import 'package:syncrow_app/features/devices/bloc/smart_door_bloc/smart_door_event.dart'; +import 'package:syncrow_app/features/devices/bloc/smart_door_bloc/smart_door_state.dart'; +import 'package:syncrow_app/features/devices/view/widgets/smart_door/repeat_widget.dart'; +import 'package:syncrow_app/features/shared_widgets/default_button.dart'; +import 'package:syncrow_app/features/shared_widgets/default_container.dart'; +import 'package:syncrow_app/features/shared_widgets/default_scaffold.dart'; +import 'package:syncrow_app/features/shared_widgets/text_widgets/body_large.dart'; +import 'package:syncrow_app/features/shared_widgets/text_widgets/body_medium.dart'; +import 'package:syncrow_app/utils/resource_manager/color_manager.dart'; +import 'package:syncrow_app/utils/resource_manager/font_manager.dart'; + + +class OfflineOneTimePasswordPage extends StatelessWidget { + final String? deviceId; + final String? type; + const OfflineOneTimePasswordPage({super.key, this.deviceId, this.type}); + @override + Widget build(BuildContext context) { + bool isRepeat = false; + bool generated = false; + return BlocProvider( + create: (BuildContext context) => SmartDoorBloc(deviceId: deviceId!), + child: BlocConsumer(listener: (context, state) { + if (state is FailedState) { + ScaffoldMessenger.of(context).showSnackBar( + SnackBar( + content: Text(state.errorMessage), + backgroundColor: Colors.red, + ), + ); + } + if (state is IsRepeatState){ + isRepeat = state.repeat; + } + if (state is GeneratePasswordOneTimestate ){ + generated = state.generated; + } + }, builder: (context, state) { + final smartDoorBloc = BlocProvider.of(context); + return DefaultScaffold( + appBar: AppBar( + backgroundColor: Colors.transparent, + centerTitle: true, + title: const BodyLarge( + text: 'Create One-Time Password', + fontColor: ColorsManager.primaryColor, + fontWeight: FontsManager.bold, + ), + leading: IconButton( + onPressed: () { + Navigator.of(context).pop(true); + }, + icon: const Icon(Icons.arrow_back) + ), + ), + child: state is LoadingInitialState + ? const Center(child: CircularProgressIndicator()) + : SingleChildScrollView( + child: Column( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const BodyMedium( + text: 'Save the password immediately. The password is not displayed in the app.', + fontWeight: FontWeight.normal, + fontColor: ColorsManager.grayColor, + ), + const SizedBox( + height: 20, + ), + const BodyMedium( + text: '7-Digit Password', + fontWeight: FontWeight.normal, + fontColor: ColorsManager.grayColor, + ), + DefaultContainer( + padding: const EdgeInsets.symmetric(horizontal: 15, vertical: 15), + child: Column( + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + mainAxisSize: MainAxisSize.max, + children: [ + Flexible( + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children:smartDoorBloc.passwordController.text.isEmpty? + List.generate(10, (index) { + return const Padding( + padding: EdgeInsets.symmetric(horizontal: 4.0,vertical: 15), + child: Icon( + Icons.circle, + size: 20.0, + color: Colors.black, + ), + ); + }) + :[ + Expanded( + child: Row( + children: [ + Expanded( + child: BodyLarge( + style: const TextStyle( + color: ColorsManager.primaryColor, + fontWeight: FontWeight.bold, + letterSpacing: 8.0 , + fontSize: 25, + wordSpacing: 2), + textAlign: TextAlign.center, + text: smartDoorBloc.passwordController.text, + fontSize: 25, + ),), + IconButton( + onPressed: () async { + await Clipboard.setData(ClipboardData( + text: smartDoorBloc.passwordController.text)); + }, + icon: const Icon(Icons.copy) + ), + ], + ), + ), + ], + )), + const SizedBox( + width: 10, + ), + + ], + ), + if(smartDoorBloc.passwordController.text.isNotEmpty) + Column( + children: [ + const Divider( + color: ColorsManager.graysColor, + ), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Expanded( + child: Container( + padding: const EdgeInsets.all(10.0), + child: const BodyMedium( + text: 'Password Name', + fontWeight: FontWeight.normal, + ), + ), + ), + SizedBox( + width: MediaQuery.of(context).size.width / 2.6, + child: TextFormField( + controller: BlocProvider.of(context) + .passwordNameController, + decoration: const InputDecoration( + hintText: 'Enter The Name', + hintStyle: TextStyle( + fontSize: 14, color: ColorsManager.textGray)), + )), + ], + ), + + ], + ), + + ], + ), + ), + const SizedBox( + height: 20, + ), + const BodyMedium( + textAlign: TextAlign.center, + text: 'Save the password immediately. The password is not displayed in the app.', + fontWeight: FontWeight.normal, + fontColor: ColorsManager.grayColor, + ), + + // NameTimeWidget(type:type!), + const SizedBox( + height: 20, + ), + Center( + child: SizedBox( + width: MediaQuery.of(context).size.width/1.5, + child: DefaultButton( + isDone: generated, + isLoading: smartDoorBloc.isSavingPassword , + borderRadius: 30, + backgroundColor:ColorsManager.primaryColor , + onPressed: () { + if(generated==false){ + smartDoorBloc.add(GenerateAndSavePasswordOneTimeEvent(context: context)); + }else{ + Navigator.pop(context); + } + }, + child: const BodyMedium( + text: 'Obtain Password', + fontWeight: FontWeight.bold, + fontColor: Colors.white, + ),), + ), + ), + const SizedBox( + height: 20, + ), + isRepeat? const RepeatWidget():const SizedBox(), + const SizedBox( + height: 40, + ) + ], + ), + ), + ); + })); + } +} diff --git a/lib/features/devices/view/widgets/smart_door/create_temporary_password.dart b/lib/features/devices/view/widgets/smart_door/create_temporary_password.dart index e6a41ad..2eb0e3c 100644 --- a/lib/features/devices/view/widgets/smart_door/create_temporary_password.dart +++ b/lib/features/devices/view/widgets/smart_door/create_temporary_password.dart @@ -159,7 +159,7 @@ class CreateTemporaryPassword extends StatelessWidget { const SizedBox( height: 20, ), - NameTimeWidget(type:type!), + NameTimeWidget(), const SizedBox( height: 20, ), diff --git a/lib/features/devices/view/widgets/smart_door/offline_timeLimit_password_page.dart b/lib/features/devices/view/widgets/smart_door/offline_timeLimit_password_page.dart new file mode 100644 index 0000000..eea7e35 --- /dev/null +++ b/lib/features/devices/view/widgets/smart_door/offline_timeLimit_password_page.dart @@ -0,0 +1,291 @@ +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:syncrow_app/features/devices/bloc/smart_door_bloc/smart_door_bloc.dart'; +import 'package:syncrow_app/features/devices/bloc/smart_door_bloc/smart_door_event.dart'; +import 'package:syncrow_app/features/devices/bloc/smart_door_bloc/smart_door_state.dart'; +import 'package:syncrow_app/features/devices/view/widgets/smart_door/repeat_widget.dart'; +import 'package:syncrow_app/features/shared_widgets/default_button.dart'; +import 'package:syncrow_app/features/shared_widgets/default_container.dart'; +import 'package:syncrow_app/features/shared_widgets/default_scaffold.dart'; +import 'package:syncrow_app/features/shared_widgets/text_widgets/body_large.dart'; +import 'package:syncrow_app/features/shared_widgets/text_widgets/body_medium.dart'; +import 'package:syncrow_app/utils/resource_manager/color_manager.dart'; +import 'package:syncrow_app/utils/resource_manager/font_manager.dart'; + +class OfflineTimeLimitPasswordPage extends StatelessWidget { + final String? deviceId; + final String? type; + const OfflineTimeLimitPasswordPage({super.key, this.deviceId, this.type}); + @override + Widget build(BuildContext context) { + bool isRepeat = false; + bool generated = false; + return BlocProvider( + create: (BuildContext context) => SmartDoorBloc(deviceId: deviceId!), + child: BlocConsumer( + + listener: (context, state) { + if (state is FailedState) { + ScaffoldMessenger.of(context).showSnackBar( + SnackBar( + content: Text(state.errorMessage), + backgroundColor: Colors.red, + ), + ); + } + if (state is IsRepeatState) { + isRepeat = state.repeat; + } + if (state is GeneratePasswordOneTimestate) { + generated = state.generated; + } + }, builder: (context, state) { + final smartDoorBloc = BlocProvider.of(context); + return DefaultScaffold( + appBar: AppBar( + backgroundColor: Colors.transparent, + centerTitle: true, + title: const BodyLarge( + text: 'Create Time-Limited Password', + fontColor: ColorsManager.primaryColor, + fontWeight: FontsManager.bold, + ), + leading: IconButton( + onPressed: () { + Navigator.of(context).pop(true); + }, + icon: const Icon(Icons.arrow_back)), + ), + child: state is LoadingInitialState + ? const Center(child: CircularProgressIndicator()) + : SingleChildScrollView( + child: Column( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const BodyMedium( + text: + 'Save the password immediately. The password is not displayed in the app.', + fontWeight: FontWeight.normal, + fontColor: ColorsManager.grayColor, + ), + const SizedBox( + height: 20, + ), + + DefaultContainer( + padding: const EdgeInsets.symmetric( + horizontal: 10, vertical: 15), + child: Column( + children: [ + Row( + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + mainAxisSize: MainAxisSize.max, + children: [ + Flexible( + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: smartDoorBloc.passwordController.text.isEmpty ? + List.generate(10, (index) { + return const Padding( + padding: EdgeInsets.symmetric( + horizontal: 4.0, + vertical: 15), + child: Icon( + Icons.circle, + size: 20.0, + color: Colors.black, + ), + ); + }) : [ + Expanded( + child: Row( + children: [ + Expanded( + child: BodyLarge( + style: const TextStyle( + color: ColorsManager.primaryColor, + fontWeight: FontWeight.bold, + letterSpacing: 8.0, + fontSize: 25, + wordSpacing: 2), + textAlign: TextAlign.center, + text: smartDoorBloc.passwordController.text, + fontSize: 25, + ), + ), + IconButton( + onPressed: () async { + await Clipboard.setData( + ClipboardData(text: smartDoorBloc.passwordController.text) + ); + }, + icon: const Icon(Icons.copy)), + ], + ), + ), + ], + )), + const SizedBox( + width: 10, + ), + ], + ), + DefaultContainer( + padding: const EdgeInsets.all(20), + child: Column( + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Expanded( + child: Container( + padding: const EdgeInsets.all(10.0), + child: const BodyMedium( + text: 'Password Name', + fontWeight: FontWeight.normal, + ), + ), + ), + SizedBox( + width: MediaQuery.of(context).size.width / 2.6, + child: TextFormField( + controller: BlocProvider.of(context).passwordNameController, + decoration: + const InputDecoration( + hintText: 'Enter The Name', + hintStyle: TextStyle( + fontSize: 14, + color: ColorsManager.textGray) + ), + )), + ], + ), + Column( + children: [ + const Divider(color: ColorsManager.graysColor,), + Padding( + padding: const EdgeInsets.all(10.0), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + const Expanded( + child: BodyMedium( + text: 'Effective Time', + fontWeight: FontWeight.normal, + ), + ), + SizedBox( + width: MediaQuery.of(context).size.width / 3.5, + child: InkWell( + onTap: () { + BlocProvider.of(context).add(SelectTimeEvent(context: context, isEffective: true)); + }, + child: Text( + BlocProvider.of(context).effectiveTime, + style: TextStyle( + fontSize: 14, + color: BlocProvider.of(context).effectiveTime == + 'Select Time' ? ColorsManager.textGray : null), + ), + )),], + ), + ), + const Divider( + color: ColorsManager.graysColor, + ), + Padding( + padding: const EdgeInsets.all(10.0), + child: Row(mainAxisAlignment: + MainAxisAlignment.spaceBetween, + children: [ + const Expanded( + child: BodyMedium( + text: 'Expiration Time', + fontWeight: FontWeight.normal, + ), + ), + SizedBox( + width: MediaQuery.of(context).size.width / 3.5, + child: InkWell( + onTap: () { + BlocProvider.of(context).add(SelectTimeEvent( + context: context, + isEffective: false)); + }, + child: Text( + BlocProvider.of(context).expirationTime, + style: TextStyle( + fontSize: 14, + color: BlocProvider.of(context) + .expirationTime == 'Select Time' ? ColorsManager + .textGray : null), + ), + ), + ), + ], + ), + ), + ], + ), + ], + )), + ], + ), + ), + const SizedBox( + height: 20, + ), + const BodyMedium( + textAlign: TextAlign.center, + text: + 'Use the time-limited password at least once within 24 hours after the password takes effect. Otherwise, the password becomes invalid.', + fontWeight: FontWeight.normal, + fontColor: ColorsManager.grayColor, + ), + // NameTimeWidget(type:type!), + const SizedBox( + height: 20, + ), + Center( + child: SizedBox( + width: MediaQuery.of(context).size.width / 1.5, + child: DefaultButton( + isDone: generated, + isLoading: smartDoorBloc.isSavingPassword, + borderRadius: 30, + backgroundColor: ColorsManager.primaryColor, + onPressed: () { + if (generated == false) { + smartDoorBloc.add( + GenerateAndSavePasswordTimeLimitEvent( + context: context)); + } else { + Navigator.pop(context); + } + }, + child: const BodyMedium( + text: 'Obtain Password', + fontWeight: FontWeight.bold, + fontColor: Colors.white, + ), + ), + ), + ), + const SizedBox( + height: 20, + ), + isRepeat ? const RepeatWidget() : const SizedBox(), + const SizedBox( + height: 40, + ) + ], + ), + ), + ); + })); + } +} diff --git a/lib/features/devices/view/widgets/smart_door/repeat_widget.dart b/lib/features/devices/view/widgets/smart_door/repeat_widget.dart index 7166cbd..b35b320 100644 --- a/lib/features/devices/view/widgets/smart_door/repeat_widget.dart +++ b/lib/features/devices/view/widgets/smart_door/repeat_widget.dart @@ -1,6 +1,4 @@ - - -import 'package:day_picker/day_picker.dart'; +import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:syncrow_app/features/devices/bloc/smart_door_bloc/smart_door_bloc.dart'; @@ -9,8 +7,6 @@ import 'package:syncrow_app/features/devices/bloc/smart_door_bloc/smart_door_sta import 'package:syncrow_app/features/shared_widgets/default_container.dart'; import 'package:syncrow_app/features/shared_widgets/text_widgets/body_medium.dart'; import 'package:syncrow_app/utils/resource_manager/color_manager.dart'; -import 'package:time_picker_spinner/time_picker_spinner.dart'; - class RepeatWidget extends StatelessWidget { const RepeatWidget({ @@ -19,14 +15,13 @@ class RepeatWidget extends StatelessWidget { @override Widget build(BuildContext context) { - return BlocBuilder( - builder: (context, state) { - final smartDoorBloc = BlocProvider.of(context); - return DefaultContainer( - padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 5), - child: Column( - children: [ + return BlocBuilder( + builder: (context, state) { + final smartDoorBloc = BlocProvider.of(context); + return DefaultContainer( + padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 5), + child: Column(children: [ Padding( padding: const EdgeInsets.all(8.0), child: Row( @@ -34,14 +29,11 @@ class RepeatWidget extends StatelessWidget { children: [ InkWell( onTap: () { - smartDoorBloc - .add(const SetStartEndTimeEvent(val: true)); + smartDoorBloc.add(const SetStartEndTimeEvent(val: true)); }, child: BodyMedium( text: 'Start', - fontColor: smartDoorBloc - .isStartEndTime == - false + fontColor: smartDoorBloc.isStartEndTime == false ? Colors.black : Colors.blue, fontSize: 18, @@ -53,8 +45,7 @@ class RepeatWidget extends StatelessWidget { }, child: BodyMedium( text: 'End', - fontColor: smartDoorBloc - .isStartEndTime + fontColor: smartDoorBloc.isStartEndTime ? Colors.black : Colors.blue, fontSize: 18, @@ -66,69 +57,69 @@ class RepeatWidget extends StatelessWidget { const Divider( color: ColorsManager.graysColor, ), - Container( + smartDoorBloc.isStartEndTime + ? Container( height: 110, - child: smartDoorBloc.isStartEndTime - ? TimePickerSpinner( - time: - smartDoorBloc.startTime, - is24HourMode: false, - itemHeight: 40, - normalTextStyle: const TextStyle( - color: Colors.grey, - fontSize: 24, - ), - highlightedTextStyle: - const TextStyle(fontSize: 30, color: Colors.blue), - onTimeChange: (time) { - smartDoorBloc.add( - ChangeTimeEvent( - val: time, - isStartEndTime: - smartDoorBloc.isStartEndTime)); + child: CupertinoDatePicker( + mode: CupertinoDatePickerMode.time, + initialDateTime:smartDoorBloc.startTime, + onDateTimeChanged: (startTime) { + smartDoorBloc.add(ChangeTimeEvent(val: startTime, isStartEndTime: true)); + }, + ) + ):SizedBox( + height: 110, + child: CupertinoDatePicker( + mode: CupertinoDatePickerMode.time, + initialDateTime:smartDoorBloc.endTime, + onDateTimeChanged: (endTime) { + smartDoorBloc.add(ChangeTimeEvent(val: endTime, isStartEndTime: false)); }, ) - : Container( - child: TimePickerSpinner( - time: smartDoorBloc.endTime, - is24HourMode: false, - itemHeight: 40, - normalTextStyle: const TextStyle( - color: Colors.grey, - fontSize: 24, - ), - highlightedTextStyle: const TextStyle( - fontSize: 30, color: Colors.blue), - onTimeChange: (time) { - smartDoorBloc.add( - ChangeTimeEvent( - val: time, - isStartEndTime: - smartDoorBloc.isStartEndTime)); - }, - ), - ), ), const Divider( color: ColorsManager.graysColor, ), const SizedBox(height: 20), - SelectWeekDays( - width: MediaQuery.of(context).size.width / 1, - fontSize: 18, - fontWeight: FontWeight.w600, - days: smartDoorBloc.days, - border: false, - selectedDayTextColor: Colors.black, - unSelectedDayTextColor: Colors.grey, - boxDecoration: BoxDecoration( - borderRadius: BorderRadius.circular(30.0), - color: Colors.white), - onSelect: (values) { - smartDoorBloc.selectedDay = values; - }, - ), - ], - ));}); + SizedBox( + height: MediaQuery.of(context).size.height *0.10, + child: ListView( + scrollDirection: Axis.horizontal, + children: smartDoorBloc.days.map((day) { + bool isSelected = smartDoorBloc.selectedDays.contains(day['key']); + return Padding( + padding: const EdgeInsets.all(8.0), + child: InkWell( + onTap: () { + smartDoorBloc.add(ToggleDaySelectionEvent(key:day['key']!)); + }, + child: Container( + width: 70, + padding: EdgeInsets.symmetric(vertical: 8, horizontal: 8), + decoration: BoxDecoration( + border: Border.all( + color: isSelected? + Colors.black:ColorsManager.grayColor + ), + color: Colors.transparent, + borderRadius: BorderRadius.circular(55), + ), + child: Center( + child: Text( + day['day']!, + style: TextStyle( + fontSize: 18, + color: isSelected ? Colors.black : ColorsManager.grayColor, + ), + ), + ), + ), + ), + ); + }).toList(), + ) + ) + ])); + }); } } diff --git a/lib/features/devices/view/widgets/smart_door/view_temporary_password.dart b/lib/features/devices/view/widgets/smart_door/view_temporary_password.dart index 20be6d9..4c426ed 100644 --- a/lib/features/devices/view/widgets/smart_door/view_temporary_password.dart +++ b/lib/features/devices/view/widgets/smart_door/view_temporary_password.dart @@ -4,6 +4,8 @@ import 'package:flutter_svg/svg.dart'; import 'package:syncrow_app/features/devices/bloc/smart_door_bloc/smart_door_bloc.dart'; import 'package:syncrow_app/features/devices/bloc/smart_door_bloc/smart_door_event.dart'; import 'package:syncrow_app/features/devices/bloc/smart_door_bloc/smart_door_state.dart'; +import 'package:syncrow_app/features/devices/view/widgets/offline_one_time_password_page.dart'; +import 'package:syncrow_app/features/devices/view/widgets/smart_door/offline_timeLimit_password_page.dart'; import 'package:syncrow_app/features/shared_widgets/default_container.dart'; import 'package:syncrow_app/features/shared_widgets/default_scaffold.dart'; import 'package:syncrow_app/features/shared_widgets/text_widgets/body_medium.dart'; @@ -32,85 +34,90 @@ class ViewTemporaryPassword extends StatelessWidget { ); } }, - builder: (context, state) { - final smartDoorBloc = BlocProvider.of(context); - return DefaultScaffold( - title: 'Passwords', - actions: [ - IconButton( - onPressed: () { - Navigator.of(context).push(MaterialPageRoute( - builder: (context) => CreateTemporaryPassword(deviceId: deviceId, type: type), - )).then((result) { - if (result != null && result) { - smartDoorBloc.add(InitialPasswordsPage(type:type )); - } - }); - }, - icon: const Icon(Icons.add) - ) - ], - child: Builder( - builder: (context) { - return state is LoadingInitialState - ? const Center(child: CircularProgressIndicator()) - : Center( - child: smartDoorBloc.temporaryPasswords!.isNotEmpty - ? ListView.builder( - itemCount: smartDoorBloc.temporaryPasswords!.length, - itemBuilder: (context, index) { - return Padding( - padding: const EdgeInsets.all(5.0), - child: DefaultContainer( - padding: const EdgeInsets.symmetric( - horizontal: 15, vertical: 10), - child: ListTile( - contentPadding: EdgeInsets.zero, - leading: SvgPicture.asset( - Assets.timeLimitedPasswordIcon), - title: BodyMedium( - text: 'Password Name: ${smartDoorBloc.temporaryPasswords![index].name}', - fontWeight: FontWeight.normal, - ), - onTap: () async { - final result = await showDialog( - context: context, - builder: (context) { - return DoorDialog( - title: 'Password Information', - value: smartDoorBloc.temporaryPasswords![index], - ); - }, - ); - if(result=='delete'){ - smartDoorBloc.add(DeletePasswordEvent(passwordId: smartDoorBloc.temporaryPasswords![index].id.toString())); - } - }, - trailing: const Icon( - Icons.arrow_forward_ios, - color: ColorsManager.greyColor, - size: 15, - ), - ), - ), - ); - }, + builder: (context, state) { + final smartDoorBloc = BlocProvider.of(context); + return DefaultScaffold( + title: 'Passwords', + actions: [ + IconButton( + onPressed: () { + Navigator.of(context).push( + MaterialPageRoute(builder: (context) => + type=='One-Time' ? + OfflineOneTimePasswordPage(deviceId: deviceId, type: type) + : type=='Time-Limited' ? + OfflineTimeLimitPasswordPage(deviceId: deviceId, type: type) + : + CreateTemporaryPassword(deviceId: deviceId, type: type), + )).then((result) { + if (result != null && result) { + smartDoorBloc.add(InitialPasswordsPage(type:type )); + } + }); + }, + icon: const Icon(Icons.add) ) - : Column( - crossAxisAlignment: CrossAxisAlignment.center, - mainAxisAlignment: MainAxisAlignment.center, - children: [ - SvgPicture.asset(Assets.noValidPasswords), - const SizedBox( - height: 10, + ], + child: Builder( + builder: (context) { + return state is LoadingInitialState + ? const Center(child: CircularProgressIndicator()) + : Center( + child: smartDoorBloc.temporaryPasswords!.isNotEmpty + ? ListView.builder( + itemCount: smartDoorBloc.temporaryPasswords!.length, + itemBuilder: (context, index) { + return Padding( + padding: const EdgeInsets.all(5.0), + child: DefaultContainer( + padding: const EdgeInsets.symmetric(horizontal: 15, vertical: 10), + child: ListTile( + contentPadding: EdgeInsets.zero, + leading: SvgPicture.asset( + Assets.timeLimitedPasswordIcon), + title: BodyMedium( + text: 'Password Name: ${smartDoorBloc.temporaryPasswords![index].name}', + fontWeight: FontWeight.normal, + ), + onTap: () async { + final result = await showDialog( + context: context, + builder: (context) { + return DoorDialog( + title: 'Password Information', + value: smartDoorBloc.temporaryPasswords![index], + ); + }, + ); + if(result=='delete'){ + smartDoorBloc.add(DeletePasswordEvent(passwordId: smartDoorBloc.temporaryPasswords![index].id.toString())); + } + }, + trailing: const Icon( + Icons.arrow_forward_ios, + color: ColorsManager.greyColor, + size: 15, + ), + ), + ), + ); + }, + ) + : Column( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + SvgPicture.asset(Assets.noValidPasswords), + const SizedBox( + height: 10, + ), + const BodyMedium(text: 'No Valid Passwords') + ], ), - const BodyMedium(text: 'No Valid Passwords') - ], - ), - ); - }, - )); - }) + ); + }, + )); + }) ); } } diff --git a/pubspec.yaml b/pubspec.yaml index 59f680d..944972b 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -42,7 +42,6 @@ dependencies: shared_preferences: ^2.2.2 smooth_page_indicator: ^1.1.0 uuid: ^4.4.0 - time_picker_spinner: ^1.0.0 dev_dependencies: flutter_lints: ^3.0.1