diff --git a/lib/pages/access_management/manage_bookable_spaces/presentation/blocs/cubit/toggle_points_switch_cubit.dart b/lib/pages/access_management/manage_bookable_spaces/presentation/blocs/cubit/toggle_points_switch_cubit.dart new file mode 100644 index 00000000..0b0f11f0 --- /dev/null +++ b/lib/pages/access_management/manage_bookable_spaces/presentation/blocs/cubit/toggle_points_switch_cubit.dart @@ -0,0 +1,18 @@ +import 'package:bloc/bloc.dart'; +import 'package:equatable/equatable.dart'; + +part 'toggle_points_switch_state.dart'; + +class TogglePointsSwitchCubit extends Cubit { + TogglePointsSwitchCubit() : super(TogglePointsSwitchInitial()); + bool switchValue = true; + void activateSwitch() { + switchValue = true; + emit(ActivatePointsSwitch()); + } + + void unActivateSwitch() { + switchValue = false; + emit(UnActivatePointsSwitch()); + } +} diff --git a/lib/pages/access_management/manage_bookable_spaces/presentation/blocs/cubit/toggle_points_switch_state.dart b/lib/pages/access_management/manage_bookable_spaces/presentation/blocs/cubit/toggle_points_switch_state.dart new file mode 100644 index 00000000..872ae8dc --- /dev/null +++ b/lib/pages/access_management/manage_bookable_spaces/presentation/blocs/cubit/toggle_points_switch_state.dart @@ -0,0 +1,14 @@ +part of 'toggle_points_switch_cubit.dart'; + +sealed class TogglePointsSwitchState extends Equatable { + const TogglePointsSwitchState(); + + @override + List get props => []; +} + +final class TogglePointsSwitchInitial extends TogglePointsSwitchState {} + +class ActivatePointsSwitch extends TogglePointsSwitchState {} + +class UnActivatePointsSwitch extends TogglePointsSwitchState {} diff --git a/lib/pages/access_management/manage_bookable_spaces/presentation/blocs/update_bookable_spaces/update_bookable_spaces_bloc.dart b/lib/pages/access_management/manage_bookable_spaces/presentation/blocs/update_bookable_spaces/update_bookable_spaces_bloc.dart new file mode 100644 index 00000000..ccece88e --- /dev/null +++ b/lib/pages/access_management/manage_bookable_spaces/presentation/blocs/update_bookable_spaces/update_bookable_spaces_bloc.dart @@ -0,0 +1,35 @@ +import 'package:bloc/bloc.dart'; +import 'package:equatable/equatable.dart'; +import 'package:syncrow_web/pages/access_management/manage_bookable_spaces/domain/models/bookable_space_config.dart'; +import 'package:syncrow_web/pages/access_management/manage_bookable_spaces/domain/params/update_bookable_space_param.dart'; +import 'package:syncrow_web/pages/access_management/manage_bookable_spaces/domain/service/update_bookable_space_service.dart'; +import 'package:syncrow_web/services/api/api_exception.dart'; + +part 'update_bookable_spaces_event.dart'; +part 'update_bookable_spaces_state.dart'; + +class UpdateBookableSpacesBloc + extends Bloc { + final UpdateBookableSpaceService updateBookableSpaceService; + UpdateBookableSpacesBloc(this.updateBookableSpaceService) + : super(UpdateBookableSpacesInitial()) { + on(_onUpdateBookableSpace); + } + + Future _onUpdateBookableSpace(UpdateBookableSpace event, + Emitter emit) async { + emit(UpdateBookableSpaceLoading(event.updatedParams.spaceUuid)); + try { + final updatedSpace = + await updateBookableSpaceService.update(event.updatedParams); + + emit(UpdateBookableSpaceSuccess(bookableSpaceConfig: updatedSpace)); + } on APIException catch (e) { + emit(UpdateBookableSpaceFailure(error: e.message)); + } catch (e) { + emit( + UpdateBookableSpaceFailure(error: e.toString()), + ); + } + } +} diff --git a/lib/pages/access_management/manage_bookable_spaces/presentation/widgets/booking_period_widget.dart b/lib/pages/access_management/manage_bookable_spaces/presentation/widgets/booking_period_widget.dart new file mode 100644 index 00000000..d10afee1 --- /dev/null +++ b/lib/pages/access_management/manage_bookable_spaces/presentation/widgets/booking_period_widget.dart @@ -0,0 +1,122 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:flutter_svg/svg.dart'; +import 'package:syncrow_web/pages/access_management/manage_bookable_spaces/presentation/blocs/non_bookable_spaces_bloc/non_bookaable_spaces_bloc.dart'; +import 'package:syncrow_web/pages/access_management/manage_bookable_spaces/presentation/widgets/time_picker_widget.dart'; +import 'package:syncrow_web/utils/color_manager.dart'; +import 'package:syncrow_web/utils/constants/assets.dart'; +import 'package:syncrow_web/utils/string_utils.dart'; + +class BookingPeriodWidget extends StatelessWidget { + const BookingPeriodWidget({ + super.key, + }); + + @override + Widget build(BuildContext context) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + children: [ + Text( + '* ', + style: Theme.of(context) + .textTheme + .bodyMedium! + .copyWith(color: Colors.red), + ), + const Text('Booking Period'), + ], + ), + Container( + width: 300, + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(12), + color: ColorsManager.graysColor, + ), + child: Row( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + TimePickerWidget( + title: 'Start Time', + onTimePicked: (timePicked) { + if (timePicked == null) { + return; + } + final nonBookableBloc = + context.read(); + + if (nonBookableBloc.endTime != null && + isEndTimeAfterStartTime( + timePicked, nonBookableBloc.endTime!)) { + ScaffoldMessenger.of(context).clearSnackBars(); + ScaffoldMessenger.of(context) + .showSnackBar(const SnackBar( + content: Text( + "You can't choose start Time Before End time"), + duration: Duration(seconds: 2), + backgroundColor: ColorsManager.red, + )); + throw Exception(); + } else { + nonBookableBloc.selectedBookableSpaces.forEach( + (e) => e.spaceConfig!.bookingStartTime = timePicked, + ); + } + }, + ), + const Icon( + Icons.arrow_right_alt, + color: ColorsManager.grayColor, + ), + TimePickerWidget( + title: 'End Time', + onTimePicked: (timePicked) { + if (timePicked == null) { + return; + } + final nonBookableBloc = + context.read(); + if (nonBookableBloc.startTime != null && + isEndTimeAfterStartTime( + nonBookableBloc.startTime!, timePicked)) { + ScaffoldMessenger.of(context).clearSnackBars(); + ScaffoldMessenger.of(context) + .showSnackBar(const SnackBar( + content: Text( + "You can't choose End Time After Start time"), + duration: Duration(seconds: 2), + backgroundColor: ColorsManager.red, + )); + throw Exception(); + } else { + nonBookableBloc.selectedBookableSpaces.forEach( + (e) => e.spaceConfig!.bookingEndTime = timePicked, + ); + } + }, + ), + Container( + width: 50, + height: 32, + decoration: const BoxDecoration( + borderRadius: BorderRadius.only( + topLeft: Radius.circular(10), + bottomLeft: Radius.circular(10), + ), + ), + alignment: Alignment.center, + child: SvgPicture.asset( + Assets.clockIcon, + height: 15, + color: ColorsManager.blackColor.withValues(alpha: 0.4), + ), + ) + ], + ), + ), + ], + ); + } +} diff --git a/lib/pages/access_management/manage_bookable_spaces/presentation/widgets/check_box_space_widget.dart b/lib/pages/access_management/manage_bookable_spaces/presentation/widgets/check_box_space_widget.dart new file mode 100644 index 00000000..937ee35e --- /dev/null +++ b/lib/pages/access_management/manage_bookable_spaces/presentation/widgets/check_box_space_widget.dart @@ -0,0 +1,59 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:syncrow_web/pages/access_management/manage_bookable_spaces/domain/models/bookable_space_model.dart'; +import 'package:syncrow_web/pages/access_management/manage_bookable_spaces/presentation/blocs/non_bookable_spaces_bloc/non_bookaable_spaces_bloc.dart'; + +class CheckBoxSpaceWidget extends StatefulWidget { + final BookableSpacemodel nonBookableSpace; + final List selectedSpaces; + const CheckBoxSpaceWidget({ + super.key, + required this.nonBookableSpace, + required this.selectedSpaces, + }); + + @override + State createState() => _CheckBoxSpaceWidgetState(); +} + +class _CheckBoxSpaceWidgetState extends State { + bool isChecked = false; + @override + void initState() { + isChecked = widget.selectedSpaces.any( + (element) => element.spaceUuid == widget.nonBookableSpace.spaceUuid, + ); + super.initState(); + } + + @override + Widget build(BuildContext context) { + return Row( + children: [ + Checkbox( + value: isChecked, + onChanged: (value) => setState(() { + isChecked = value ?? false; + if (isChecked) { + context.read().add( + AddToBookableSpaceEvent( + nonBookableSpace: widget.nonBookableSpace, + ), + ); + } else { + context.read().add( + RemoveFromBookableSpaceEvent( + bookableSpace: widget.nonBookableSpace, + ), + ); + } + }), + ), + const SizedBox( + width: 5, + ), + Expanded(child: Text(widget.nonBookableSpace.spaceName)), + ], + ); + } +}