add settings and edit feature to bookable spaces

This commit is contained in:
Rafeek-Khoudare
2025-07-15 15:17:43 +03:00
parent a9895f5462
commit e9b4d35f97
22 changed files with 255 additions and 55 deletions

View File

@ -2,7 +2,7 @@ import 'package:dio/dio.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/domain/models/bookable_space_model.dart';
import 'package:syncrow_web/pages/access_management/manage_bookable_spaces/domain/params/non_bookable_spaces_params.dart'; import 'package:syncrow_web/pages/access_management/manage_bookable_spaces/domain/params/non_bookable_spaces_params.dart';
import 'package:syncrow_web/pages/access_management/manage_bookable_spaces/domain/service/non_bookable_spaces_service.dart'; import 'package:syncrow_web/pages/access_management/manage_bookable_spaces/domain/service/non_bookable_spaces_service.dart';
import 'package:syncrow_web/pages/access_management/manage_bookable_spaces/domain/service/send_bookable_spaces_to_api_params.dart'; import 'package:syncrow_web/pages/access_management/manage_bookable_spaces/domain/params/send_bookable_spaces_to_api_params.dart';
import 'package:syncrow_web/pages/space_management_v2/main_module/shared/models/paginated_data_model.dart'; import 'package:syncrow_web/pages/space_management_v2/main_module/shared/models/paginated_data_model.dart';
import 'package:syncrow_web/services/api/api_exception.dart'; import 'package:syncrow_web/services/api/api_exception.dart';
import 'package:syncrow_web/services/api/http_service.dart'; import 'package:syncrow_web/services/api/http_service.dart';

View File

@ -26,8 +26,8 @@ class BookableSpaceConfig {
configUuid: json['uuid'] as String, configUuid: json['uuid'] as String,
bookableDays: (json['daysAvailable'] as List).cast<String>(), bookableDays: (json['daysAvailable'] as List).cast<String>(),
availability: (json['active'] as bool?) ?? false, availability: (json['active'] as bool?) ?? false,
bookingEndTime: parseTimeOfDay(json['startTime'] as String), bookingStartTime: parseTimeOfDay(json['startTime'] as String),
bookingStartTime: parseTimeOfDay(json['endTime'] as String), bookingEndTime: parseTimeOfDay(json['endTime'] as String),
cost: json['points'] as int, cost: json['points'] as int,
); );

View File

@ -0,0 +1,41 @@
import 'package:syncrow_web/pages/access_management/manage_bookable_spaces/domain/models/bookable_space_model.dart';
import 'package:syncrow_web/utils/string_utils.dart';
class SendBookableSpacesToApiParams {
List<String> spaceUuids;
List<String> daysAvailable;
String startTime;
String endTime;
int points;
SendBookableSpacesToApiParams({
required this.spaceUuids,
required this.daysAvailable,
required this.startTime,
required this.endTime,
required this.points,
});
static SendBookableSpacesToApiParams fromBookableSpacesModel(
List<BookableSpacemodel> bookableSpaces) {
return SendBookableSpacesToApiParams(
spaceUuids: bookableSpaces.map((space) => space.spaceUuid).toList(),
daysAvailable: bookableSpaces
.expand((space) => space.spaceConfig!.bookableDays)
.toSet()
.toList(),
startTime: formatTimeOfDayTo24HourString(
bookableSpaces.first.spaceConfig!.bookingStartTime!),
endTime: formatTimeOfDayTo24HourString(
bookableSpaces.first.spaceConfig!.bookingEndTime!),
points: bookableSpaces.first.spaceConfig!.cost,
);
}
Map<String, dynamic> toJson() => {
'spaceUuids': spaceUuids,
'daysAvailable': daysAvailable,
'startTime': startTime,
'endTime': endTime,
'points': points
};
}

View File

@ -1,3 +1,7 @@
import 'package:flutter/foundation.dart';
import 'package:syncrow_web/pages/access_management/manage_bookable_spaces/domain/models/bookable_space_model.dart';
import 'package:syncrow_web/utils/string_utils.dart';
class UpdateBookableSpaceParam { class UpdateBookableSpaceParam {
String spaceUuid; String spaceUuid;
@ -14,6 +18,20 @@ class UpdateBookableSpaceParam {
this.availability, this.availability,
this.cost, this.cost,
}); });
factory UpdateBookableSpaceParam.fromBookableModel(
BookableSpacemodel bookableSpace) {
return UpdateBookableSpaceParam(
spaceUuid: bookableSpace.spaceUuid,
availability: bookableSpace.spaceConfig!.availability,
bookableDays: bookableSpace.spaceConfig!.bookableDays,
cost: bookableSpace.spaceConfig!.cost,
bookingStartTime: formatTimeOfDayTo24HourString(
bookableSpace.spaceConfig!.bookingStartTime!),
bookingEndTime: formatTimeOfDayTo24HourString(
bookableSpace.spaceConfig!.bookingEndTime!),
);
}
Map<String, dynamic> toJson() => { Map<String, dynamic> toJson() => {
if (bookableDays != null) 'daysAvailable': bookableDays, if (bookableDays != null) 'daysAvailable': bookableDays,
if (bookingStartTime != null) 'startTime': bookingStartTime, if (bookingStartTime != null) 'startTime': bookingStartTime,

View File

@ -1,6 +1,6 @@
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/domain/models/bookable_space_model.dart';
import 'package:syncrow_web/pages/access_management/manage_bookable_spaces/domain/params/non_bookable_spaces_params.dart'; import 'package:syncrow_web/pages/access_management/manage_bookable_spaces/domain/params/non_bookable_spaces_params.dart';
import 'package:syncrow_web/pages/access_management/manage_bookable_spaces/domain/service/send_bookable_spaces_to_api_params.dart'; import 'package:syncrow_web/pages/access_management/manage_bookable_spaces/domain/params/send_bookable_spaces_to_api_params.dart';
import 'package:syncrow_web/pages/space_management_v2/main_module/shared/models/paginated_data_model.dart'; import 'package:syncrow_web/pages/space_management_v2/main_module/shared/models/paginated_data_model.dart';
abstract class NonBookableSpacesService { abstract class NonBookableSpacesService {

View File

@ -3,8 +3,8 @@ import 'package:equatable/equatable.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.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/domain/models/bookable_space_model.dart';
import 'package:syncrow_web/pages/access_management/manage_bookable_spaces/domain/params/non_bookable_spaces_params.dart'; import 'package:syncrow_web/pages/access_management/manage_bookable_spaces/domain/params/non_bookable_spaces_params.dart';
import 'package:syncrow_web/pages/access_management/manage_bookable_spaces/domain/params/send_bookable_spaces_to_api_params.dart';
import 'package:syncrow_web/pages/access_management/manage_bookable_spaces/domain/service/non_bookable_spaces_service.dart'; import 'package:syncrow_web/pages/access_management/manage_bookable_spaces/domain/service/non_bookable_spaces_service.dart';
import 'package:syncrow_web/pages/access_management/manage_bookable_spaces/domain/service/send_bookable_spaces_to_api_params.dart';
import 'package:syncrow_web/pages/space_management_v2/main_module/shared/models/paginated_data_model.dart'; import 'package:syncrow_web/pages/space_management_v2/main_module/shared/models/paginated_data_model.dart';
part 'non_bookaable_spaces_event.dart'; part 'non_bookaable_spaces_event.dart';
@ -16,11 +16,13 @@ class NonBookableSpacesBloc
List<BookableSpacemodel> selectedBookableSpaces = []; List<BookableSpacemodel> selectedBookableSpaces = [];
NonBookableSpacesBloc(this.nonBookableSpacesService) NonBookableSpacesBloc(this.nonBookableSpacesService)
: super(NonBookableSpacesInitial()) { : super(NonBookableSpacesInitial()) {
on<CallInitStateEvent>(_onCallInitStateEvent);
on<LoadUnBookableSpacesEvent>(_onLoadUnBookableSpacesEvent); on<LoadUnBookableSpacesEvent>(_onLoadUnBookableSpacesEvent);
on<AddToBookableSpaceEvent>(_onAddToBookableSpaceEvent); on<AddToBookableSpaceEvent>(_onAddToBookableSpaceEvent);
on<RemoveFromBookableSpaceEvent>(_onRemoveFromBookableSpaceEvent); on<RemoveFromBookableSpaceEvent>(_onRemoveFromBookableSpaceEvent);
on<SendBookableSpacesToApi>(_onSendBookableSpacesToApi); on<SendBookableSpacesToApi>(_onSendBookableSpacesToApi);
on<CheckConfigurValidityEvent>(_onCheckConfigurValidityEvent); on<CheckConfigurValidityEvent>(_onCheckConfigurValidityEvent);
on<EditModeSelected>(_onEditModeSelected);
} }
TimeOfDay? get endTime => TimeOfDay? get endTime =>
@ -28,6 +30,12 @@ class NonBookableSpacesBloc
TimeOfDay? get startTime => TimeOfDay? get startTime =>
selectedBookableSpaces.first.spaceConfig!.bookingStartTime; selectedBookableSpaces.first.spaceConfig!.bookingStartTime;
void _onCallInitStateEvent(
CallInitStateEvent event, Emitter<NonBookableSpacesState> emit) {
emit(NonBookableSpacesInitial());
}
Future<void> _onLoadUnBookableSpacesEvent(LoadUnBookableSpacesEvent event, Future<void> _onLoadUnBookableSpacesEvent(LoadUnBookableSpacesEvent event,
Emitter<NonBookableSpacesState> emit) async { Emitter<NonBookableSpacesState> emit) async {
if (state is NonBookableSpacesLoaded) { if (state is NonBookableSpacesLoaded) {
@ -117,7 +125,7 @@ class NonBookableSpacesBloc
selectedBookableSpaces, selectedBookableSpaces,
), ),
); );
emit(NonBookableSpacesInitial()); add(CallInitStateEvent());
} catch (e) { } catch (e) {
emit( emit(
NonBookableSpacesError(e.toString()), NonBookableSpacesError(e.toString()),
@ -133,4 +141,10 @@ class NonBookableSpacesBloc
emit(UnValidSaveButtonState()); emit(UnValidSaveButtonState());
} }
} }
void _onEditModeSelected(
EditModeSelected event, Emitter<NonBookableSpacesState> emit) {
selectedBookableSpaces.clear();
selectedBookableSpaces.add(event.editingBookableSpace);
}
} }

View File

@ -7,6 +7,8 @@ sealed class NonBookableSpacesEvent extends Equatable {
List<Object> get props => []; List<Object> get props => [];
} }
class CallInitStateEvent extends NonBookableSpacesEvent {}
class LoadUnBookableSpacesEvent extends NonBookableSpacesEvent { class LoadUnBookableSpacesEvent extends NonBookableSpacesEvent {
final NonBookableSpacesParams nonBookableSpacesParams; final NonBookableSpacesParams nonBookableSpacesParams;
const LoadUnBookableSpacesEvent({ const LoadUnBookableSpacesEvent({
@ -31,3 +33,10 @@ class RemoveFromBookableSpaceEvent extends NonBookableSpacesEvent {
class SendBookableSpacesToApi extends NonBookableSpacesEvent {} class SendBookableSpacesToApi extends NonBookableSpacesEvent {}
class CheckConfigurValidityEvent extends NonBookableSpacesEvent {} class CheckConfigurValidityEvent extends NonBookableSpacesEvent {}
class EditModeSelected extends NonBookableSpacesEvent {
final BookableSpacemodel editingBookableSpace;
const EditModeSelected({
required this.editingBookableSpace,
});
}

View File

@ -10,6 +10,10 @@ class StepsCubit extends Cubit<StepsState> {
emit(StepOneState()); emit(StepOneState());
} }
void editValueInit() {
emit(StepTwoState());
}
void goToNextStep() { void goToNextStep() {
if (state is StepOneState) { if (state is StepOneState) {
emit(StepTwoState()); emit(StepTwoState());

View File

@ -13,4 +13,3 @@ final class StepOneState extends StepsState {}
final class StepTwoState extends StepsState {} final class StepTwoState extends StepsState {}
final class StepEditMode extends StepsState {}

View File

@ -24,6 +24,7 @@ class UpdateBookableSpacesBloc
await updateBookableSpaceService.update(event.updatedParams); await updateBookableSpaceService.update(event.updatedParams);
emit(UpdateBookableSpaceSuccess(bookableSpaceConfig: updatedSpace)); emit(UpdateBookableSpaceSuccess(bookableSpaceConfig: updatedSpace));
event.onSuccess?.call();
} on APIException catch (e) { } on APIException catch (e) {
emit(UpdateBookableSpaceFailure(error: e.message)); emit(UpdateBookableSpaceFailure(error: e.message));
} catch (e) { } catch (e) {

View File

@ -8,8 +8,10 @@ sealed class UpdateBookableSpaceEvent extends Equatable {
} }
class UpdateBookableSpace extends UpdateBookableSpaceEvent { class UpdateBookableSpace extends UpdateBookableSpaceEvent {
final void Function()? onSuccess;
final UpdateBookableSpaceParam updatedParams; final UpdateBookableSpaceParam updatedParams;
const UpdateBookableSpace({ const UpdateBookableSpace({
required this.updatedParams, required this.updatedParams,
this.onSuccess,
}); });
} }

View File

@ -1,6 +1,7 @@
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/access_management/manage_bookable_spaces/data/remote_non_bookable_spaces.dart'; import 'package:syncrow_web/pages/access_management/manage_bookable_spaces/data/remote_non_bookable_spaces.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/domain/params/non_bookable_spaces_params.dart'; import 'package:syncrow_web/pages/access_management/manage_bookable_spaces/domain/params/non_bookable_spaces_params.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/blocs/non_bookable_spaces_bloc/non_bookaable_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';
@ -13,23 +14,36 @@ import 'package:syncrow_web/utils/color_manager.dart';
class SetupBookableSpacesDialog extends StatelessWidget { class SetupBookableSpacesDialog extends StatelessWidget {
final TextEditingController pointsController = TextEditingController(); final TextEditingController pointsController = TextEditingController();
SetupBookableSpacesDialog({super.key}); final BookableSpacemodel? editingBookableSpace;
SetupBookableSpacesDialog({
super.key,
this.editingBookableSpace,
});
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return MultiBlocProvider( return MultiBlocProvider(
providers: [ providers: [
BlocProvider<StepsCubit>( BlocProvider<StepsCubit>(
create: (context) => StepsCubit()..initDialogValue(), create: editingBookableSpace == null
? (context) => StepsCubit()..initDialogValue()
: (context) => StepsCubit()..editValueInit(),
), ),
BlocProvider<NonBookableSpacesBloc>( BlocProvider<NonBookableSpacesBloc>(
create: (context) => NonBookableSpacesBloc( create: editingBookableSpace == null
RemoteNonBookableSpaces(HTTPService()), ? (context) => NonBookableSpacesBloc(
)..add( RemoteNonBookableSpaces(HTTPService()),
LoadUnBookableSpacesEvent( )..add(
nonBookableSpacesParams: LoadUnBookableSpacesEvent(
NonBookableSpacesParams(currentPage: 1), nonBookableSpacesParams:
), NonBookableSpacesParams(currentPage: 1),
), ),
)
: (context) => NonBookableSpacesBloc(
RemoteNonBookableSpaces(HTTPService()),
)..add(
EditModeSelected(
editingBookableSpace: editingBookableSpace!),
),
), ),
], ],
child: AlertDialog( child: AlertDialog(
@ -67,6 +81,7 @@ class SetupBookableSpacesDialog extends StatelessWidget {
flex: 7, flex: 7,
child: DetailsStepsWidget( child: DetailsStepsWidget(
pointsController: pointsController, pointsController: pointsController,
editingBookableSpace: editingBookableSpace,
), ),
) )
], ],
@ -79,7 +94,9 @@ class SetupBookableSpacesDialog extends StatelessWidget {
? NextFirstStepButton(selectedSpaces: selectedSpaces) ? NextFirstStepButton(selectedSpaces: selectedSpaces)
: SaveSecondStepButton( : SaveSecondStepButton(
selectedSpaces: selectedSpaces, selectedSpaces: selectedSpaces,
pointsController: pointsController); pointsController: pointsController,
isEditingMode: editingBookableSpace != null,
);
}), }),
], ],
), ),

View File

@ -1,6 +1,7 @@
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:flutter_svg/svg.dart'; import 'package:flutter_svg/svg.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'; 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/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/color_manager.dart';
@ -8,8 +9,10 @@ import 'package:syncrow_web/utils/constants/assets.dart';
import 'package:syncrow_web/utils/string_utils.dart'; import 'package:syncrow_web/utils/string_utils.dart';
class BookingPeriodWidget extends StatelessWidget { class BookingPeriodWidget extends StatelessWidget {
final BookableSpacemodel? editingBookableSpace;
const BookingPeriodWidget({ const BookingPeriodWidget({
super.key, super.key,
this.editingBookableSpace,
}); });
@override @override
@ -39,22 +42,23 @@ class BookingPeriodWidget extends StatelessWidget {
crossAxisAlignment: CrossAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center,
children: [ children: [
TimePickerWidget( TimePickerWidget(
title: 'Start Time', title: editingBookableSpace == null
? 'Start Time'
: editingBookableSpace!.spaceConfig!.bookingStartTime!
.format(context),
onTimePicked: (timePicked) { onTimePicked: (timePicked) {
if (timePicked == null) { if (timePicked == null) {
return; return;
} }
final nonBookableBloc = final nonBookableBloc = context.read<NonBookableSpacesBloc>();
context.read<NonBookableSpacesBloc>();
if (nonBookableBloc.endTime != null && if (nonBookableBloc.endTime != null &&
isEndTimeAfterStartTime( isEndTimeAfterStartTime(
timePicked, nonBookableBloc.endTime!)) { timePicked, nonBookableBloc.endTime!)) {
ScaffoldMessenger.of(context).clearSnackBars(); ScaffoldMessenger.of(context).clearSnackBars();
ScaffoldMessenger.of(context) ScaffoldMessenger.of(context).showSnackBar(const SnackBar(
.showSnackBar(const SnackBar( content:
content: Text( Text("You can't choose start Time Before End time"),
"You can't choose start Time Before End time"),
duration: Duration(seconds: 2), duration: Duration(seconds: 2),
backgroundColor: ColorsManager.red, backgroundColor: ColorsManager.red,
)); ));
@ -71,21 +75,22 @@ class BookingPeriodWidget extends StatelessWidget {
color: ColorsManager.grayColor, color: ColorsManager.grayColor,
), ),
TimePickerWidget( TimePickerWidget(
title: 'End Time', title: editingBookableSpace == null
? 'End Time'
: editingBookableSpace!.spaceConfig!.bookingEndTime!
.format(context),
onTimePicked: (timePicked) { onTimePicked: (timePicked) {
if (timePicked == null) { if (timePicked == null) {
return; return;
} }
final nonBookableBloc = final nonBookableBloc = context.read<NonBookableSpacesBloc>();
context.read<NonBookableSpacesBloc>();
if (nonBookableBloc.startTime != null && if (nonBookableBloc.startTime != null &&
isEndTimeAfterStartTime( isEndTimeAfterStartTime(
nonBookableBloc.startTime!, timePicked)) { nonBookableBloc.startTime!, timePicked)) {
ScaffoldMessenger.of(context).clearSnackBars(); ScaffoldMessenger.of(context).clearSnackBars();
ScaffoldMessenger.of(context) ScaffoldMessenger.of(context).showSnackBar(const SnackBar(
.showSnackBar(const SnackBar( content:
content: Text( Text("You can't choose End Time After Start time"),
"You can't choose End Time After Start time"),
duration: Duration(seconds: 2), duration: Duration(seconds: 2),
backgroundColor: ColorsManager.red, backgroundColor: ColorsManager.red,
)); ));

View File

@ -4,7 +4,6 @@ import 'package:go_router/go_router.dart';
import 'package:syncrow_web/pages/access_management/manage_bookable_spaces/domain/params/bookable_spaces_params.dart'; import 'package:syncrow_web/pages/access_management/manage_bookable_spaces/domain/params/bookable_spaces_params.dart';
import 'package:syncrow_web/pages/access_management/manage_bookable_spaces/presentation/blocs/bookable_spaces_bloc/bookable_spaces_bloc.dart'; import 'package:syncrow_web/pages/access_management/manage_bookable_spaces/presentation/blocs/bookable_spaces_bloc/bookable_spaces_bloc.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/blocs/non_bookable_spaces_bloc/non_bookaable_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/utils/color_manager.dart'; import 'package:syncrow_web/utils/color_manager.dart';
class ButtonsDividerBottomDialogWidget extends StatelessWidget { class ButtonsDividerBottomDialogWidget extends StatelessWidget {
@ -63,7 +62,7 @@ class ButtonsDividerBottomDialogWidget extends StatelessWidget {
ScaffoldMessenger.of(context).showSnackBar( ScaffoldMessenger.of(context).showSnackBar(
const SnackBar( const SnackBar(
content: Text( content: Text(
'Spaces Added Successfully', 'Operation Done Successfully',
style: TextStyle(color: ColorsManager.activeGreen), style: TextStyle(color: ColorsManager.activeGreen),
), ),
duration: Duration(seconds: 2), duration: Duration(seconds: 2),

View File

@ -1,14 +1,17 @@
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/access_management/manage_bookable_spaces/domain/models/bookable_space_model.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/space_step_part_widget.dart'; import 'package:syncrow_web/pages/access_management/manage_bookable_spaces/presentation/widgets/space_step_part_widget.dart';
import 'package:syncrow_web/pages/access_management/manage_bookable_spaces/presentation/widgets/step_two_details_widget.dart'; import 'package:syncrow_web/pages/access_management/manage_bookable_spaces/presentation/widgets/step_two_details_widget.dart';
class DetailsStepsWidget extends StatelessWidget { class DetailsStepsWidget extends StatelessWidget {
final TextEditingController pointsController; final TextEditingController pointsController;
final BookableSpacemodel? editingBookableSpace;
const DetailsStepsWidget({ const DetailsStepsWidget({
super.key, super.key,
required this.pointsController, required this.pointsController,
this.editingBookableSpace,
}); });
@override @override
@ -22,6 +25,7 @@ class DetailsStepsWidget extends StatelessWidget {
} else if (state is StepTwoState) { } else if (state is StepTwoState) {
return StepTwoDetailsWidget( return StepTwoDetailsWidget(
pointsController: pointsController, pointsController: pointsController,
editingBookableSpace:editingBookableSpace
); );
} else { } else {
return const SizedBox(); return const SizedBox();

View File

@ -1,12 +1,15 @@
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:flutter_svg/svg.dart'; import 'package:flutter_svg/svg.dart';
import 'package:syncrow_web/pages/access_management/manage_bookable_spaces/data/remote_update_bookable_space_service.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/domain/models/bookable_space_model.dart';
import 'package:syncrow_web/pages/access_management/manage_bookable_spaces/domain/params/bookable_spaces_params.dart'; import 'package:syncrow_web/pages/access_management/manage_bookable_spaces/domain/params/bookable_spaces_params.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/params/update_bookable_space_param.dart';
import 'package:syncrow_web/pages/access_management/manage_bookable_spaces/presentation/blocs/bookable_spaces_bloc/bookable_spaces_bloc.dart'; import 'package:syncrow_web/pages/access_management/manage_bookable_spaces/presentation/blocs/bookable_spaces_bloc/bookable_spaces_bloc.dart';
import 'package:syncrow_web/pages/access_management/manage_bookable_spaces/presentation/blocs/update_bookable_spaces/update_bookable_spaces_bloc.dart'; import 'package:syncrow_web/pages/access_management/manage_bookable_spaces/presentation/blocs/update_bookable_spaces/update_bookable_spaces_bloc.dart';
import 'package:syncrow_web/pages/access_management/manage_bookable_spaces/presentation/screens/setup_bookable_spaces_dialog.dart';
import 'package:syncrow_web/pages/access_management/manage_bookable_spaces/presentation/widgets/custom_data_table.dart'; import 'package:syncrow_web/pages/access_management/manage_bookable_spaces/presentation/widgets/custom_data_table.dart';
import 'package:syncrow_web/services/api/http_service.dart';
import 'package:syncrow_web/utils/color_manager.dart'; import 'package:syncrow_web/utils/color_manager.dart';
import 'package:syncrow_web/utils/constants/assets.dart'; import 'package:syncrow_web/utils/constants/assets.dart';
@ -143,7 +146,28 @@ class TablePartWidget extends StatelessWidget {
)), )),
DataCell(Center( DataCell(Center(
child: ElevatedButton( child: ElevatedButton(
onPressed: () {}, onPressed: () {
final bookableBloc = context.read<BookableSpacesBloc>();
showDialog(
context: context,
builder: (context) => MultiBlocProvider(
providers: [
BlocProvider.value(
value: bookableBloc,
),
BlocProvider(
create: (context) => UpdateBookableSpacesBloc(
RemoteUpdateBookableSpaceService(HTTPService()),
),
),
],
child: SetupBookableSpacesDialog(
editingBookableSpace: space,
),
),
);
},
style: ElevatedButton.styleFrom( style: ElevatedButton.styleFrom(
padding: EdgeInsets.zero, padding: EdgeInsets.zero,
fixedSize: const Size(50, 30), fixedSize: const Size(50, 30),

View File

@ -1,19 +1,36 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
import 'package:flutter_bloc/flutter_bloc.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/cubit/toggle_points_switch_cubit.dart'; import 'package:syncrow_web/pages/access_management/manage_bookable_spaces/presentation/blocs/cubit/toggle_points_switch_cubit.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/blocs/non_bookable_spaces_bloc/non_bookaable_spaces_bloc.dart';
import 'package:syncrow_web/pages/access_management/manage_bookable_spaces/presentation/widgets/search_unbookable_spaces_widget.dart'; import 'package:syncrow_web/pages/access_management/manage_bookable_spaces/presentation/widgets/search_unbookable_spaces_widget.dart';
import 'package:syncrow_web/utils/color_manager.dart'; import 'package:syncrow_web/utils/color_manager.dart';
class PointsPartWidget extends StatelessWidget { class PointsPartWidget extends StatefulWidget {
final BookableSpacemodel? editingBookableSpace;
const PointsPartWidget({ const PointsPartWidget({
super.key, super.key,
required this.pointsController, required this.pointsController,
this.editingBookableSpace,
}); });
final TextEditingController pointsController; final TextEditingController pointsController;
@override
State<PointsPartWidget> createState() => _PointsPartWidgetState();
}
class _PointsPartWidgetState extends State<PointsPartWidget> {
@override
void initState() {
if (widget.editingBookableSpace != null) {
widget.pointsController.text =
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>(
@ -73,7 +90,7 @@ class PointsPartWidget extends StatelessWidget {
context context
.read<TogglePointsSwitchCubit>() .read<TogglePointsSwitchCubit>()
.unActivateSwitch(); .unActivateSwitch();
pointsController.clear(); widget.pointsController.clear();
context context
.read<NonBookableSpacesBloc>() .read<NonBookableSpacesBloc>()
.selectedBookableSpaces .selectedBookableSpaces
@ -102,16 +119,16 @@ class PointsPartWidget extends StatelessWidget {
.selectedBookableSpaces .selectedBookableSpaces
.forEach( .forEach(
(e) => e.spaceConfig!.cost = int.parse( (e) => e.spaceConfig!.cost = int.parse(
pointsController.text.isEmpty widget.pointsController.text.isEmpty
? '0' ? '0'
: pointsController.text, : widget.pointsController.text,
), ),
); );
context context
.read<NonBookableSpacesBloc>() .read<NonBookableSpacesBloc>()
.add(CheckConfigurValidityEvent()); .add(CheckConfigurValidityEvent());
}, },
controller: pointsController, controller: widget.pointsController,
inputFormatters: [FilteringTextInputFormatter.digitsOnly], inputFormatters: [FilteringTextInputFormatter.digitsOnly],
suffix: const SizedBox(), suffix: const SizedBox(),
) )

View File

@ -2,17 +2,21 @@ 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/domain/models/bookable_space_model.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/presentation/blocs/non_bookable_spaces_bloc/non_bookaable_spaces_bloc.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/blocs/update_bookable_spaces/update_bookable_spaces_bloc.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 SaveSecondStepButton extends StatelessWidget { class SaveSecondStepButton extends StatelessWidget {
final List<BookableSpacemodel> selectedSpaces; final List<BookableSpacemodel> selectedSpaces;
final TextEditingController pointsController; final TextEditingController pointsController;
final bool isEditingMode;
const SaveSecondStepButton({ const SaveSecondStepButton({
super.key, super.key,
required this.selectedSpaces, required this.selectedSpaces,
required this.pointsController, required this.pointsController,
required this.isEditingMode,
}); });
@override @override
@ -27,9 +31,11 @@ class SaveSecondStepButton extends StatelessWidget {
if (selectedSpaces.any( if (selectedSpaces.any(
(element) => element.isValid, (element) => element.isValid,
)) { )) {
context.read<NonBookableSpacesBloc>().add( isEditingMode
SendBookableSpacesToApi(), ? callEditLogic(context)
); : context.read<NonBookableSpacesBloc>().add(
SendBookableSpacesToApi(),
);
} }
}, },
onCancelPressed: () => context.pop(), onCancelPressed: () => context.pop(),
@ -37,4 +43,19 @@ class SaveSecondStepButton extends StatelessWidget {
}, },
); );
} }
void callEditLogic(BuildContext context) {
context.read<UpdateBookableSpacesBloc>().add(
UpdateBookableSpace(
onSuccess: () =>
context.read<NonBookableSpacesBloc>().add(CallInitStateEvent()),
updatedParams: UpdateBookableSpaceParam.fromBookableModel(
context
.read<NonBookableSpacesBloc>()
.selectedBookableSpaces
.first,
),
),
);
}
} }

View File

@ -1,5 +1,6 @@
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/access_management/manage_bookable_spaces/domain/models/bookable_space_model.dart';
import 'package:syncrow_web/pages/access_management/manage_bookable_spaces/presentation/blocs/cubit/toggle_points_switch_cubit.dart'; import 'package:syncrow_web/pages/access_management/manage_bookable_spaces/presentation/blocs/cubit/toggle_points_switch_cubit.dart';
import 'package:syncrow_web/pages/access_management/manage_bookable_spaces/presentation/widgets/booking_period_widget.dart'; import 'package:syncrow_web/pages/access_management/manage_bookable_spaces/presentation/widgets/booking_period_widget.dart';
import 'package:syncrow_web/pages/access_management/manage_bookable_spaces/presentation/widgets/points_part_widget.dart'; import 'package:syncrow_web/pages/access_management/manage_bookable_spaces/presentation/widgets/points_part_widget.dart';
@ -7,9 +8,11 @@ import 'package:syncrow_web/pages/access_management/manage_bookable_spaces/prese
class StepTwoDetailsWidget extends StatelessWidget { class StepTwoDetailsWidget extends StatelessWidget {
final TextEditingController pointsController; final TextEditingController pointsController;
final BookableSpacemodel? editingBookableSpace;
const StepTwoDetailsWidget({ const StepTwoDetailsWidget({
super.key, super.key,
required this.pointsController, required this.pointsController,
this.editingBookableSpace,
}); });
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
@ -19,17 +22,27 @@ class StepTwoDetailsWidget extends StatelessWidget {
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
const WeekDaysCheckboxRow(), WeekDaysCheckboxRow(
editingBookableSpace: editingBookableSpace,
),
const SizedBox( const SizedBox(
height: 20, height: 20,
), ),
const BookingPeriodWidget(), BookingPeriodWidget(
editingBookableSpace: editingBookableSpace,
),
const SizedBox( const SizedBox(
height: 20, height: 20,
), ),
BlocProvider( BlocProvider(
create: (context) => TogglePointsSwitchCubit()..activateSwitch(), create: editingBookableSpace == null
child: PointsPartWidget(pointsController: pointsController), ? (context) => TogglePointsSwitchCubit()..activateSwitch()
: editingBookableSpace!.spaceConfig!.cost == 0
? (context) => TogglePointsSwitchCubit()..unActivateSwitch()
: (context) => TogglePointsSwitchCubit()..activateSwitch(),
child: PointsPartWidget(
pointsController: pointsController,
editingBookableSpace: editingBookableSpace),
) )
], ],
), ),

View File

@ -68,10 +68,6 @@ class StepperPartWidget extends StatelessWidget {
) )
], ],
); );
} else if (state is StepEditMode) {
return const CircleTitleStepperWidget(
title: 'Settings',
);
} else { } else {
return const SizedBox(); return const SizedBox();
} }

View File

@ -1,11 +1,9 @@
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:flutter_svg/flutter_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/blocs/non_bookable_spaces_bloc/non_bookaable_spaces_bloc.dart';
import 'package:syncrow_web/utils/color_manager.dart'; import 'package:syncrow_web/utils/color_manager.dart';
import 'package:syncrow_web/utils/constants/assets.dart';
class TimePickerWidget extends StatefulWidget { class TimePickerWidget extends StatefulWidget {
final String title; final String title;

View File

@ -1,9 +1,14 @@
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/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'; import 'package:syncrow_web/pages/access_management/manage_bookable_spaces/presentation/blocs/non_bookable_spaces_bloc/non_bookaable_spaces_bloc.dart';
class WeekDaysCheckboxRow extends StatefulWidget { class WeekDaysCheckboxRow extends StatefulWidget {
const WeekDaysCheckboxRow({super.key}); final BookableSpacemodel? editingBookableSpace;
const WeekDaysCheckboxRow({
super.key,
this.editingBookableSpace,
});
@override @override
State<WeekDaysCheckboxRow> createState() => _WeekDaysCheckboxRowState(); State<WeekDaysCheckboxRow> createState() => _WeekDaysCheckboxRowState();
@ -19,6 +24,19 @@ class _WeekDaysCheckboxRowState extends State<WeekDaysCheckboxRow> {
'Sat': false, 'Sat': false,
'Sun': false, 'Sun': false,
}; };
@override
void initState() {
super.initState();
final existingDays =
widget.editingBookableSpace?.spaceConfig?.bookableDays ?? [];
for (var day in _daysChecked.keys) {
if (existingDays.contains(day)) {
_daysChecked[day] = true;
}
}
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {