From e2d4e48875c5f2e2eb85a80b60cd8137eb78e98a Mon Sep 17 00:00:00 2001 From: Rafeek-Khoudare Date: Mon, 7 Jul 2025 15:36:35 +0300 Subject: [PATCH] build main screens with its widgets for bookableScreen --- assets/icons/add_button_Icon.svg | 10 ++ assets/icons/back_button_icon.svg | 4 + assets/icons/clock_icon.svg | 4 + assets/icons/no_data_table.svg | 24 +++ .../booking_system/view/booking_page.dart | 9 +- .../screens/setup_bookable_spaces_dialog.dart | 140 ++++++++++++++++++ .../buttons_divider_bottom_dialog_widget.dart | 88 +++++++++++ .../widgets/column_title_widget.dart | 37 +++++ .../widgets/custom_data_table.dart | 55 +++++++ 9 files changed, 369 insertions(+), 2 deletions(-) create mode 100644 assets/icons/add_button_Icon.svg create mode 100644 assets/icons/back_button_icon.svg create mode 100644 assets/icons/clock_icon.svg create mode 100644 assets/icons/no_data_table.svg create mode 100644 lib/pages/access_management/manage_bookable_spaces/presentation/screens/setup_bookable_spaces_dialog.dart create mode 100644 lib/pages/access_management/manage_bookable_spaces/presentation/widgets/buttons_divider_bottom_dialog_widget.dart create mode 100644 lib/pages/access_management/manage_bookable_spaces/presentation/widgets/column_title_widget.dart create mode 100644 lib/pages/access_management/manage_bookable_spaces/presentation/widgets/custom_data_table.dart diff --git a/assets/icons/add_button_Icon.svg b/assets/icons/add_button_Icon.svg new file mode 100644 index 00000000..f9b8eae7 --- /dev/null +++ b/assets/icons/add_button_Icon.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/assets/icons/back_button_icon.svg b/assets/icons/back_button_icon.svg new file mode 100644 index 00000000..5cc7b637 --- /dev/null +++ b/assets/icons/back_button_icon.svg @@ -0,0 +1,4 @@ + + + + diff --git a/assets/icons/clock_icon.svg b/assets/icons/clock_icon.svg new file mode 100644 index 00000000..296aa862 --- /dev/null +++ b/assets/icons/clock_icon.svg @@ -0,0 +1,4 @@ + + + + diff --git a/assets/icons/no_data_table.svg b/assets/icons/no_data_table.svg new file mode 100644 index 00000000..c97946a2 --- /dev/null +++ b/assets/icons/no_data_table.svg @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/lib/pages/access_management/booking_system/view/booking_page.dart b/lib/pages/access_management/booking_system/view/booking_page.dart index 6fdb53bd..d35f258d 100644 --- a/lib/pages/access_management/booking_system/view/booking_page.dart +++ b/lib/pages/access_management/booking_system/view/booking_page.dart @@ -1,6 +1,8 @@ import 'package:flutter/material.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/utils/constants/assets.dart'; +import 'package:syncrow_web/utils/constants/routes_const.dart'; class BookingPage extends StatelessWidget { const BookingPage({super.key}); @@ -33,8 +35,11 @@ class BookingPage extends StatelessWidget { SvgTextButton( svgAsset: Assets.homeIcon, label: 'Manage Bookable Spaces', - onPressed: () {}), - SizedBox(width: 20), + onPressed: () { + context + .go(RoutesConst.manageBookableSapcesPage); + }), + const SizedBox(width: 20), SvgTextButton( svgAsset: Assets.groupIcon, label: 'Manage Users', diff --git a/lib/pages/access_management/manage_bookable_spaces/presentation/screens/setup_bookable_spaces_dialog.dart b/lib/pages/access_management/manage_bookable_spaces/presentation/screens/setup_bookable_spaces_dialog.dart new file mode 100644 index 00000000..f073b6ba --- /dev/null +++ b/lib/pages/access_management/manage_bookable_spaces/presentation/screens/setup_bookable_spaces_dialog.dart @@ -0,0 +1,140 @@ +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/data/dummy_non_nookable_spaces.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/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/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/stepper_part_widget.dart'; +import 'package:syncrow_web/utils/color_manager.dart'; + +class SetupBookableSpacesDialog extends StatelessWidget { + final TextEditingController pointsController = TextEditingController(); + SetupBookableSpacesDialog({super.key}); + @override + Widget build(BuildContext context) { + return MultiBlocProvider( + providers: [ + BlocProvider( + create: (context) => StepsCubit()..initDialogValue(), + ), + BlocProvider( + create: (context) => NonBookableSpacesBloc( + DummyNonNookableSpaces(), + )..add( + LoadUnBookableSpacesEvent( + nonBookableSpacesParams: + NonBookableSpacesParams(currentPage: 1), + ), + ), + ), + ], + child: AlertDialog( + contentPadding: EdgeInsets.zero, + title: Text( + 'Set Up a Bookable Spaces', + style: TextStyle( + fontWeight: FontWeight.w700, + color: ColorsManager.dialogBlueTitle, + fontSize: 15, + ), + ), + content: Column( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + const Divider(), + Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const Expanded( + flex: 3, + child: StepperPartWidget(), + ), + const SizedBox( + height: 588, + child: VerticalDivider( + thickness: 0.5, + width: 1, + ), + ), + Expanded( + flex: 7, + child: DetailsStepsWidget( + pointsController: pointsController, + ), + ) + ], + ), + Builder(builder: (context) { + return ButtonsDividerBottomDialogWidget( + onNextPressed: () { + final stepsState = context.read().state; + final selectedSpaces = context + .read() + .selectedBookableSpaces; + if (stepsState is StepOneState) { + if (selectedSpaces.isNotEmpty) { + context.read().goToNextStep(); + } else { + ScaffoldMessenger.of(context).showSnackBar( + const SnackBar( + content: Text('Please select at least one space.'), + ), + ); + } + } else if (stepsState is StepTwoState) { + selectedSpaces.forEach( + (e) => + e.spaceConfig.cost = int.parse(pointsController.text), + ); + if (selectedSpaces.any( + (element) => !element.isValid, + )) { + ScaffoldMessenger.of(context).showSnackBar( + const SnackBar( + content: Text('Please fill the required fields.'), + ), + ); + } else {} + } + }, + onCancelPressed: () => context.pop(), + ); + }), + ], + ), + ), + ); + } +} + +class DetailsStepsWidget extends StatelessWidget { + final TextEditingController pointsController; + const DetailsStepsWidget({ + super.key, + required this.pointsController, + }); + + @override + Widget build(BuildContext context) { + return Container( + padding: const EdgeInsets.symmetric(horizontal: 30, vertical: 20), + child: BlocBuilder( + builder: (context, state) { + if (state is StepOneState) { + return SpacesStepDetailsWidget(); + } else if (state is StepTwoState) { + return StepTwoDetailsWidget( + pointsController: pointsController, + ); + } else { + return const SizedBox(); + } + }, + ), + ); + } +} diff --git a/lib/pages/access_management/manage_bookable_spaces/presentation/widgets/buttons_divider_bottom_dialog_widget.dart b/lib/pages/access_management/manage_bookable_spaces/presentation/widgets/buttons_divider_bottom_dialog_widget.dart new file mode 100644 index 00000000..e177b9b1 --- /dev/null +++ b/lib/pages/access_management/manage_bookable_spaces/presentation/widgets/buttons_divider_bottom_dialog_widget.dart @@ -0,0 +1,88 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_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'; + +class ButtonsDividerBottomDialogWidget extends StatelessWidget { + final void Function() onNextPressed; + final void Function() onCancelPressed; + const ButtonsDividerBottomDialogWidget({ + super.key, + required this.onNextPressed, + required this.onCancelPressed, + }); + + @override + Widget build(BuildContext context) { + return Column( + children: [ + const Divider( + thickness: 0.5, + height: 1, + ), + Row( + children: [ + Expanded( + child: InkWell( + borderRadius: const BorderRadius.only( + bottomLeft: Radius.circular(26), + ), + onTap: onCancelPressed, + child: Container( + height: 40, + alignment: Alignment.center, + decoration: const BoxDecoration( + border: Border( + right: BorderSide( + color: ColorsManager.grayBorder, + ), + ), + borderRadius: BorderRadius.only( + bottomLeft: Radius.circular(26), + ), + ), + child: const Text( + 'Cancel', + style: TextStyle(color: ColorsManager.grayBorder), + ), + ), + ), + ), + Expanded( + child: BlocBuilder( + builder: (context, state) { + return InkWell( + borderRadius: const BorderRadius.only( + bottomRight: Radius.circular(26), + ), + onTap: onNextPressed, + child: Container( + height: 40, + alignment: Alignment.center, + decoration: const BoxDecoration( + border: Border( + right: BorderSide( + color: ColorsManager.grayBorder, + ), + ), + borderRadius: BorderRadius.only( + bottomRight: Radius.circular(26), + ), + ), + child: Text( + state is StepOneState ? 'Next' : 'Save', + style: const TextStyle( + color: ColorsManager.blueColor, + ), + ), + ), + ); + }, + ), + ) + ], + ) + ], + ); + } +} diff --git a/lib/pages/access_management/manage_bookable_spaces/presentation/widgets/column_title_widget.dart b/lib/pages/access_management/manage_bookable_spaces/presentation/widgets/column_title_widget.dart new file mode 100644 index 00000000..4ff11ec6 --- /dev/null +++ b/lib/pages/access_management/manage_bookable_spaces/presentation/widgets/column_title_widget.dart @@ -0,0 +1,37 @@ +import 'package:flutter/material.dart'; +import 'package:syncrow_web/utils/color_manager.dart'; + +class ColumnTitleWidget extends StatelessWidget { + final bool isFirst; + final bool isLast; + final String title; + const ColumnTitleWidget({ + super.key, + required this.title, + required this.isFirst, + required this.isLast, + }); + + @override + Widget build(BuildContext context) { + return Container( + alignment: Alignment.centerLeft, + padding: const EdgeInsets.only(left: 10), + decoration: BoxDecoration( + color: ColorsManager.graysColor, + borderRadius: isFirst + ? const BorderRadius.only( + topLeft: Radius.circular(12), + ) + : isLast + ? const BorderRadius.only( + topRight: Radius.circular(12), + ) + : null, + ), + child: Text( + title, + style: const TextStyle(color: ColorsManager.grayColor), + )); + } +} \ No newline at end of file diff --git a/lib/pages/access_management/manage_bookable_spaces/presentation/widgets/custom_data_table.dart b/lib/pages/access_management/manage_bookable_spaces/presentation/widgets/custom_data_table.dart new file mode 100644 index 00000000..a72104fe --- /dev/null +++ b/lib/pages/access_management/manage_bookable_spaces/presentation/widgets/custom_data_table.dart @@ -0,0 +1,55 @@ +import 'package:data_table_2/data_table_2.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:syncrow_web/pages/access_management/manage_bookable_spaces/presentation/widgets/column_title_widget.dart'; +import 'package:syncrow_web/utils/color_manager.dart'; +import 'package:syncrow_web/utils/constants/assets.dart'; + +class CustomDataTable extends StatelessWidget { + final List columnsTitles; + final List Function(T item) cellsWidgets; + final List items; + + const CustomDataTable({ + super.key, + required this.items, + required this.cellsWidgets, + required this.columnsTitles, + }); + + @override + Widget build(BuildContext context) { + return DataTable2( + dividerThickness: 0.5, + columnSpacing: 2, + horizontalMargin: 0, + empty: SvgPicture.asset(Assets.emptyDataTable), + decoration: BoxDecoration( + color: ColorsManager.circleRolesBackground, + borderRadius: BorderRadius.circular(12), + boxShadow: const [ + BoxShadow( + color: ColorsManager.textGray, + blurRadius: 12, + offset: Offset(0, 4), + ), + ], + ), + columns: columnsTitles.asMap().entries.map((entry) { + final index = entry.key; + final title = entry.value; + + return DataColumn( + label: ColumnTitleWidget( + title: title, + isFirst: index == 0, + isLast: index == columnsTitles.length - 1, + ), + ); + }).toList(), + rows: items.map((item) { + return DataRow(cells: cellsWidgets(item)); + }).toList(), + ); + } +}