6177214e-ce7c-49e3-99de-ff9721b26f63 — Commit 32ed0b27

AuthorNKL<nikolaj.king@gmail.com>
Date2025-12-08 08:33:41 +0100
made the bottomsheet fixed to the page and made the page fully scrollable

Changed files

.../lib/booking_details/booking_details_page.dart  | 112 +++++++-----
 .../components/booking_details_bottom_sheet.dart   | 193 +++++++++++----------
 2 files changed, 163 insertions(+), 142 deletions(-)

Diff

diff --git a/comwell_key_app/lib/booking_details/booking_details_page.dart b/comwell_key_app/lib/booking_details/booking_details_page.dart
index 6e5cb147..c3bc603d 100644
--- a/comwell_key_app/lib/booking_details/booking_details_page.dart
+++ b/comwell_key_app/lib/booking_details/booking_details_page.dart
@@ -53,8 +53,11 @@ class BookingDetailsPage extends StatelessWidget {
Widget _buildBookingDetailsPage(BuildContext context,
BookingDetailsState state, BookingDetailsBloc cubit) {
final theme = Theme.of(context);
+ final screenHeight = MediaQuery.of(context).size.height;
+
return Stack(
children: [
+ // Background image - fixed
Container(
decoration: const BoxDecoration(
image: DecorationImage(
@@ -63,6 +66,7 @@ class BookingDetailsPage extends StatelessWidget {
),
),
),
+ // Gradient overlay - fixed
Container(
decoration: const BoxDecoration(
gradient: LinearGradient(
@@ -75,55 +79,67 @@ class BookingDetailsPage extends StatelessWidget {
),
),
),
- Stack(
- alignment: Alignment.center,
- children: [
- if (cubit.booking.reservationStatus ==
- ReservationStatus.preregistered ||
- cubit.booking.reservationStatus ==
- ReservationStatus.preregistered ||
- cubit.booking.reservationStatus == ReservationStatus.checkedin)
- SafeArea(
- child: cubit.booking.isPrimaryGuest &&cubit.booking.reservationStatus == ReservationStatus.checkedin ? ShareButton(guests: state.guests) : const SizedBox(),
- ),
- Column(
- crossAxisAlignment: CrossAxisAlignment.center,
- mainAxisAlignment: MainAxisAlignment.center,
- children: [
- const Spacer(),
- if (cubit.booking.roomNumber != '')
- RoomNumberContainer(cubit: cubit),
- _buildBookingDetailsInformation(context, state, cubit, theme),
- const Padding(
- padding: EdgeInsets.symmetric(horizontal: 16.0),
- child: Divider(color: colorDivider),
- ),
- const SizedBox(height: 10),
- if (
- state.keys.isNotEmpty &&
- cubit.booking.roomNumber != '' &&
- state.keys.any((key) => key.label == cubit.booking.roomNumber)
- )
- UnlockRoomButton(roomNumber: cubit.booking.roomNumber)
- else if (cubit.booking.reservationStatus == ReservationStatus.checkedin
- )
- const GetKeysButton()
- else if (cubit.booking.reservationStatus ==
- ReservationStatus.preregistered)
- const CheckInButtonTimer()
- else if (cubit.booking.reservationStatus ==
- ReservationStatus.newreservation)
- const PreregisterButton()
- else
- const SizedBox(),
- const SizedBox(
- height: 200,
+ // Share button - fixed at top
+ if (cubit.booking.reservationStatus ==
+ ReservationStatus.preregistered ||
+ cubit.booking.reservationStatus ==
+ ReservationStatus.preregistered ||
+ cubit.booking.reservationStatus == ReservationStatus.checkedin)
+ SafeArea(
+ child: cubit.booking.isPrimaryGuest &&
+ cubit.booking.reservationStatus ==
+ ReservationStatus.checkedin
+ ? ShareButton(guests: state.guests)
+ : const SizedBox(),
+ ),
+ // Scrollable content
+ SingleChildScrollView(
+ child: Column(
+ children: [
+ // Top section with room info - leaves 60px for sheet peek
+ SizedBox(
+ height: screenHeight - 100,
+ child: SafeArea(
+ bottom: false,
+ child: Column(
+ crossAxisAlignment: CrossAxisAlignment.center,
+ mainAxisAlignment: MainAxisAlignment.end,
+ children: [
+ if (cubit.booking.roomNumber != '')
+ RoomNumberContainer(cubit: cubit),
+ _buildBookingDetailsInformation(
+ context, state, cubit, theme),
+ const Padding(
+ padding: EdgeInsets.symmetric(horizontal: 16.0),
+ child: Divider(color: colorDivider),
+ ),
+ const SizedBox(height: 10),
+ if (state.keys.isNotEmpty &&
+ cubit.booking.roomNumber != '' &&
+ state.keys
+ .any((key) => key.label == cubit.booking.roomNumber))
+ UnlockRoomButton(roomNumber: cubit.booking.roomNumber)
+ else if (cubit.booking.reservationStatus ==
+ ReservationStatus.checkedin)
+ const GetKeysButton()
+ else if (cubit.booking.reservationStatus ==
+ ReservationStatus.preregistered)
+ const CheckInButtonTimer()
+ else if (cubit.booking.reservationStatus ==
+ ReservationStatus.newreservation)
+ const PreregisterButton()
+ else
+ const SizedBox(),
+ const SizedBox(height: 24),
+ ],
+ ),
),
- ],
- ),
- BookingDetailsBottomSheet(cubit: cubit, state: state),
- ],
- )
+ ),
+ // Bottom sheet content (scrollable, styled like a sheet)
+ BookingDetailsBottomSheet(cubit: cubit, state: state),
+ ],
+ ),
+ ),
],
);
}
diff --git a/comwell_key_app/lib/booking_details/components/booking_details_bottom_sheet.dart b/comwell_key_app/lib/booking_details/components/booking_details_bottom_sheet.dart
index 7c36701d..bd33cfdd 100644
--- a/comwell_key_app/lib/booking_details/components/booking_details_bottom_sheet.dart
+++ b/comwell_key_app/lib/booking_details/components/booking_details_bottom_sheet.dart
@@ -2,12 +2,12 @@ import 'package:comwell_key_app/booking_details/bloc/booking_details_bloc.dart';
import 'package:comwell_key_app/booking_details/components/check_out_button.dart';
import 'package:comwell_key_app/booking_details/components/housekeeping_button.dart';
import 'package:comwell_key_app/booking_details/components/practical_information_button.dart';
-import 'package:comwell_key_app/common/components/bottom_sheet_widget.dart';
import 'package:comwell_key_app/common/components/comwell_error_widget.dart';
import 'package:comwell_key_app/common/components/outlined_pill_button.dart';
import 'package:comwell_key_app/overview/models/booking.dart';
import 'package:comwell_key_app/profile/components/comwell_club_container.dart';
import 'package:comwell_key_app/routing/app_routes.dart';
+import 'package:comwell_key_app/themes/light_theme.dart';
import 'package:comwell_key_app/up_sales/components/catalog/service_catalog.dart';
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
@@ -22,105 +22,110 @@ class BookingDetailsBottomSheet extends StatelessWidget {
@override
Widget build(BuildContext context) {
final theme = Theme.of(context);
- final isActive =
- cubit.user?.isClubMember ?? false;
+ final isActive = cubit.user?.isClubMember ?? false;
- return BottomSheetWidget(
- widgetChildren: [
- const SizedBox(height: 16),
- cubit.booking.reservationStatus == ReservationStatus.checkedin &&
- cubit.getCheckOutTime().isBefore(DateTime.now())
- ? const Padding(
- padding: EdgeInsets.symmetric(horizontal: 16.0),
- child: CheckOutButton(),
- )
- : const SizedBox(),
- cubit.booking.reservationStatus == ReservationStatus.checkedin &&
- cubit.isHouseKeepingTime
- ? Column(
- crossAxisAlignment: CrossAxisAlignment.start,
- children: [
- const SizedBox(height: 16),
- Padding(
- padding: const EdgeInsets.symmetric(horizontal: 16.0),
- child: HousekeepingButton(
- key: ValueKey(state.isHouseKeepingOrdered),
- booking: cubit.booking),
- ),
- ],
- )
- : const SizedBox(),
- const SizedBox(height: 20),
- _buildUpSalesCatalogButton(cubit.booking.reservationStatus, context),
- const SizedBox(height: 20),
- Padding(
- padding: const EdgeInsets.symmetric(horizontal: 16),
- child: Text("booking_details_page_practical_information".tr(),
- style: theme.textTheme.headlineMedium),
- ),
- const SizedBox(height: 20),
- Row(children: [
- Expanded(
- child: AspectRatio(
- aspectRatio: 175 / 220,
- child: Padding(
- padding: const EdgeInsets.only(left: 16),
- child: PracticalInformationButton(
- iconPath: "assets/icons/ic_bed.svg",
- title: "booking_details_page_hotel_information_button_title"
- .tr(),
- subtitle:
- "booking_details_page_hotel_information_button_subtitle"
- .tr(),
- onClick: () {
- context.pushNamed(AppRoutes.hotelInformation.name,
- extra: cubit.booking);
- }),
+ return Container(
+ decoration: const BoxDecoration(
+ color: Colors.white,
+ borderRadius: BorderRadius.vertical(top: Radius.circular(20)),
+ ),
+ child: Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ mainAxisSize: MainAxisSize.min,
+ children: [
+ // Handle indicator
+ Center(
+ child: Container(
+ margin: const EdgeInsets.only(top: 20),
+ width: 70,
+ height: 5,
+ decoration: BoxDecoration(
+ color: colorDivider,
+ borderRadius: BorderRadius.circular(5),
),
),
),
- const SizedBox(width: 8),
- Expanded(
- child: AspectRatio(
- aspectRatio: 175 / 220,
- child: Padding(
- padding: const EdgeInsets.only(right: 16),
- child: PracticalInformationButton(
- iconPath: "assets/icons/ic_telephone.svg",
- title: "booking_details_page_contact_button_title".tr(),
- subtitle:
- "booking_details_page_contact_button_subtitle".tr(),
- onClick: () {
- context.pushNamed(AppRoutes.contact.name,
- extra: cubit.booking);
- }),
- ),
+ const SizedBox(height: 16),
+ if (cubit.booking.reservationStatus == ReservationStatus.checkedin &&
+ cubit.getCheckOutTime().isBefore(DateTime.now()))
+ const Padding(
+ padding: EdgeInsets.symmetric(horizontal: 16.0),
+ child: CheckOutButton(),
),
+ if (cubit.booking.reservationStatus == ReservationStatus.checkedin &&
+ cubit.isHouseKeepingTime)
+ Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ const SizedBox(height: 16),
+ Padding(
+ padding: const EdgeInsets.symmetric(horizontal: 16.0),
+ child: HousekeepingButton(
+ key: ValueKey(state.isHouseKeepingOrdered),
+ booking: cubit.booking),
+ ),
+ ],
+ ),
+ const SizedBox(height: 20),
+ _buildUpSalesCatalogButton(cubit.booking.reservationStatus, context),
+ const SizedBox(height: 20),
+ Padding(
+ padding: const EdgeInsets.symmetric(horizontal: 16),
+ child: Text("booking_details_page_practical_information".tr(),
+ style: theme.textTheme.headlineMedium),
),
- ]),
- const SizedBox(height: 16),
- if (!isActive && cubit.user != null)
- ComwellClubContainer(
- user: cubit.user!,
- onSignupClick: () {
- cubit.add(const InitialEvent(fetchRemote: true));
- }),
- const SizedBox(height: 16),
- // if (cubit.booking.rooms.length > 1)
- // Padding(
- // padding: const EdgeInsets.symmetric(horizontal: 16),
- // child: Text('rooms'.tr(), style: theme.textTheme.headlineMedium),
- // ),
- // const SizedBox(height: 16),
- // if (state.keys.isNotEmpty)
- // Padding(
- // padding: const EdgeInsets.symmetric(horizontal: 16),
- // child:
- // Text('room_keys'.tr(), style: theme.textTheme.headlineMedium),
- // ),
- // const SizedBox(height: 16),
- const SizedBox(height: 50),
- ],
+ const SizedBox(height: 20),
+ Row(children: [
+ Expanded(
+ child: AspectRatio(
+ aspectRatio: 175 / 220,
+ child: Padding(
+ padding: const EdgeInsets.only(left: 16),
+ child: PracticalInformationButton(
+ iconPath: "assets/icons/ic_bed.svg",
+ title:
+ "booking_details_page_hotel_information_button_title"
+ .tr(),
+ subtitle:
+ "booking_details_page_hotel_information_button_subtitle"
+ .tr(),
+ onClick: () {
+ context.pushNamed(AppRoutes.hotelInformation.name,
+ extra: cubit.booking);
+ }),
+ ),
+ ),
+ ),
+ const SizedBox(width: 8),
+ Expanded(
+ child: AspectRatio(
+ aspectRatio: 175 / 220,
+ child: Padding(
+ padding: const EdgeInsets.only(right: 16),
+ child: PracticalInformationButton(
+ iconPath: "assets/icons/ic_telephone.svg",
+ title: "booking_details_page_contact_button_title".tr(),
+ subtitle:
+ "booking_details_page_contact_button_subtitle".tr(),
+ onClick: () {
+ context.pushNamed(AppRoutes.contact.name,
+ extra: cubit.booking);
+ }),
+ ),
+ ),
+ ),
+ ]),
+ const SizedBox(height: 16),
+ if (!isActive && cubit.user != null)
+ ComwellClubContainer(
+ user: cubit.user!,
+ onSignupClick: () {
+ cubit.add(const InitialEvent(fetchRemote: true));
+ }),
+ const SizedBox(height: 16),
+ const SizedBox(height: 50),
+ ],
+ ),
);
}