From aab2b4a52a995d2ee46eef79e4827c13b0e5b3b0 Mon Sep 17 00:00:00 2001 From: Rafeek-Khoudare Date: Thu, 10 Jul 2025 15:52:15 +0300 Subject: [PATCH] insert after update and refactor --- .../bookable_spaces_bloc.dart | 29 ++ .../bookable_spaces_event.dart | 11 + .../bookable_spaces_state.dart | 2 + .../manage_bookable_spaces_screen.dart | 411 ++---------------- .../widgets/next_first_step_button.dart | 4 + 5 files changed, 84 insertions(+), 373 deletions(-) diff --git a/lib/pages/access_management/manage_bookable_spaces/presentation/blocs/bookable_spaces_bloc/bookable_spaces_bloc.dart b/lib/pages/access_management/manage_bookable_spaces/presentation/blocs/bookable_spaces_bloc/bookable_spaces_bloc.dart index 14288a25..009db2b9 100644 --- a/lib/pages/access_management/manage_bookable_spaces/presentation/blocs/bookable_spaces_bloc/bookable_spaces_bloc.dart +++ b/lib/pages/access_management/manage_bookable_spaces/presentation/blocs/bookable_spaces_bloc/bookable_spaces_bloc.dart @@ -1,5 +1,6 @@ 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/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/service/bookable_spaces_service.dart'; @@ -15,6 +16,7 @@ class BookableSpacesBloc BookableSpacesBloc(this.bookableSpacesService) : super(BookableSpacesInitial()) { on(_onLoadBookableSpaces); + on(_onInsertUpdatedSpaceEven); } Future _onLoadBookableSpaces( @@ -31,4 +33,31 @@ class BookableSpacesBloc ); } } + + void _onInsertUpdatedSpaceEven( + InsertUpdatedSpaceEvent event, Emitter emit) { + emit(InsertingUpdatedSpaceState()); + + if (event.bookableSpace.spaceConfig!.configUuid == + event.updatedBookableSpaceConfig.configUuid) { + final editedBookableSpace = event.bookableSpaces.data.firstWhere( + (element) => element.spaceUuid == event.bookableSpace.spaceUuid, + ); + final config = editedBookableSpace.spaceConfig!.copyWith( + availability: event.updatedBookableSpaceConfig.availability, + bookableDays: event.updatedBookableSpaceConfig.bookableDays, + bookingEndTime: event.updatedBookableSpaceConfig.bookingEndTime, + bookingStartTime: event.updatedBookableSpaceConfig.bookingStartTime, + cost: event.updatedBookableSpaceConfig.cost, + ); + editedBookableSpace.spaceConfig = config; + final index = event.bookableSpaces.data.indexWhere( + (element) => element.spaceUuid == event.bookableSpace.spaceUuid, + ); + event.bookableSpaces.data.removeAt(index); + event.bookableSpaces.data.insert(index, editedBookableSpace); + } + + emit(BookableSpacesLoaded(bookableSpacesList: event.bookableSpaces)); + } } diff --git a/lib/pages/access_management/manage_bookable_spaces/presentation/blocs/bookable_spaces_bloc/bookable_spaces_event.dart b/lib/pages/access_management/manage_bookable_spaces/presentation/blocs/bookable_spaces_bloc/bookable_spaces_event.dart index 47a1b396..46cfe908 100644 --- a/lib/pages/access_management/manage_bookable_spaces/presentation/blocs/bookable_spaces_bloc/bookable_spaces_event.dart +++ b/lib/pages/access_management/manage_bookable_spaces/presentation/blocs/bookable_spaces_bloc/bookable_spaces_event.dart @@ -11,3 +11,14 @@ class LoadBookableSpacesEvent extends BookableSpacesEvent { final BookableSpacesParams params; const LoadBookableSpacesEvent(this.params); } + +class InsertUpdatedSpaceEvent extends BookableSpacesEvent { + final PaginatedDataModel bookableSpaces; + final BookableSpacemodel bookableSpace; + final BookableSpaceConfig updatedBookableSpaceConfig; + const InsertUpdatedSpaceEvent({ + required this.bookableSpaces, + required this.bookableSpace, + required this.updatedBookableSpaceConfig, + }); +} diff --git a/lib/pages/access_management/manage_bookable_spaces/presentation/blocs/bookable_spaces_bloc/bookable_spaces_state.dart b/lib/pages/access_management/manage_bookable_spaces/presentation/blocs/bookable_spaces_bloc/bookable_spaces_state.dart index d722ddef..d22f585a 100644 --- a/lib/pages/access_management/manage_bookable_spaces/presentation/blocs/bookable_spaces_bloc/bookable_spaces_state.dart +++ b/lib/pages/access_management/manage_bookable_spaces/presentation/blocs/bookable_spaces_bloc/bookable_spaces_state.dart @@ -24,3 +24,5 @@ final class BookableSpacesError extends BookableSpacesState { required this.error, }); } + +class InsertingUpdatedSpaceState extends BookableSpacesState {} diff --git a/lib/pages/access_management/manage_bookable_spaces/presentation/screens/manage_bookable_spaces_screen.dart b/lib/pages/access_management/manage_bookable_spaces/presentation/screens/manage_bookable_spaces_screen.dart index 9ed9cd2d..1c2e98f6 100644 --- a/lib/pages/access_management/manage_bookable_spaces/presentation/screens/manage_bookable_spaces_screen.dart +++ b/lib/pages/access_management/manage_bookable_spaces/presentation/screens/manage_bookable_spaces_screen.dart @@ -1,24 +1,22 @@ import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; -import 'package:flutter_svg/svg.dart'; -import 'package:go_router/go_router.dart'; -import 'package:syncrow_web/pages/access_management/booking_system/view/widgets/icon_text_button.dart'; import 'package:syncrow_web/pages/access_management/manage_bookable_spaces/data/remote_bookable_spaces_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/data/remote_update_bookable_space_service.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/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/device_managment/shared/navigate_home_grid_view.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/main_manage_bookable_widgets/bottom_pagination_part_widget.dart'; +import 'package:syncrow_web/pages/access_management/manage_bookable_spaces/presentation/widgets/main_manage_bookable_widgets/table_part_widget.dart'; +import 'package:syncrow_web/pages/access_management/manage_bookable_spaces/presentation/widgets/main_manage_bookable_widgets/top_part_widget.dart'; + import 'package:syncrow_web/services/api/http_service.dart'; -import 'package:syncrow_web/utils/color_manager.dart'; -import 'package:syncrow_web/utils/constants/assets.dart'; -import 'package:syncrow_web/utils/extension/build_context_x.dart'; -import 'package:syncrow_web/utils/theme/responsive_text_theme.dart'; -import 'package:syncrow_web/web_layout/web_scaffold.dart'; class ManageBookableSpacesPage extends StatefulWidget { - const ManageBookableSpacesPage({super.key}); + final PageController pageController; + const ManageBookableSpacesPage({ + super.key, + required this.pageController, + }); @override State createState() => @@ -26,63 +24,39 @@ class ManageBookableSpacesPage extends StatefulWidget { } class _ManageBookableSpacesPageState extends State { - final PageController _pageController = PageController(initialPage: 1); - int _currentPageIndex = 1; @override Widget build(BuildContext context) { - return WebScaffold( - enableMenuSidebar: false, - appBarTitle: Text( - 'Access Management', - style: ResponsiveTextTheme.of(context).deviceManagementTitle, - ), - centerBody: Row( - mainAxisSize: MainAxisSize.min, - children: [ - TextButton( - onPressed: () => _switchPage(0), - child: Text( - 'Access Overview', - style: context.textTheme.titleMedium?.copyWith( - color: _currentPageIndex == 0 ? Colors.white : Colors.grey, - fontWeight: - _currentPageIndex == 0 ? FontWeight.w700 : FontWeight.w400, + return MultiBlocProvider( + providers: [ + BlocProvider( + create: (context) => BookableSpacesBloc( + RemoteBookableSpacesService(HTTPService()), + )..add( + LoadBookableSpacesEvent( + BookableSpacesParams(currentPage: 1), ), ), + ), + BlocProvider( + create: (context) => UpdateBookableSpacesBloc( + RemoteUpdateBookableSpaceService(HTTPService()), ), - TextButton( - onPressed: () => _switchPage(1), - child: Text( - 'Booking System', - style: context.textTheme.titleMedium?.copyWith( - color: _currentPageIndex == 1 ? Colors.white : Colors.grey, - fontWeight: - _currentPageIndex == 1 ? FontWeight.w700 : FontWeight.w400, - ), - ), - ), - ], - ), - rightBody: const NavigateHomeGridView(), - scaffoldBody: BlocProvider( - create: (context) => BookableSpacesBloc( - RemoteBookableSpacesService(HTTPService()), - )..add(LoadBookableSpacesEvent( - BookableSpacesParams(currentPage: 1), - )), - child: const ManageBookableSpacesWidget(), + ) + ], + child: ManageBookableSpacesWidget( + pageController: widget.pageController, ), ); } - - void _switchPage(int index) { - setState(() => _currentPageIndex = index); - _pageController.jumpToPage(index); - } } class ManageBookableSpacesWidget extends StatelessWidget { - const ManageBookableSpacesWidget({super.key}); + final PageController pageController; + + const ManageBookableSpacesWidget({ + super.key, + required this.pageController, + }); @override Widget build(BuildContext context) { @@ -91,332 +65,23 @@ class ManageBookableSpacesWidget extends StatelessWidget { child: Column( children: [ Expanded( - flex: 10, - child: Padding( - padding: const EdgeInsetsGeometry.symmetric(vertical: 5), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - SvgTextButton( - svgSize: 15, - fontSize: 10, - fontWeight: FontWeight.bold, - svgAsset: Assets.backButtonIcon, - label: 'Booking Home', - onPressed: () { - context.pop(); - }), - SvgTextButton( - svgSize: 15, - fontSize: 10, - fontWeight: FontWeight.bold, - svgAsset: Assets.addButtonIcon, - label: 'Set Up a Bookable Spaces', - onPressed: () { - final bloc = context.read(); - showDialog( - context: context, - builder: (context) => BlocProvider.value( - value: bloc, - child: SetupBookableSpacesDialog(), - ), - ); - }, - ) - ], - ), - )), + flex: 10, child: TopPartWidget(pageController: pageController)), const SizedBox( height: 10, ), - Expanded( + const Expanded( flex: 85, - child: BlocBuilder( - builder: (context, state) { - if (state is BookableSpacesLoading) { - return const Center(child: CircularProgressIndicator()); - } else if (state is BookableSpacesError) { - return Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Text(state.error), - const SizedBox( - height: 5, - ), - ElevatedButton( - onPressed: () => context - .read() - .add(LoadBookableSpacesEvent( - BookableSpacesParams(currentPage: 1), - )), - child: const Text('try Again')) - ]); - } else if (state is BookableSpacesLoaded) { - return CustomDataTable( - items: state.bookableSpacesList.data, - cellsWidgets: (space) => [ - DataCell( - Padding( - padding: const EdgeInsetsGeometry.only(left: 10), - child: Text( - space.spaceName, - style: const TextStyle(fontSize: 11), - )), - ), - DataCell(Padding( - padding: const EdgeInsetsGeometry.only(left: 10), - child: Text( - space.spaceVirtualAddress, - style: const TextStyle(fontSize: 11), - ))), - DataCell(Container( - padding: const EdgeInsetsGeometry.only(left: 10), - width: 200, - child: Wrap( - spacing: 4, - children: space.spaceConfig!.bookableDays - .map((day) => Text( - day, - style: const TextStyle(fontSize: 11), - )) - .toList(), - ), - )), - DataCell( - Padding( - padding: const EdgeInsetsGeometry.only(left: 10), - child: Text( - space.spaceConfig!.bookingStartTime! - .format(context), - style: const TextStyle(fontSize: 11), - ), - ), - ), - DataCell( - Padding( - padding: const EdgeInsetsGeometry.only(left: 10), - child: Text( - space.spaceConfig!.bookingEndTime!.format(context), - style: const TextStyle(fontSize: 11), - ), - ), - ), - DataCell(Padding( - padding: const EdgeInsetsGeometry.only(left: 10), - child: Text( - '${space.spaceConfig!.cost} Points', - style: const TextStyle(fontSize: 11), - ))), - DataCell(Center( - child: Transform.scale( - scale: 0.7, - child: Switch( - value: space.spaceConfig!.availability, - trackColor: WidgetStateProperty.resolveWith( - (Set states) { - return ColorsManager.blue1; - }), - inactiveTrackColor: ColorsManager.lightGrayColor, - thumbColor: WidgetStateProperty.resolveWith( - (Set states) { - return ColorsManager.whiteColors; - }), - onChanged: (value) {}, - ), - ), - )), - DataCell(Center( - child: ElevatedButton( - onPressed: () {}, - style: ElevatedButton.styleFrom( - padding: EdgeInsets.zero, - fixedSize: const Size(50, 30), - elevation: 1, - ), - child: SvgPicture.asset( - Assets.settings, - height: 15, - color: ColorsManager.blue1, - ), - ), - )), - ], - columnsTitles: const [ - 'Space', - 'Space Virtual Address', - 'Bookable Days', - 'Booking Start Time', - 'Booking End Time', - 'Cost', - 'Availability', - 'Settings', - ], - ); - } else { - return const SizedBox(); - } - }, - ), + child: TablePartWidget(), ), const SizedBox( height: 5, ), - Expanded( + const Expanded( flex: 5, - child: BlocBuilder( - builder: (context, state) { - if (state is BookableSpacesLoaded) { - final totalPages = state.bookableSpacesList.totalPages; - final currentPage = state.bookableSpacesList.page; - - List paginationItems = []; - - // « Two pages back - if (currentPage > 2) { - paginationItems.add( - _buildArrowButton( - label: '«', - onTap: () { - context.read().add( - LoadBookableSpacesEvent( - BookableSpacesParams( - currentPage: currentPage - 2), - ), - ); - }, - ), - ); - } - - // < One page back - if (currentPage > 1) { - paginationItems.add( - _buildArrowButton( - label: '<', - onTap: () { - context.read().add( - LoadBookableSpacesEvent( - BookableSpacesParams( - currentPage: currentPage - 1), - ), - ); - }, - ), - ); - } - - // Page numbers - for (int i = 1; i <= totalPages; i++) { - paginationItems.add( - Padding( - padding: const EdgeInsets.symmetric(horizontal: 4), - child: GestureDetector( - onTap: () { - if (i != currentPage) { - context.read().add( - LoadBookableSpacesEvent( - BookableSpacesParams(currentPage: i), - ), - ); - } - }, - child: Container( - width: 30, - height: 30, - alignment: Alignment.center, - decoration: BoxDecoration( - color: i == currentPage - ? ColorsManager.dialogBlueTitle - : Colors.grey[300], - borderRadius: BorderRadius.circular(8), - ), - child: Text( - '$i', - style: TextStyle( - color: i == currentPage - ? Colors.white - : Colors.black, - fontWeight: i == currentPage - ? FontWeight.bold - : FontWeight.normal, - ), - ), - ), - ), - ), - ); - } - - // > One page forward - if (currentPage < totalPages) { - paginationItems.add( - _buildArrowButton( - label: '>', - onTap: () { - context.read().add( - LoadBookableSpacesEvent( - BookableSpacesParams( - currentPage: currentPage + 1), - ), - ); - }, - ), - ); - } - - // » Two pages forward - if (currentPage + 1 < totalPages) { - paginationItems.add( - _buildArrowButton( - label: '»', - onTap: () { - context.read().add( - LoadBookableSpacesEvent( - BookableSpacesParams( - currentPage: currentPage + 2), - ), - ); - }, - ), - ); - } - - return Row( - mainAxisAlignment: MainAxisAlignment.end, - children: paginationItems, - ); - } else { - return const SizedBox.shrink(); - } - }, - ), + child: BottomPaginationPartWidget(), ), ], ), ); } - - Widget _buildArrowButton( - {required String label, required VoidCallback onTap}) { - return Padding( - padding: const EdgeInsets.symmetric(horizontal: 4), - child: GestureDetector( - onTap: onTap, - child: Container( - padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8), - decoration: BoxDecoration( - color: Colors.grey[300], - borderRadius: BorderRadius.circular(8), - ), - child: Text( - label, - style: const TextStyle( - color: Colors.black, - fontWeight: FontWeight.bold, - ), - ), - ), - ), - ); - } } diff --git a/lib/pages/access_management/manage_bookable_spaces/presentation/widgets/next_first_step_button.dart b/lib/pages/access_management/manage_bookable_spaces/presentation/widgets/next_first_step_button.dart index a404a900..bf1f1af6 100644 --- a/lib/pages/access_management/manage_bookable_spaces/presentation/widgets/next_first_step_button.dart +++ b/lib/pages/access_management/manage_bookable_spaces/presentation/widgets/next_first_step_button.dart @@ -2,6 +2,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.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/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/widgets/buttons_divider_bottom_dialog_widget.dart'; @@ -21,6 +22,9 @@ class NextFirstStepButton extends StatelessWidget { ? null : () { context.read().goToNextStep(); + context + .read() + .add(CheckConfigurValidityEvent()); }, onCancelPressed: () => context.pop(), );