no need for selectedbookableSpaces list anymore instead i am using state list

This commit is contained in:
Rafeek-Khoudare
2025-07-22 16:47:50 +03:00
parent b6d4084ca7
commit 6a7174b929
12 changed files with 331 additions and 282 deletions

View File

@ -10,51 +10,123 @@ part 'setup_bookable_spaces_state.dart';
class SetupBookableSpacesBloc class SetupBookableSpacesBloc
extends Bloc<SetupBookableSpacesEvent, SetupBookableSpacesState> { extends Bloc<SetupBookableSpacesEvent, SetupBookableSpacesState> {
NonBookableSpacesService nonBookableSpacesService; NonBookableSpacesService nonBookableSpacesService;
List<BookableSpacemodel> selectedBookableSpaces = [];
SetupBookableSpacesBloc(this.nonBookableSpacesService) SetupBookableSpacesBloc(this.nonBookableSpacesService)
: super(SetupBookableSpacesInitial()) { : super(const SetupBookableSpacesInitial(bookableSpaces: [])) {
on<AddToBookableSpaceEvent>(_onAddToBookableSpaceEvent); on<AddToBookableSpaceEvent>(_onAddToBookableSpaceEvent);
on<RemoveFromBookableSpaceEvent>(_onRemoveFromBookableSpaceEvent); on<RemoveFromBookableSpaceEvent>(_onRemoveFromBookableSpaceEvent);
on<AddBookableDaysEvent>(_onAddBookableDays);
on<ChangeStartTimeEvent>(_onChangeStartTimeEvent);
on<ChangeEndTimeEvent>(_onChangeEndTimeEvent);
on<ChangeCostEvent>(_onChangeCostEvent);
on<CheckConfigurValidityEvent>(_onCheckConfigurValidityEvent); on<CheckConfigurValidityEvent>(_onCheckConfigurValidityEvent);
on<EditModeSelected>(_onEditModeSelected); on<EditModeSelected>(_onEditModeSelected);
} }
TimeOfDay? get endTime => List<BookableSpacemodel> get currentBookableSpaces {
selectedBookableSpaces.first.spaceConfig!.bookingEndTime; return switch (state) {
AddNonBookableSpaceIntoBookableState(:final bookableSpaces) =>
TimeOfDay? get startTime => bookableSpaces,
selectedBookableSpaces.first.spaceConfig!.bookingStartTime; RemoveBookableSpaceIntoNonBookableState(:final bookableSpaces) =>
bookableSpaces,
SetupBookableSpacesInitial(:final bookableSpaces) => bookableSpaces,
InProgressState(:final bookableSpaces) => bookableSpaces,
ValidSaveButtonState(:final bookableSpaces) => bookableSpaces,
UnValidSaveButtonState(:final bookableSpaces) => bookableSpaces,
};
}
void _onAddToBookableSpaceEvent( void _onAddToBookableSpaceEvent(
AddToBookableSpaceEvent event, AddToBookableSpaceEvent event,
Emitter<SetupBookableSpacesState> emit, Emitter<SetupBookableSpacesState> emit,
) { ) {
emit(InProgressState()); emit(InProgressState(bookableSpaces: state.bookableSpaces));
selectedBookableSpaces.add(event.nonBookableSpace); final updatedSpaces = List<BookableSpacemodel>.from(state.bookableSpaces);
emit(AddNonBookableSpaceIntoBookableState(
bookableSpaces: selectedBookableSpaces)); updatedSpaces.add(event.nonBookableSpace);
emit(AddNonBookableSpaceIntoBookableState(bookableSpaces: updatedSpaces));
} }
void _onRemoveFromBookableSpaceEvent(RemoveFromBookableSpaceEvent event, void _onRemoveFromBookableSpaceEvent(RemoveFromBookableSpaceEvent event,
Emitter<SetupBookableSpacesState> emit) { Emitter<SetupBookableSpacesState> emit) {
emit(InProgressState()); emit(InProgressState(bookableSpaces: state.bookableSpaces));
selectedBookableSpaces.remove(event.bookableSpace); state.bookableSpaces.remove(event.bookableSpace);
emit(RemoveBookableSpaceIntoNonBookableState( emit(RemoveBookableSpaceIntoNonBookableState(
bookableSpaces: selectedBookableSpaces)); bookableSpaces: state.bookableSpaces));
}
void _onAddBookableDays(
AddBookableDaysEvent event, Emitter<SetupBookableSpacesState> emit) {
final updatedSpaces = state.bookableSpaces.map((space) {
final updatedConfig = space.spaceConfig?.copyWith(
bookableDays: event.bookableDays,
);
return space.copyWith(spaceConfig: updatedConfig);
}).toList();
emit(SetupBookableSpacesInitial(bookableSpaces: updatedSpaces));
}
void _onChangeStartTimeEvent(
ChangeStartTimeEvent event, Emitter<SetupBookableSpacesState> emit) {
final updatedSpaces = state.bookableSpaces.map((space) {
final updatedConfig = space.spaceConfig?.copyWith(
bookingStartTime: event.startTime,
);
return space.copyWith(spaceConfig: updatedConfig);
}).toList();
emit(SetupBookableSpacesInitial(bookableSpaces: updatedSpaces));
}
void _onChangeEndTimeEvent(
ChangeEndTimeEvent event, Emitter<SetupBookableSpacesState> emit) {
final updatedSpaces = state.bookableSpaces.map((space) {
final updatedConfig = space.spaceConfig?.copyWith(
bookingEndTime: event.endTime,
);
return space.copyWith(spaceConfig: updatedConfig);
}).toList();
emit(SetupBookableSpacesInitial(bookableSpaces: updatedSpaces));
}
void _onChangeCostEvent(
ChangeCostEvent event, Emitter<SetupBookableSpacesState> emit) {
final updatedSpaces = state.bookableSpaces.map((space) {
final updatedConfig = space.spaceConfig?.copyWith(
cost: event.cost,
);
return space.copyWith(spaceConfig: updatedConfig);
}).toList();
emit(SetupBookableSpacesInitial(bookableSpaces: updatedSpaces));
} }
void _onCheckConfigurValidityEvent(CheckConfigurValidityEvent event, void _onCheckConfigurValidityEvent(CheckConfigurValidityEvent event,
Emitter<SetupBookableSpacesState> emit) { Emitter<SetupBookableSpacesState> emit) {
if (selectedBookableSpaces.first.spaceConfig!.isValid) { if (state.bookableSpaces.first.spaceConfig!.isValid) {
emit(ValidSaveButtonState()); emit(ValidSaveButtonState(
bookableSpaces: state.bookableSpaces,
));
} else { } else {
emit(UnValidSaveButtonState()); emit(UnValidSaveButtonState(
bookableSpaces: state.bookableSpaces,
));
} }
} }
void _onEditModeSelected( void _onEditModeSelected(
EditModeSelected event, Emitter<SetupBookableSpacesState> emit) { EditModeSelected event,
selectedBookableSpaces.clear(); Emitter<SetupBookableSpacesState> emit,
selectedBookableSpaces.add(event.editingBookableSpace); ) {
final updatedList = [event.editingBookableSpace];
emit(SetupBookableSpacesInitial(bookableSpaces: updatedList));
} }
} }

View File

@ -21,6 +21,34 @@ class RemoveFromBookableSpaceEvent extends SetupBookableSpacesEvent {
}); });
} }
class AddBookableDaysEvent extends SetupBookableSpacesEvent {
final List<String> bookableDays;
const AddBookableDaysEvent({
required this.bookableDays,
});
}
class ChangeCostEvent extends SetupBookableSpacesEvent {
final int cost;
const ChangeCostEvent({
required this.cost,
});
}
class ChangeStartTimeEvent extends SetupBookableSpacesEvent {
final TimeOfDay startTime;
const ChangeStartTimeEvent({
required this.startTime,
});
}
class ChangeEndTimeEvent extends SetupBookableSpacesEvent {
final TimeOfDay endTime;
const ChangeEndTimeEvent({
required this.endTime,
});
}
class CheckConfigurValidityEvent extends SetupBookableSpacesEvent {} class CheckConfigurValidityEvent extends SetupBookableSpacesEvent {}
class EditModeSelected extends SetupBookableSpacesEvent { class EditModeSelected extends SetupBookableSpacesEvent {

View File

@ -1,32 +1,37 @@
part of 'setup_bookable_spaces_bloc.dart'; part of 'setup_bookable_spaces_bloc.dart';
sealed class SetupBookableSpacesState extends Equatable { sealed class SetupBookableSpacesState extends Equatable {
const SetupBookableSpacesState(); final List<BookableSpacemodel> bookableSpaces;
const SetupBookableSpacesState({required this.bookableSpaces});
TimeOfDay? get startTime =>
bookableSpaces.first.spaceConfig!.bookingStartTime;
TimeOfDay? get endTime => bookableSpaces.first.spaceConfig!.bookingEndTime;
@override @override
List<Object> get props => []; List<Object> get props => [];
} }
final class SetupBookableSpacesInitial extends SetupBookableSpacesState {} final class SetupBookableSpacesInitial extends SetupBookableSpacesState {
const SetupBookableSpacesInitial({required super.bookableSpaces});
}
class AddNonBookableSpaceIntoBookableState extends SetupBookableSpacesState { class AddNonBookableSpaceIntoBookableState extends SetupBookableSpacesState {
final List<BookableSpacemodel> bookableSpaces; const AddNonBookableSpaceIntoBookableState({required super.bookableSpaces});
const AddNonBookableSpaceIntoBookableState({
required this.bookableSpaces,
});
} }
class InProgressState extends SetupBookableSpacesState {} class InProgressState extends SetupBookableSpacesState {
const InProgressState({required super.bookableSpaces});
}
class RemoveBookableSpaceIntoNonBookableState extends SetupBookableSpacesState { class RemoveBookableSpaceIntoNonBookableState extends SetupBookableSpacesState {
final List<BookableSpacemodel> bookableSpaces;
const RemoveBookableSpaceIntoNonBookableState({ const RemoveBookableSpaceIntoNonBookableState({
required this.bookableSpaces, required super.bookableSpaces,
}); });
} }
class ValidSaveButtonState extends SetupBookableSpacesState {} class ValidSaveButtonState extends SetupBookableSpacesState {
const ValidSaveButtonState({required super.bookableSpaces});
class UnValidSaveButtonState extends SetupBookableSpacesState {} }
class UnValidSaveButtonState extends SetupBookableSpacesState {
const UnValidSaveButtonState({required super.bookableSpaces});
}

View File

@ -63,9 +63,10 @@ class _SetupBookableSpacesDialogState extends State<SetupBookableSpacesDialog> {
RemoteNonBookableSpaces(HTTPService())) RemoteNonBookableSpaces(HTTPService()))
: (context) => SetupBookableSpacesBloc( : (context) => SetupBookableSpacesBloc(
RemoteNonBookableSpaces(HTTPService())) RemoteNonBookableSpaces(HTTPService()))
..add(EditModeSelected( ..add(
editingBookableSpace: widget.editingBookableSpace!, EditModeSelected(
)), editingBookableSpace: widget.editingBookableSpace!),
),
), ),
BlocProvider( BlocProvider(
create: (context) => SendBookableSpacesBloc( create: (context) => SendBookableSpacesBloc(
@ -115,16 +116,14 @@ class _SetupBookableSpacesDialogState extends State<SetupBookableSpacesDialog> {
), ),
Builder(builder: (context) { Builder(builder: (context) {
final stepsState = context.watch<StepsCubit>().state; final stepsState = context.watch<StepsCubit>().state;
final setupBookableSpacesBloc = final bookableSpaces =
context.watch<SetupBookableSpacesBloc>(); context.watch<SetupBookableSpacesBloc>().state.bookableSpaces;
final selectedSpaces =
setupBookableSpacesBloc.selectedBookableSpaces;
return stepsState is StepOneState return stepsState is StepOneState
? NextFirstStepButton(selectedSpaces: selectedSpaces) ? const NextFirstStepButton()
: SaveSecondStepButton( : SaveSecondStepButton(
selectedSpaces: selectedSpaces,
pointsController: pointsController, pointsController: pointsController,
isEditingMode: widget.editingBookableSpace != null, isEditingMode: widget.editingBookableSpace != null,
bookableSpaces: bookableSpaces,
); );
}), }),
], ],

View File

@ -17,6 +17,8 @@ class BookingPeriodWidget extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final state = context.watch<SetupBookableSpacesBloc>().state;
return Column( return Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
@ -32,139 +34,108 @@ class BookingPeriodWidget extends StatelessWidget {
const Text('Booking Period'), const Text('Booking Period'),
], ],
), ),
const SizedBox( const SizedBox(height: 5),
height: 5,
),
Container( Container(
width: 230, width: 230,
decoration: BoxDecoration( decoration: BoxDecoration(
borderRadius: BorderRadius.circular(8), borderRadius: BorderRadius.circular(8),
color: ColorsManager.circleRolesBackground, color: ColorsManager.circleRolesBackground,
boxShadow: [ boxShadow: [
BoxShadow( BoxShadow(
offset: Offset.zero, offset: Offset.zero,
blurRadius: 4, blurRadius: 4,
spreadRadius: 0, spreadRadius: 0,
color: ColorsManager.timePickerColor.withValues(alpha: 0.15), color: ColorsManager.timePickerColor.withValues(alpha: 0.15),
) )
]), ],
),
child: Row( child: Row(
crossAxisAlignment: CrossAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center,
children: [ children: [
TimePickerWidget( TimePickerWidget(
title: editingBookableSpace == null title: editingBookableSpace?.spaceConfig?.bookingStartTime
? 'Start Time' ?.format(context) ??
: editingBookableSpace!.spaceConfig!.bookingStartTime! 'Start Time',
.format(context), onTimePicked: (pickedStartTime) {
onTimePicked: (timePicked) { if (pickedStartTime == null) return;
if (timePicked == null) {
if (state.endTime != null &&
isEndTimeAfterStartTime(
pickedStartTime, state.endTime!)) {
_showInvalidSnackBar(
context, "You can't choose Start Time after End Time");
return; return;
} }
final setupBookableSpacesBloc =
context.read<SetupBookableSpacesBloc>();
if (setupBookableSpacesBloc.endTime != null && context.read<SetupBookableSpacesBloc>().add(
isEndTimeAfterStartTime( ChangeStartTimeEvent(startTime: pickedStartTime),
timePicked, setupBookableSpacesBloc.endTime!)) { );
ScaffoldMessenger.of(context).clearSnackBars(); context.read<SetupBookableSpacesBloc>().add(
ScaffoldMessenger.of(context).showSnackBar(const SnackBar( CheckConfigurValidityEvent(),
content: );
Text("You can't choose start Time Before End time"),
duration: Duration(seconds: 2),
backgroundColor: ColorsManager.red,
));
throw Exception();
} else {
for (int i = 0;
i <
setupBookableSpacesBloc
.selectedBookableSpaces.length;
i++) {
final space =
setupBookableSpacesBloc.selectedBookableSpaces[i];
final updatedConfig = space.spaceConfig
?.copyWith(bookingStartTime: timePicked);
final updatedSpace =
space.copyWith(spaceConfig: updatedConfig);
setupBookableSpacesBloc.selectedBookableSpaces[i] =
updatedSpace;
}
}
}, },
), ),
const SizedBox( const SizedBox(width: 10),
width: 10,
),
const Icon( const Icon(
Icons.arrow_right_alt, Icons.arrow_right_alt,
color: ColorsManager.grayColor, color: ColorsManager.grayColor,
size: 13, size: 13,
), ),
TimePickerWidget( TimePickerWidget(
title: editingBookableSpace == null title: editingBookableSpace?.spaceConfig?.bookingEndTime
? 'End Time' ?.format(context) ??
: editingBookableSpace!.spaceConfig!.bookingEndTime! 'End Time',
.format(context), onTimePicked: (pickedEndTime) {
onTimePicked: (timePicked) { if (pickedEndTime == null) return;
if (timePicked == null) {
if (state.startTime != null &&
isEndTimeAfterStartTime(
state.startTime!, pickedEndTime)) {
_showInvalidSnackBar(
context, "You can't choose End Time before Start Time");
return; return;
} }
final setupBookableSpacesBloc =
context.read<SetupBookableSpacesBloc>();
if (setupBookableSpacesBloc.startTime != null &&
isEndTimeAfterStartTime(
setupBookableSpacesBloc.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 {
for (int i = 0;
i <
setupBookableSpacesBloc
.selectedBookableSpaces.length;
i++) {
final space =
setupBookableSpacesBloc.selectedBookableSpaces[i];
final updatedConfig = space.spaceConfig
?.copyWith(bookingEndTime: timePicked);
final updatedSpace =
space.copyWith(spaceConfig: updatedConfig);
setupBookableSpacesBloc.selectedBookableSpaces[i] = context.read<SetupBookableSpacesBloc>().add(
updatedSpace; ChangeEndTimeEvent(endTime: pickedEndTime),
} );
} context.read<SetupBookableSpacesBloc>().add(
CheckConfigurValidityEvent(),
);
}, },
), ),
const SizedBox( const SizedBox(width: 15),
width: 15,
),
Container( Container(
width: 30, width: 30,
height: 32, height: 32,
alignment: Alignment.center,
decoration: const BoxDecoration( decoration: const BoxDecoration(
borderRadius: BorderRadius.only( borderRadius: BorderRadius.only(
topLeft: Radius.circular(10), topLeft: Radius.circular(10),
bottomLeft: Radius.circular(10), bottomLeft: Radius.circular(10),
), ),
), ),
alignment: Alignment.center,
child: SvgPicture.asset( child: SvgPicture.asset(
Assets.clockIcon, Assets.clockIcon,
height: 18, height: 18,
color: ColorsManager.blackColor.withValues(alpha: 0.4), color: ColorsManager.blackColor.withValues(alpha: 0.4),
), ),
) ),
], ],
), ),
), ),
], ],
); );
} }
void _showInvalidSnackBar(BuildContext context, String message) {
ScaffoldMessenger.of(context).clearSnackBars();
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(message),
duration: const Duration(seconds: 2),
backgroundColor: ColorsManager.red,
),
);
}
} }

View File

@ -7,12 +7,10 @@ import 'package:syncrow_web/utils/color_manager.dart';
class CheckBoxSpaceWidget extends StatelessWidget { class CheckBoxSpaceWidget extends StatelessWidget {
final BookableSpacemodel nonBookableSpace; final BookableSpacemodel nonBookableSpace;
final List<BookableSpacemodel> selectedSpaces;
const CheckBoxSpaceWidget({ const CheckBoxSpaceWidget({
super.key, super.key,
required this.nonBookableSpace, required this.nonBookableSpace,
required this.selectedSpaces,
}); });
@override @override
@ -37,12 +35,15 @@ class CheckBoxSpaceWidget extends StatelessWidget {
value: isChecked, value: isChecked,
onChanged: (value) { onChanged: (value) {
final bloc = context.read<SetupBookableSpacesBloc>(); final bloc = context.read<SetupBookableSpacesBloc>();
if (value ?? false) { if (value ?? false) {
bloc.add(AddToBookableSpaceEvent( bloc.add(AddToBookableSpaceEvent(
nonBookableSpace: nonBookableSpace)); nonBookableSpace: nonBookableSpace,
));
} else { } else {
bloc.add(RemoveFromBookableSpaceEvent( bloc.add(RemoveFromBookableSpaceEvent(
bookableSpace: nonBookableSpace)); bookableSpace: nonBookableSpace,
));
} }
}, },
); );

View File

@ -1,32 +1,42 @@
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:go_router/go_router.dart'; import 'package:go_router/go_router.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/setup_bookable_spaces_bloc/setup_bookable_spaces_bloc.dart'; import 'package:syncrow_web/pages/access_management/manage_bookable_spaces/presentation/blocs/setup_bookable_spaces_bloc/setup_bookable_spaces_bloc.dart';
import 'package:syncrow_web/pages/access_management/manage_bookable_spaces/presentation/blocs/steps_cubit/cubit/steps_cubit.dart'; import 'package:syncrow_web/pages/access_management/manage_bookable_spaces/presentation/blocs/steps_cubit/cubit/steps_cubit.dart';
import 'package:syncrow_web/pages/access_management/manage_bookable_spaces/presentation/widgets/buttons_divider_bottom_dialog_widget.dart'; import 'package:syncrow_web/pages/access_management/manage_bookable_spaces/presentation/widgets/buttons_divider_bottom_dialog_widget.dart';
class NextFirstStepButton extends StatelessWidget { class NextFirstStepButton extends StatelessWidget {
final List<BookableSpacemodel> selectedSpaces;
const NextFirstStepButton({ const NextFirstStepButton({
super.key, super.key,
required this.selectedSpaces,
}); });
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return ButtonsDividerBottomDialogWidget( return BlocBuilder<SetupBookableSpacesBloc, SetupBookableSpacesState>(
title: 'Next', builder: (context, state) {
onNextPressed: selectedSpaces.isEmpty return switch (state) {
? null SetupBookableSpacesInitial() => ButtonsDividerBottomDialogWidget(
: () { title: 'Next',
context.read<StepsCubit>().goToNextStep(); onNextPressed: null,
context onCancelPressed: () => context.pop(),
.read<SetupBookableSpacesBloc>() ),
.add(CheckConfigurValidityEvent()); AddNonBookableSpaceIntoBookableState(:final bookableSpaces) ||
}, RemoveBookableSpaceIntoNonBookableState(:final bookableSpaces) =>
onCancelPressed: () => context.pop(), ButtonsDividerBottomDialogWidget(
title: 'Next',
onNextPressed: bookableSpaces.isEmpty
? null
: () {
context.read<StepsCubit>().goToNextStep();
context.read<SetupBookableSpacesBloc>().add(
CheckConfigurValidityEvent(),
);
},
onCancelPressed: () => context.pop(),
),
_ => const SizedBox(),
};
},
); );
} }
} }

View File

@ -9,14 +9,14 @@ import 'package:syncrow_web/utils/color_manager.dart';
class PointsPartWidget extends StatefulWidget { class PointsPartWidget extends StatefulWidget {
final BookableSpacemodel? editingBookableSpace; final BookableSpacemodel? editingBookableSpace;
final TextEditingController pointsController;
const PointsPartWidget({ const PointsPartWidget({
super.key, super.key,
required this.pointsController, required this.pointsController,
this.editingBookableSpace, this.editingBookableSpace,
}); });
final TextEditingController pointsController;
@override @override
State<PointsPartWidget> createState() => _PointsPartWidgetState(); State<PointsPartWidget> createState() => _PointsPartWidgetState();
} }
@ -24,26 +24,28 @@ class PointsPartWidget extends StatefulWidget {
class _PointsPartWidgetState extends State<PointsPartWidget> { class _PointsPartWidgetState extends State<PointsPartWidget> {
@override @override
void initState() { void initState() {
super.initState();
if (widget.editingBookableSpace != null) { if (widget.editingBookableSpace != null) {
widget.pointsController.text = widget.pointsController.text =
widget.editingBookableSpace!.spaceConfig!.cost.toString(); widget.editingBookableSpace!.spaceConfig!.cost.toString();
} }
super.initState();
} }
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return BlocBuilder<TogglePointsSwitchCubit, TogglePointsSwitchState>( return BlocBuilder<TogglePointsSwitchCubit, TogglePointsSwitchState>(
builder: (context, state) { builder: (context, switchState) {
final isSwitchOn = switchState is ActivatePointsSwitch;
return Column( return Column(
children: [ children: [
Row( Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [ children: [
Row( Row(
mainAxisAlignment: MainAxisAlignment.start,
children: [ children: [
if (state is ActivatePointsSwitch) if (isSwitchOn)
Text( Text(
'* ', '* ',
style: Theme.of(context) style: Theme.of(context)
@ -52,9 +54,7 @@ class _PointsPartWidgetState extends State<PointsPartWidget> {
.copyWith(color: Colors.red), .copyWith(color: Colors.red),
) )
else else
const SizedBox( const SizedBox(width: 11),
width: 11,
),
const Text('Points/hrs'), const Text('Points/hrs'),
], ],
), ),
@ -62,83 +62,54 @@ class _PointsPartWidgetState extends State<PointsPartWidget> {
scale: 0.7, scale: 0.7,
child: Switch( child: Switch(
materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
trackOutlineColor: WidgetStateProperty.resolveWith<Color>( trackOutlineColor:
(Set<WidgetState> states) { WidgetStateProperty.all(ColorsManager.whiteColors),
return ColorsManager.whiteColors;
},
),
activeTrackColor: ColorsManager.dialogBlueTitle, activeTrackColor: ColorsManager.dialogBlueTitle,
inactiveTrackColor: ColorsManager.lightGrayBorderColor, inactiveTrackColor: ColorsManager.lightGrayBorderColor,
thumbColor: WidgetStateProperty.resolveWith<Color>( thumbColor:
(Set<WidgetState> states) { WidgetStateProperty.all(ColorsManager.whiteColors),
return ColorsManager.whiteColors; value: isSwitchOn,
},
),
value: state is ActivatePointsSwitch,
onChanged: (value) { onChanged: (value) {
final toggleCubit =
context.read<TogglePointsSwitchCubit>();
final bloc = context.read<SetupBookableSpacesBloc>(); final bloc = context.read<SetupBookableSpacesBloc>();
final updatedCost = value ? -1 : 0; final updatedCost = value ? -1 : 0;
final switchCubit =
context.read<TogglePointsSwitchCubit>();
if (value) { if (value) {
switchCubit.activateSwitch(); toggleCubit.activateSwitch();
} else { } else {
switchCubit.unActivateSwitch(); toggleCubit.unActivateSwitch();
widget.pointsController.clear(); widget.pointsController.clear();
} }
bloc.add(ChangeCostEvent(cost: updatedCost));
for (int i = 0;
i < bloc.selectedBookableSpaces.length;
i++) {
final space = bloc.selectedBookableSpaces[i];
final updatedConfig =
space.spaceConfig?.copyWith(cost: updatedCost);
final updatedSpace =
space.copyWith(spaceConfig: updatedConfig);
bloc.selectedBookableSpaces[i] = updatedSpace;
}
bloc.add(CheckConfigurValidityEvent()); bloc.add(CheckConfigurValidityEvent());
}, },
), ),
) ),
], ],
), ),
const SizedBox( const SizedBox(height: 5),
height: 5, if (isSwitchOn)
),
if (state is ActivatePointsSwitch)
SearchUnbookableSpacesWidget( SearchUnbookableSpacesWidget(
title: 'Ex: 0', title: 'Ex: 0',
topPadding: 0, topPadding: 0,
blur: 1, blur: 1,
raduis: 10, raduis: 10,
height: 34, height: 34,
onChanged: (p0) { controller: widget.pointsController,
suffix: const SizedBox(),
inputFormatters: [FilteringTextInputFormatter.digitsOnly],
onChanged: (_) {
final updatedCost = final updatedCost =
int.tryParse(widget.pointsController.text) ?? 0; int.tryParse(widget.pointsController.text) ?? 0;
final bloc = context.read<SetupBookableSpacesBloc>();
for (var i = 0; i < bloc.selectedBookableSpaces.length; i++) {
final space = bloc.selectedBookableSpaces[i];
final updatedConfig =
space.spaceConfig?.copyWith(cost: updatedCost);
final updatedSpace =
space.copyWith(spaceConfig: updatedConfig);
bloc.selectedBookableSpaces[i] = updatedSpace;
}
context context
.read<SetupBookableSpacesBloc>() .read<SetupBookableSpacesBloc>()
.add(CheckConfigurValidityEvent()); .add(ChangeCostEvent(cost: updatedCost));
context.read<SetupBookableSpacesBloc>().add(
CheckConfigurValidityEvent(),
);
}, },
controller: widget.pointsController,
inputFormatters: [FilteringTextInputFormatter.digitsOnly],
suffix: const SizedBox(),
) )
else else
const SizedBox(), const SizedBox(),

View File

@ -10,68 +10,68 @@ import 'package:syncrow_web/pages/access_management/manage_bookable_spaces/prese
import 'package:syncrow_web/pages/access_management/manage_bookable_spaces/presentation/widgets/buttons_divider_bottom_dialog_widget.dart'; import 'package:syncrow_web/pages/access_management/manage_bookable_spaces/presentation/widgets/buttons_divider_bottom_dialog_widget.dart';
class SaveSecondStepButton extends StatelessWidget { class SaveSecondStepButton extends StatelessWidget {
final List<BookableSpacemodel> selectedSpaces;
final TextEditingController pointsController; final TextEditingController pointsController;
final bool isEditingMode; final bool isEditingMode;
final List<BookableSpacemodel> bookableSpaces;
const SaveSecondStepButton({ const SaveSecondStepButton({
super.key, super.key,
required this.selectedSpaces,
required this.pointsController, required this.pointsController,
required this.isEditingMode, required this.isEditingMode,
required this.bookableSpaces,
}); });
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return BlocConsumer<SendBookableSpacesBloc, SendBookableSpacesState>( return BlocListener<SendBookableSpacesBloc, SendBookableSpacesState>(
listener: (context, state) { listener: (context, state) {
if (state is SendBookableSpacesSuccess) { if (state is SendBookableSpacesSuccess) {
context.read<NonBookableSpacesBloc>().add(CallInitStateEvent()); context.read<NonBookableSpacesBloc>().add(CallInitStateEvent());
} else if (state is SendBookableSpacesError) { } else if (state is SendBookableSpacesError) {
ScaffoldMessenger.of(context).showSnackBar( ScaffoldMessenger.of(context).showSnackBar(
SnackBar( SnackBar(content: Text(state.error)),
content: Text(state.error),
),
); );
} }
}, },
builder: (context, state) { child: BlocBuilder<SetupBookableSpacesBloc, SetupBookableSpacesState>(
return ButtonsDividerBottomDialogWidget( builder: (context, state) {
title: 'Save', return ButtonsDividerBottomDialogWidget(
onNextPressed: state is UnValidSaveButtonState title: 'Save',
? null onNextPressed: state is UnValidSaveButtonState
: () { ? null
if (selectedSpaces.any( : () {
(element) => element.isValid, if (bookableSpaces.any((e) => e.isValid)) {
)) { if (isEditingMode) {
isEditingMode callEditLogic(context);
? callEditLogic(context) } else {
: context.read<SendBookableSpacesBloc>().add( context.read<SendBookableSpacesBloc>().add(
SendBookableSpacesToApi( SendBookableSpacesToApi(
selectedBookableSpaces: context selectedBookableSpaces: bookableSpaces,
.read<SetupBookableSpacesBloc>() ),
.selectedBookableSpaces),
); );
} }
}, }
onCancelPressed: () => context.pop(), },
); onCancelPressed: () => context.pop(),
}, );
},
),
); );
} }
void callEditLogic(BuildContext context) { void callEditLogic(BuildContext context) {
context.read<UpdateBookableSpacesBloc>().add( print(bookableSpaces.first.spaceConfig!.cost);
UpdateBookableSpace( if (bookableSpaces.isNotEmpty) {
onSuccess: () => context.read<UpdateBookableSpacesBloc>().add(
context.read<NonBookableSpacesBloc>().add(CallInitStateEvent()), UpdateBookableSpace(
updatedParam: UpdateBookableSpaceParam.fromBookableModel( onSuccess: () => context
context .read<NonBookableSpacesBloc>()
.read<SetupBookableSpacesBloc>() .add(CallInitStateEvent()),
.selectedBookableSpaces updatedParam: UpdateBookableSpaceParam.fromBookableModel(
.first, bookableSpaces.first,
),
), ),
), );
); }
} }
} }

View File

@ -12,7 +12,7 @@ class TimePickerWidget extends StatefulWidget {
required this.onTimePicked, required this.onTimePicked,
required this.title, required this.title,
}); });
late SetupBookableSpacesBloc setupBookableSpacesBloc; late final SetupBookableSpacesBloc setupBookableSpacesBloc;
final void Function(TimeOfDay? timePicked) onTimePicked; final void Function(TimeOfDay? timePicked) onTimePicked;
@override @override
State<TimePickerWidget> createState() => _TimePickerWidgetState(); State<TimePickerWidget> createState() => _TimePickerWidgetState();
@ -47,9 +47,14 @@ class _TimePickerWidgetState extends State<TimePickerWidget> {
); );
}, },
); );
if (tempTime == null) return;
widget.onTimePicked(tempTime); widget.onTimePicked(tempTime);
timePicked = tempTime; timePicked = tempTime;
widget.setupBookableSpacesBloc.add(CheckConfigurValidityEvent()); widget.setupBookableSpacesBloc.add(CheckConfigurValidityEvent());
setState(() {}); setState(() {});
}, },
child: Container( child: Container(

View File

@ -36,9 +36,7 @@ class UnbookableListWidget extends StatelessWidget {
if (index < nonBookableSpaces.data.length) { if (index < nonBookableSpaces.data.length) {
return CheckBoxSpaceWidget( return CheckBoxSpaceWidget(
nonBookableSpace: nonBookableSpaces.data[index], nonBookableSpace: nonBookableSpaces.data[index],
selectedSpaces: context
.read<SetupBookableSpacesBloc>()
.selectedBookableSpaces,
); );
} else { } else {
return const Padding( return const Padding(

View File

@ -25,6 +25,7 @@ class _WeekDaysCheckboxRowState extends State<WeekDaysCheckboxRow> {
'Sat': false, 'Sat': false,
'Sun': false, 'Sun': false,
}; };
@override @override
void initState() { void initState() {
super.initState(); super.initState();
@ -56,9 +57,7 @@ class _WeekDaysCheckboxRowState extends State<WeekDaysCheckboxRow> {
const Text('Days'), const Text('Days'),
], ],
), ),
const SizedBox( const SizedBox(height: 20),
height: 20,
),
Row( Row(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: _daysChecked.entries.map((entry) { children: _daysChecked.entries.map((entry) {
@ -79,34 +78,24 @@ class _WeekDaysCheckboxRowState extends State<WeekDaysCheckboxRow> {
.map((e) => e.key) .map((e) => e.key)
.toList(); .toList();
final bloc = context.read<SetupBookableSpacesBloc>(); context.read<SetupBookableSpacesBloc>().add(
AddBookableDaysEvent(bookableDays: selectedDays),
for (int i = 0; );
i < bloc.selectedBookableSpaces.length; context.read<SetupBookableSpacesBloc>().add(
i++) { CheckConfigurValidityEvent(),
final space = bloc.selectedBookableSpaces[i]; );
final updatedConfig = space.spaceConfig
?.copyWith(bookableDays: selectedDays);
final updatedSpace =
space.copyWith(spaceConfig: updatedConfig);
bloc.selectedBookableSpaces[i] = updatedSpace;
}
bloc.add(CheckConfigurValidityEvent());
}, },
), ),
const SizedBox( const SizedBox(width: 8),
width: 8,
),
Expanded( Expanded(
child: Text( child: Text(
entry.key, entry.key,
style: const TextStyle( style: const TextStyle(
fontSize: 13, fontSize: 13,
fontWeight: FontWeight.w400, fontWeight: FontWeight.w400,
),
), ),
)), ),
], ],
), ),
); );