6177214e-ce7c-49e3-99de-ff9721b26f63 — Commit 928f45b5

AuthorEdmir Suljic<esu@dwarf.dk>
Date2025-08-01 10:26:06 +0200
Feature almost finished. AddonItems left

Changed files

comwell_key_app/assets/icons/ic_apple_pay.svg      |   5 +
 comwell_key_app/assets/translations/da-DK.json     |   7 +-
 comwell_key_app/assets/translations/en-US.json     |   7 +-
 comwell_key_app/ios/Runner/Runner.entitlements     |   7 +-
 .../ios/Runner/RunnerRelease.entitlements          |   7 +-
 .../check_out/models/check_out_item.g.dart         |  21 ++++
 .../.generated/services/models/booking_dto.g.dart  |   4 +
 .../booking_details/bloc/booking_details_bloc.dart |  21 +++-
 .../lib/booking_details/booking_details_page.dart  |   2 +-
 .../components/booking_details_bottom_sheet.dart   |   4 +-
 .../components/check_out_button.dart               |   8 +-
 .../lib/check_in/check_in_repository.dart          |   1 +
 .../lib/check_out/bloc/check_out_cubit.dart        |  79 +++++++++----
 .../lib/check_out/bloc/check_out_state.dart        |  27 +++--
 .../lib/check_out/check_out_repository.dart        |  11 +-
 .../check_out/components/apply_club_points.dart    |  22 ++--
 .../components/change_payment_button.dart          |  95 ----------------
 .../components/check_out_bill_list_item.dart       |   4 +-
 .../components/check_out_bottom_sheet.dart         |  48 +++++++-
 .../components/checkout_itemized_bill.dart         |   2 +-
 .../components/confirm_check_out_dialog.dart       |  14 ++-
 .../lib/check_out/models/check_out_item.dart       |  21 +++-
 .../models/checkout_processing_state.dart          |   8 +-
 .../lib/check_out/models/payment_method.dart       |   4 +-
 .../lib/check_out/pages/check_out_error_page.dart  |  69 ++++++++++++
 .../check_out/pages/check_out_processing_page.dart | 124 +++------------------
 .../check_out/pages/check_out_success_page.dart    |   6 +-
 .../lib/check_out/pages/checkout_payment_page.dart |  10 +-
 comwell_key_app/lib/overview/models/booking.dart   |   8 +-
 .../overview/repository/overview_repository.dart   |   9 +-
 .../components/prereg_bottom_button.dart           |  20 +---
 .../pregistration/cubit/preregistration_cubit.dart |  10 +-
 .../pregistration/pregistration_repository.dart    |  17 ++-
 comwell_key_app/lib/profile/utils/constants.dart   |   4 +
 comwell_key_app/lib/services/api.dart              |   1 +
 .../interceptors/response_handle_interceptor.dart  | 100 +++++++++--------
 .../lib/services/mappers/booking_mapper.dart       |   3 +
 .../lib/services/models/booking_dto.dart           |   3 +
 38 files changed, 439 insertions(+), 374 deletions(-)

Diff

diff --git a/comwell_key_app/assets/icons/ic_apple_pay.svg b/comwell_key_app/assets/icons/ic_apple_pay.svg
new file mode 100644
index 00000000..0bdc26f3
--- /dev/null
+++ b/comwell_key_app/assets/icons/ic_apple_pay.svg
@@ -0,0 +1,5 @@
+<svg width="40" height="28" viewBox="0 0 40 28" fill="none" xmlns="http://www.w3.org/2000/svg">
+<rect x="0.5" y="0.5" width="39" height="27" rx="1.5" fill="white"/>
+<rect x="0.5" y="0.5" width="39" height="27" rx="1.5" stroke="#E0E0E0"/>
+<path fill-rule="evenodd" clip-rule="evenodd" d="M11.3014 10.0471C10.9615 10.4525 10.4178 10.7722 9.87398 10.7265C9.806 10.1785 10.0722 9.59613 10.3838 9.23646C10.7236 8.81971 11.3184 8.52284 11.7999 8.5C11.8565 9.0709 11.6356 9.63039 11.3014 10.0471ZM11.7913 10.835C11.3123 10.8072 10.8751 10.9802 10.5221 11.1199C10.2948 11.2098 10.1024 11.286 9.95606 11.286C9.79179 11.286 9.59144 11.2058 9.3665 11.1157C9.07174 10.9977 8.73476 10.8627 8.38137 10.8692C7.57137 10.8806 6.81801 11.3431 6.40451 12.0795C5.55486 13.5525 6.1836 15.7333 7.00493 16.9322C7.4071 17.5259 7.88857 18.1768 8.52298 18.1539C8.80208 18.1433 9.00285 18.0574 9.21063 17.9686C9.44984 17.8663 9.69833 17.76 10.0863 17.76C10.4609 17.76 10.6985 17.8635 10.9266 17.9629C11.1435 18.0573 11.3518 18.1481 11.661 18.1425C12.3181 18.1311 12.7316 17.5488 13.1338 16.955C13.5678 16.3178 13.7585 15.6959 13.7874 15.6015L13.7908 15.5906C13.7901 15.5899 13.7848 15.5874 13.7753 15.583C13.6302 15.5161 12.5213 15.0044 12.5107 13.6324C12.5 12.4807 13.3902 11.8973 13.5304 11.8054C13.5389 11.7998 13.5447 11.796 13.5473 11.7941C12.9808 10.9491 12.0972 10.8578 11.7913 10.835ZM16.3398 18.0798V9.17944H19.6535C21.3641 9.17944 22.5593 10.3669 22.5593 12.1025C22.5593 13.838 21.3415 15.0369 19.6082 15.0369H17.7106V18.0798H16.3398ZM17.7109 10.3438H19.2913C20.4808 10.3438 21.1605 10.9832 21.1605 12.1078C21.1605 13.2325 20.4808 13.8776 19.2856 13.8776H17.7109V10.3438ZM27.0883 17.0121C26.7258 17.7086 25.9271 18.1481 25.0661 18.1481C23.7916 18.1481 22.9023 17.3831 22.9023 16.2299C22.9023 15.0881 23.7633 14.4316 25.355 14.3345L27.0656 14.2318V13.7408C27.0656 13.0157 26.5955 12.6218 25.7572 12.6218C25.0661 12.6218 24.562 12.9815 24.46 13.5296H23.2252C23.2649 12.3763 24.3411 11.5371 25.7968 11.5371C27.3659 11.5371 28.3854 12.3649 28.3854 13.6494V18.0796H27.1166V17.0121H27.0883ZM25.4335 17.0925C24.7028 17.0925 24.2383 16.7385 24.2383 16.1962C24.2383 15.6367 24.6858 15.3113 25.5411 15.2599L27.0648 15.1628V15.6652C27.0648 16.4988 26.3624 17.0925 25.4335 17.0925ZM32.5941 18.4277C32.0447 19.9863 31.416 20.5001 30.0792 20.5001C29.9772 20.5001 29.6373 20.4887 29.558 20.4658V19.3982C29.643 19.4097 29.8526 19.4211 29.9602 19.4211C30.5663 19.4211 30.9062 19.1642 31.1157 18.4962L31.2404 18.1023L28.918 11.6226H30.3511L31.9654 16.8806H31.9937L33.6081 11.6226H35.0015L32.5941 18.4277Z" fill="black"/>
+</svg>
diff --git a/comwell_key_app/assets/translations/da-DK.json b/comwell_key_app/assets/translations/da-DK.json
index f8e497cb..3b3b1fe7 100644
--- a/comwell_key_app/assets/translations/da-DK.json
+++ b/comwell_key_app/assets/translations/da-DK.json
@@ -175,15 +175,18 @@
"checkout_page_payment_club_points_title": "Brug Comwell Club Point",
"checkout_page_payment_club_points_subtitle": "Du har {} point, anvend og spar {} kr.",
"checkout_page_payment_club_points_subtitle_zero": "Du har ingen point at anvende",
- "checkout_page_payment_payment_title": "Betal med {}",
+ "checkout_page_payment_payment_title": "Betal og check ud",
+ "checkout_page_confirmation": "Gå til check-out",
"accept_terms": "Accepter betingelserne",
"checkout_page_payment_dialog_title": "Er du sikker på du vil checke ud af hotellet?",
"checkout_page_payment_dialog_subtitle": "Når du bekræfter, har du 30 minutter til at forlade dit værelse.",
"checkout_page_payment_dialog_confirm": "Ja, check ud nu",
"checkout_page_payment_dialog_cancel": "Nej",
"checkout_page_processing_success_title": "Check-out bekræftet",
- "checkout_page_processing_success_subtitle": "Det check-out er nu bekræftet og du har nu 30 minutter til at forlade dit værelse. Herefter vil du ikke længere kunne bruge dit nøglekort.",
+ "checkout_page_processing_success_subtitle": "Det check-out er nu bekræftet og du har nu 30 minutter til at forlade dit værelse. Herefter vil du ikke længere kunne bruge dit nøglekort. ",
"checkout_page_processing_success_subtitle_no_digital_card": "Du er nu checket ud. Husk at aflevere din nøgle i lobbyen.",
+ "checkout_page_processing_error_title": "Check-out fejlet",
+ "checkout_page_processing_error_subtitle": "Der skete en fejl ved check-out. Du bedes henvende dig i receptionen.",
"payment_cards_title": "Betalingskort",
"payment_cards_subtitle": "For at kunne overnatte på Comwell, skal vi bruge et betalingskort.",
"payment_cards_my_cards": "Mine kort",
diff --git a/comwell_key_app/assets/translations/en-US.json b/comwell_key_app/assets/translations/en-US.json
index 8193bf15..414bbad4 100644
--- a/comwell_key_app/assets/translations/en-US.json
+++ b/comwell_key_app/assets/translations/en-US.json
@@ -178,15 +178,18 @@
"checkout_page_payment_club_points_title": "Use Comwell Club Points",
"checkout_page_payment_club_points_subtitle": "You have {} points, use them and save {} kr.",
"checkout_page_payment_club_points_subtitle_zero": "You have no points to use",
- "checkout_page_payment_payment_title": "Pay with {}",
+ "checkout_page_payment_payment_title": "Pay and check out",
+ "checkout_page_confirmation": "Go to checkout",
"accept_terms": "Accept terms and conditions",
"checkout_page_payment_dialog_title": "Are you sure you want to check out?",
"checkout_page_payment_dialog_subtitle": "When you check out, you have 30 minutes to leave your room",
"checkout_page_payment_dialog_confirm": "Yes, check out now",
"checkout_page_payment_dialog_cancel": "No",
"checkout_page_processing_success_title": "Check-out confirmed",
- "checkout_page_processing_success_subtitle": "You have 30 minutes to leave your room",
+ "checkout_page_processing_success_subtitle": "You have 30 minutes to leave your room, after which you will no longer be able to use your keycard.",
"checkout_page_processing_success_subtitle_no_digital_card": "You are now checked out. Please return your key to the reception",
+ "checkout_page_processing_error_title": "Check-out failed",
+ "checkout_page_processing_error_subtitle": "An error occurred while checking out. Please go to the reception.",
"payment_cards_title": "Payment cards",
"payment_cards_subtitle": "To stay at Comwell, we need a payment card.",
"payment_cards_my_cards": "My cards",
diff --git a/comwell_key_app/ios/Runner/Runner.entitlements b/comwell_key_app/ios/Runner/Runner.entitlements
index 0c67376e..4b666946 100644
--- a/comwell_key_app/ios/Runner/Runner.entitlements
+++ b/comwell_key_app/ios/Runner/Runner.entitlements
@@ -1,5 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
-<dict/>
+<dict>
+ <key>com.apple.developer.in-app-payments</key>
+ <array>
+ <string>merchant.ComwellHotelsECOM</string>
+ </array>
+</dict>
</plist>
diff --git a/comwell_key_app/ios/Runner/RunnerRelease.entitlements b/comwell_key_app/ios/Runner/RunnerRelease.entitlements
index 0c67376e..4b666946 100644
--- a/comwell_key_app/ios/Runner/RunnerRelease.entitlements
+++ b/comwell_key_app/ios/Runner/RunnerRelease.entitlements
@@ -1,5 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
-<dict/>
+<dict>
+ <key>com.apple.developer.in-app-payments</key>
+ <array>
+ <string>merchant.ComwellHotelsECOM</string>
+ </array>
+</dict>
</plist>
diff --git a/comwell_key_app/lib/.generated/check_out/models/check_out_item.g.dart b/comwell_key_app/lib/.generated/check_out/models/check_out_item.g.dart
new file mode 100644
index 00000000..28a2be7a
--- /dev/null
+++ b/comwell_key_app/lib/.generated/check_out/models/check_out_item.g.dart
@@ -0,0 +1,21 @@
+// GENERATED CODE - DO NOT MODIFY BY HAND
+
+part of '../../../check_out/models/check_out_item.dart';
+
+// **************************************************************************
+// JsonSerializableGenerator
+// **************************************************************************
+
+AddOnItem _$AddOnItemFromJson(Map json) => AddOnItem(
+ json['code'] as String,
+ json['description'] as String,
+ (json['quantity'] as num).toInt(),
+ json['price'] as num,
+ );
+
+Map<String, dynamic> _$AddOnItemToJson(AddOnItem instance) => <String, dynamic>{
+ 'code': instance.code,
+ 'description': instance.description,
+ 'quantity': instance.quantity,
+ 'price': instance.price,
+ };
diff --git a/comwell_key_app/lib/.generated/services/models/booking_dto.g.dart b/comwell_key_app/lib/.generated/services/models/booking_dto.g.dart
index e5f80a00..2c7fe309 100644
--- a/comwell_key_app/lib/.generated/services/models/booking_dto.g.dart
+++ b/comwell_key_app/lib/.generated/services/models/booking_dto.g.dart
@@ -25,6 +25,9 @@ BookingDTO _$BookingDTOFromJson(Map json) => BookingDTO(
totalCharge: json['totalCharge'] as num?,
balance: json['balance'] as num?,
maskedCardNumber: json['maskedCardNumber'] as String?,
+ addOnItems: (json['addOnItems'] as List<dynamic>?)
+ ?.map((e) => AddOnItem.fromJson(Map<String, dynamic>.from(e as Map)))
+ .toList(),
);
Map<String, dynamic> _$BookingDTOToJson(BookingDTO instance) =>
@@ -47,4 +50,5 @@ Map<String, dynamic> _$BookingDTOToJson(BookingDTO instance) =>
'totalCharge': instance.totalCharge,
'balance': instance.balance,
'maskedCardNumber': instance.maskedCardNumber,
+ 'addOnItems': instance.addOnItems?.map((e) => e.toJson()).toList(),
};
diff --git a/comwell_key_app/lib/booking_details/bloc/booking_details_bloc.dart b/comwell_key_app/lib/booking_details/bloc/booking_details_bloc.dart
index 1c89d08e..e74f6116 100644
--- a/comwell_key_app/lib/booking_details/bloc/booking_details_bloc.dart
+++ b/comwell_key_app/lib/booking_details/bloc/booking_details_bloc.dart
@@ -75,7 +75,6 @@ class BookingDetailsBloc
});
on<GetBookingDetailsEvent>((event, emit) async {
-
await getBookingDetails(emit, event.bookingId);
});
@@ -167,21 +166,33 @@ class BookingDetailsBloc
}
}
+ String get trimmedBalance {
+ final balance = booking.balance;
+ if (balance == null) return '';
+ if (balance == balance.toInt()) {
+ return balance.toInt().toString();
+ } else {
+ return balance.toStringAsFixed(2);
+ }
+ }
+
DateTime getCheckInTime() => booking.startDate.add(const Duration(hours: 15));
bool get canCheckOut {
final now = DateTime.now();
final today = DateTime(now.year, now.month, now.day);
- final checkInDate = DateTime(booking.startDate.year, booking.startDate.month, booking.startDate.day);
- final checkOutDate = DateTime(booking.endDate.year, booking.endDate.month, booking.endDate.day);
-
+ final checkInDate = DateTime(
+ booking.startDate.year, booking.startDate.month, booking.startDate.day);
+ final checkOutDate = DateTime(
+ booking.endDate.year, booking.endDate.month, booking.endDate.day);
+
if (checkInDate == checkOutDate) {
return false;
}
print("checkOutDate: ${checkOutDate.isAfter(today)}");
print("today: $today");
-
+
return checkOutDate.isBefore(today);
}
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 0d0b0b55..11b588c9 100644
--- a/comwell_key_app/lib/booking_details/booking_details_page.dart
+++ b/comwell_key_app/lib/booking_details/booking_details_page.dart
@@ -168,7 +168,7 @@ class BookingDetailsPage extends StatelessWidget {
),
Text(
'total_charge_value'.tr(
- args: [cubit.booking.balance.toString()]),
+ args: [cubit.trimmedBalance]),
style: theme.textTheme.headlineMedium?.copyWith(
color: Colors.white,
),
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 ca32af6d..e8abfbc6 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
@@ -24,7 +24,7 @@ class BookingDetailsBottomSheet extends StatelessWidget {
return BottomSheetWidget(
widgetChildren: [
const SizedBox(height: 16),
- cubit.booking.reservationStatus == ReservationStatus.checkedin && cubit.canCheckOut
+ cubit.booking.reservationStatus == ReservationStatus.checkedin //TODO uncomment this before merging && cubit.canCheckOut
? const Padding(
padding: EdgeInsets.symmetric(horizontal: 16.0),
child: CheckOutButton(),
@@ -79,7 +79,7 @@ class BookingDetailsBottomSheet extends StatelessWidget {
),
]),
const SizedBox(height: 16),
- if (cubit.booking.roomNumber != '')
+ if (cubit.booking.rooms.length > 1)
Padding(
padding: const EdgeInsets.symmetric(horizontal: 16),
child: Text('rooms'.tr(), style: theme.textTheme.headlineMedium),
diff --git a/comwell_key_app/lib/booking_details/components/check_out_button.dart b/comwell_key_app/lib/booking_details/components/check_out_button.dart
index 097629d4..8a2a199d 100644
--- a/comwell_key_app/lib/booking_details/components/check_out_button.dart
+++ b/comwell_key_app/lib/booking_details/components/check_out_button.dart
@@ -23,8 +23,12 @@ class CheckOutButton extends StatelessWidget {
),
child: InkWell(
borderRadius: const BorderRadius.all(Radius.circular(15)),
- onTap: () {
- context.pushNamed(AppRoutes.checkOut.name, extra: cubit.booking);
+ onTap: () async {
+
+ final result = await context.pushNamed(AppRoutes.checkOut.name, extra: cubit.booking);
+ if (result == true) {
+ cubit.add(InitialEvent());
+ }
},
child: Padding(
padding: const EdgeInsets.all(16.0),
diff --git a/comwell_key_app/lib/check_in/check_in_repository.dart b/comwell_key_app/lib/check_in/check_in_repository.dart
index 3287eeec..e39c6f72 100644
--- a/comwell_key_app/lib/check_in/check_in_repository.dart
+++ b/comwell_key_app/lib/check_in/check_in_repository.dart
@@ -74,5 +74,6 @@ class CheckInRepository {
digitalCard: true,
guests: null,
rooms: const [],
+ addOnItems: const [],
);
}
diff --git a/comwell_key_app/lib/check_out/bloc/check_out_cubit.dart b/comwell_key_app/lib/check_out/bloc/check_out_cubit.dart
index 05c9a5fe..0e85f956 100644
--- a/comwell_key_app/lib/check_out/bloc/check_out_cubit.dart
+++ b/comwell_key_app/lib/check_out/bloc/check_out_cubit.dart
@@ -1,5 +1,6 @@
import 'package:adyen_checkout/adyen_checkout.dart';
import 'package:bloc/bloc.dart';
+import 'package:comwell_key_app/booking_details/booking_details_repository.dart';
import 'package:comwell_key_app/check_out/bloc/check_out_state.dart';
import 'package:comwell_key_app/check_out/check_out_repository.dart';
import 'package:comwell_key_app/check_out/models/check_out_item.dart';
@@ -25,7 +26,7 @@ class CheckoutCubit extends Cubit<CheckoutState> {
final _tracking = locator<ComwellTracking>();
final pageController = PageController();
bool _isAnimating = false;
- final Booking booking;
+ late Booking booking;
CheckoutPage get currentPage =>
CheckoutPage.fromIndex(pageController.page?.toInt() ?? 0);
@@ -37,11 +38,10 @@ class CheckoutCubit extends Cubit<CheckoutState> {
final user = await profileRepository.fetchProfileSettings();
emit(state.clubPointsFetched(user.points));
//setItems([...state.items, CheckoutItem("Körv", 500)]);
-
} catch (e) {
// Todo handle error
- emit(state.processingStateUpdated(CheckoutProcessingStateError()));
-
+ emit(state.processingStateUpdated(
+ CheckoutProcessingStateError(message: "Error fetching club points")));
}
}
@@ -53,7 +53,7 @@ class CheckoutCubit extends Cubit<CheckoutState> {
}
}
- void setItems(Iterable<CheckoutItem> items) {
+ void setItems(Iterable<AddOnItem> items) {
emit(state.itemsUpdated(items));
}
@@ -71,8 +71,19 @@ class CheckoutCubit extends Cubit<CheckoutState> {
quantity: 1);
_tracking.trackBeginCheckout(analyticsEventItem);
emit(state.processingStateUpdated(CheckoutProcessingStateProcessing()));
- createSession();
- checkOut();
+ await createSession();
+ }
+
+ Future<void> processCheckoutWithoutPaying() async {
+ emit(state.processingStateUpdated(CheckoutProcessingStateProcessing()));
+ try {
+ await checkOutRepository.checkOut(booking.confirmationId);
+ emit(state.processingStateUpdated(CheckoutProcessingStateConfirmed()));
+ } catch (e) {
+ emit(state.processingStateUpdated(
+ CheckoutProcessingStateError(message: e.toString())));
+ await Future<void>.delayed(const Duration(milliseconds: 1000));
+ }
}
void onContinueClicked() {
@@ -80,6 +91,9 @@ class CheckoutCubit extends Cubit<CheckoutState> {
_isAnimating = true;
switch (currentPage) {
case CheckoutPage.confirmation:
+ if (booking.balance == 0) {
+ return _navigateToProcessing();
+ }
return _navigateTo(CheckoutPage.payment);
case CheckoutPage.payment:
return _navigateToProcessing();
@@ -88,10 +102,14 @@ class CheckoutCubit extends Cubit<CheckoutState> {
void _navigateToProcessing() {
_isAnimating = false;
- if (!state.isTermsAccepted) {
+ if (!state.isTermsAccepted && (booking.balance ?? 0.0) > 0.0) {
emit(state.showAcceptTermsError());
} else {
- processCheckout();
+ if (booking.balance == 0) {
+ processCheckoutWithoutPaying();
+ } else {
+ processCheckout();
+ }
}
}
@@ -134,30 +152,41 @@ class CheckoutCubit extends Cubit<CheckoutState> {
Future<void> checkOut() async {
try {
+ if (state.processingState is CheckoutProcessingStateConfirmed) {
+ booking =
+ await profileRepository.getBookingDetails(booking.confirmationId);
+ }
emit(state.processingStateUpdated(CheckoutProcessingStateProcessing()));
- await checkOutRepository.checkOut(booking.confirmationId);
+ if (booking.balance != 0) {
+ await checkOutRepository.checkOut(booking.confirmationId);
+ } else {
+ emit(state.processingStateUpdated(
+ CheckoutProcessingStateError(message: "Balance is not 0")));
+ }
+ emit(state.processingStateUpdated(CheckoutProcessingStateConfirmed()));
} catch (e) {
- emit(state.processingStateUpdated(CheckoutProcessingStateError()));
+ emit(state.processingStateUpdated(
+ CheckoutProcessingStateError(message: "Error checking out")));
+ await Future<void>.delayed(const Duration(milliseconds: 1000));
}
}
- void createSession() async {
+ Future<void> createSession() async {
try {
-
final bookingPrice = booking.balance?.toInt();
-
-
final amount = Amount(
value: bookingPrice!,
currency: currency,
);
final paymentConfigurations = await preregistrationRepository
.sessionCheckout(amount, booking.confirmationId);
- print("paymentConfigurations: ${paymentConfigurations}");
emit(state.processingStateUpdated(CheckoutProcessingStateSessionReceived(
paymentConfigurations: paymentConfigurations)));
+ await Future<void>.delayed(const Duration(milliseconds: 4000));
} catch (e) {
- emit(state.processingStateUpdated(CheckoutProcessingStateError()));
+ emit(state.processingStateUpdated(
+ CheckoutProcessingStateError(message: "Error creating session")));
+ await Future<void>.delayed(const Duration(milliseconds: 1000));
}
}
@@ -165,21 +194,23 @@ class CheckoutCubit extends Cubit<CheckoutState> {
switch (result) {
case PaymentAdvancedFinished():
case PaymentSessionFinished():
- emit(state.processingStateUpdated(CheckoutProcessingStateSuccess()));
- await Future<void>.delayed(const Duration(milliseconds: 1000));
+ emit(state
+ .processingStateUpdated(CheckoutProcessingPaymentStateSuccess()));
+ //await Future<void>.delayed(const Duration(milliseconds: 4000));
emit(state.processingStateUpdated(CheckoutProcessingStateConfirmed()));
+ await checkOut();
+
break;
case PaymentCancelledByUser():
case PaymentError():
- emit(state.processingStateUpdated(CheckoutProcessingStateError()));
+ emit(state.processingStateUpdated(
+ CheckoutProcessingStateError(message: "Error processing payment")));
await Future<void>.delayed(const Duration(milliseconds: 1000));
- emit(state.processingStateUpdated(CheckoutProcessingStateNotStarted()));
+ //emit(state.processingStateUpdated(CheckoutProcessingStateNotStarted()));
}
}
- void onPaymentMethodChanged(CheckoutPaymentMethod method) {
- emit(state.paymentMethodChanged(method));
- }
+
void onUserDismissPaymentPopup() {
emit(state.processingStateUpdated(CheckoutProcessingStateNotStarted()));
diff --git a/comwell_key_app/lib/check_out/bloc/check_out_state.dart b/comwell_key_app/lib/check_out/bloc/check_out_state.dart
index dddda4a5..7b19e8eb 100644
--- a/comwell_key_app/lib/check_out/bloc/check_out_state.dart
+++ b/comwell_key_app/lib/check_out/bloc/check_out_state.dart
@@ -5,7 +5,7 @@ import 'package:comwell_key_app/check_out/pages/check_out_page.dart';
import 'package:equatable/equatable.dart';
class CheckoutState extends Equatable {
- final Iterable<CheckoutItem> _items;
+ final Iterable<AddOnItem> _items;
final bool isTermsAccepted;
final bool applyClubPoints;
final int clubPoints;
@@ -14,21 +14,20 @@ class CheckoutState extends Equatable {
final CheckoutPaymentMethod? paymentMethod;
final bool showTermsError;
- int get totalPriceBeforeDiscount => _sumOfList(_items);
+ num get totalPriceBeforeDiscount => _sumOfList(_items);
- int get totalPriceAfterDiscount => _sumOfList(items) - clubPoints;
+ num get totalPriceAfterDiscount => _sumOfList(items);
- int get totalPrice => _sumOfList(_items);
+ num get totalPrice => _sumOfList(_items);
- Iterable<CheckoutItem> get items {
+ Iterable<AddOnItem> get items {
if (applyClubPoints) {
- return [..._items, CheckoutItem("Rabat", clubPoints * -1)];
+ return [..._items, AddOnItem("Rabat", "Rabat", clubPoints * -1, clubPoints * -1)];
}
return _items;
}
- int _sumOfList(Iterable<CheckoutItem> list) {
-
+ num _sumOfList(Iterable<AddOnItem> list) {
if (list.isEmpty) return 0;
return list
.map((item) => item.price)
@@ -36,7 +35,7 @@ class CheckoutState extends Equatable {
}
const CheckoutState({
- required Iterable<CheckoutItem> items,
+ required Iterable<AddOnItem> items,
required this.isTermsAccepted,
required this.page,
required this.showTermsError,
@@ -51,12 +50,12 @@ class CheckoutState extends Equatable {
isTermsAccepted = false,
page = CheckoutPage.confirmation,
showTermsError = false,
- clubPoints = 0,
+ clubPoints = 10,
paymentMethod = CheckoutPaymentMethod.creditCard,
processingState = CheckoutProcessingStateNotStarted(),
applyClubPoints = false;
- CheckoutState itemsUpdated(Iterable<CheckoutItem> items) =>
+ CheckoutState itemsUpdated(Iterable<AddOnItem> items) =>
_copyWith(items: items);
CheckoutState termsAccepted() => _copyWith(termsAccepted: true, showTermsError: false);
@@ -83,7 +82,7 @@ class CheckoutState extends Equatable {
CheckoutState _copyWith({
- Iterable<CheckoutItem>? items,
+ Iterable<AddOnItem>? items,
bool? termsAccepted,
bool? applyClubPoints,
CheckoutProcessingState? updateProcessingState,
@@ -103,8 +102,8 @@ class CheckoutState extends Equatable {
paymentMethod: paymentMethod ?? this.paymentMethod);
}
- static Iterable<CheckoutItem> _mockItems() =>
- [1, 2, 3].map((i) => CheckoutItem("item $i", i * 100));
+ static Iterable<AddOnItem> _mockItems() =>
+ [1, 2, 3].map((i) => AddOnItem("item $i", "item $i", 1, i * 100));
@override
diff --git a/comwell_key_app/lib/check_out/check_out_repository.dart b/comwell_key_app/lib/check_out/check_out_repository.dart
index 9c14183b..a1e50d8d 100644
--- a/comwell_key_app/lib/check_out/check_out_repository.dart
+++ b/comwell_key_app/lib/check_out/check_out_repository.dart
@@ -7,13 +7,6 @@ class CheckOutRepository {
CheckOutRepository();
Future<Json?> checkOut(String confirmationId) async {
- final response = await _api.checkOut(confirmationId);
-
- if (response?["status"] == "success") {
- return response;
- } else {
- print("here in exception: ${response?["message"]}");
- throw Exception(response?["message"]);
- }
+ return await _api.checkOut(confirmationId);
}
-}
\ No newline at end of file
+}
diff --git a/comwell_key_app/lib/check_out/components/apply_club_points.dart b/comwell_key_app/lib/check_out/components/apply_club_points.dart
index 6557cf91..7f1e3e5d 100644
--- a/comwell_key_app/lib/check_out/components/apply_club_points.dart
+++ b/comwell_key_app/lib/check_out/components/apply_club_points.dart
@@ -22,7 +22,10 @@ class ApplyClubPoints extends StatelessWidget {
Text(
cubit.state.clubPoints > 0
? "checkout_page_payment_club_points_subtitle".tr(
- args: ["${cubit.state.clubPoints}", "${cubit.state.clubPoints}"],
+ args: [
+ "${cubit.state.clubPoints}",
+ "${cubit.state.clubPoints}"
+ ],
)
: "checkout_page_payment_club_points_subtitle_zero".tr(),
style: TextStyle(color: colorBlack[65]),
@@ -32,13 +35,16 @@ class ApplyClubPoints extends StatelessWidget {
),
const SizedBox(width: 20),
if (cubit.state.clubPoints > 0)
- Switch(
- value: cubit.state.applyClubPoints,
- activeColor: sandColor[80],
- onChanged: (value) {
- cubit.onApplyClubPointsClicked(value);
- },
- )
+ Switch(
+ value: cubit.state.applyClubPoints,
+ activeColor: sandColor[80],
+ inactiveTrackColor: Colors.grey[200],
+ inactiveThumbColor: Colors.white,
+ trackOutlineColor: const WidgetStatePropertyAll(Colors.white),
+ onChanged: (value) {
+ cubit.onApplyClubPointsClicked(value);
+ },
+ )
],
);
}
diff --git a/comwell_key_app/lib/check_out/components/change_payment_button.dart b/comwell_key_app/lib/check_out/components/change_payment_button.dart
deleted file mode 100644
index 803fcc00..00000000
--- a/comwell_key_app/lib/check_out/components/change_payment_button.dart
+++ /dev/null
@@ -1,95 +0,0 @@
-import 'package:comwell_key_app/check_out/bloc/check_out_cubit.dart';
-import 'package:comwell_key_app/check_out/models/payment_method.dart';
-import 'package:comwell_key_app/themes/light_theme.dart';
-import 'package:easy_localization/easy_localization.dart';
-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';
-
-class ChangePaymentButton extends StatelessWidget {
- const ChangePaymentButton({super.key});
-
- void _showPaymentPicker(BuildContext context) async {
- final cubit = context.read<CheckoutCubit>();
- final Iterable<CheckoutPaymentMethod?> listItems = [
- CheckoutPaymentMethod.creditCard,
- null,
- CheckoutPaymentMethod.appleOrGooglePay
- ];
- final response = await showModalBottomSheet<dynamic>(
- context: context,
- builder: (context) {
- return Padding(
- padding: const EdgeInsets.symmetric(vertical: 16.0),
- child: Column(
- mainAxisSize: MainAxisSize.min,
- children: [
- ...listItems.map((item) {
- if (item == null) {
- return const Divider(
- color: colorDivider,
- indent: 16,
- endIndent: 16,
- );
- }
- return InkWell(
- onTap: () {
- context.pop(item);
- },
- child: Padding(
- padding: const EdgeInsets.symmetric(
- vertical: 16,
- horizontal: 16,
- ),
- child: Row(
- mainAxisAlignment: MainAxisAlignment.center,
- children: [
- item.iconWidget,
- const SizedBox(width: 32),
- Text(item.stringId.tr()),
- ],
- ),
- ),
- );
- }),
- ],
- ),
- );
- });
- if (response is CheckoutPaymentMethod) {
- cubit.onPaymentMethodChanged(response);
- }
- }
-
- @override
- Widget build(BuildContext context) {
- final cubit = context.read<CheckoutCubit>();
- final paymentMethod = cubit.state.paymentMethod!;
- return InkWell(
- onTap: () async {
- _showPaymentPicker(context);
- },
- child: Container(
- decoration: BoxDecoration(
- border: Border.all(color: colorDivider),
- ),
- padding: const EdgeInsets.all(12),
- child: Row(
- crossAxisAlignment: CrossAxisAlignment.center,
- children: [
- paymentMethod.iconWidget,
- const SizedBox(width: 12),
- Text(
- "checkout_page_payment_payment_title"
- .tr(args: [paymentMethod.stringId.tr()]),
- style: Theme.of(context).textTheme.bodyMedium,
- ),
- const Expanded(child: SizedBox()),
- SvgPicture.asset("assets/icons/arrow-left.svg"),
- ],
- ),
- ),
- );
- }
-}
diff --git a/comwell_key_app/lib/check_out/components/check_out_bill_list_item.dart b/comwell_key_app/lib/check_out/components/check_out_bill_list_item.dart
index ccacc303..cf45446c 100644
--- a/comwell_key_app/lib/check_out/components/check_out_bill_list_item.dart
+++ b/comwell_key_app/lib/check_out/components/check_out_bill_list_item.dart
@@ -2,7 +2,7 @@ import 'package:comwell_key_app/check_out/models/check_out_item.dart';
import 'package:flutter/material.dart';
class CheckOutBillListItem extends StatelessWidget {
- final CheckoutItem item;
+ final AddOnItem item;
const CheckOutBillListItem({super.key, required this.item});
@@ -13,7 +13,7 @@ class CheckOutBillListItem extends StatelessWidget {
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
- item.name,
+ item.code,
style: Theme.of(context).textTheme.bodyMedium,
),
Text(
diff --git a/comwell_key_app/lib/check_out/components/check_out_bottom_sheet.dart b/comwell_key_app/lib/check_out/components/check_out_bottom_sheet.dart
index 03c8ba1e..e63658d0 100644
--- a/comwell_key_app/lib/check_out/components/check_out_bottom_sheet.dart
+++ b/comwell_key_app/lib/check_out/components/check_out_bottom_sheet.dart
@@ -1,4 +1,7 @@
+import 'dart:io';
+
import 'package:comwell_key_app/check_out/bloc/check_out_cubit.dart';
+import 'package:comwell_key_app/check_out/models/payment_method.dart';
import 'package:comwell_key_app/themes/light_theme.dart';
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
@@ -14,6 +17,7 @@ class CheckOutBottomSheet extends StatelessWidget {
Widget build(BuildContext context) {
final cubit = context.read<CheckoutCubit>();
final paymentMethod = cubit.state.paymentMethod!;
+ final theme = Theme.of(context);
return Container(
decoration:
const BoxDecoration(shape: BoxShape.rectangle, color: Colors.white),
@@ -30,7 +34,18 @@ class CheckOutBottomSheet extends StatelessWidget {
child: Builder(builder: (context) {
if (cubit.state.page == CheckoutPage.confirmation) {
return ElevatedButton(
- onPressed: cubit.onContinueClicked,
+ onPressed: cubit.booking.balance == 0
+ ? () async {
+ await showDialog<void>(
+ context: context,
+ builder: (context) =>
+ ConfirmCheckOutDialog(onConfirm: () {
+ Navigator.of(context).pop();
+ cubit.onContinueClicked();
+ }),
+ );
+ }
+ : cubit.onContinueClicked,
style: ButtonStyle(
backgroundColor:
WidgetStatePropertyAll(sandColor[100]),
@@ -39,7 +54,12 @@ class CheckOutBottomSheet extends StatelessWidget {
child: Padding(
padding: const EdgeInsets.symmetric(vertical: 17.0),
child: Text(
- "checkout_page_confirmation_continue".tr()),
+ cubit.booking.balance == 0
+ ? "checkout_page_confirmation".tr()
+ : "checkout_page_confirmation_continue".tr(),
+ style: theme.textTheme.bodyMedium
+ ?.copyWith(color: Colors.white),
+ ),
));
} else {
return OutlinedButton(
@@ -53,10 +73,30 @@ class CheckOutBottomSheet extends StatelessWidget {
}),
);
},
+ style: ButtonStyle(
+ backgroundColor: paymentMethod ==
+ CheckoutPaymentMethod
+ .appleOrGooglePay &&
+ Platform.isIOS
+ ? const WidgetStatePropertyAll(Colors.black)
+ : Platform.isAndroid &&
+ paymentMethod ==
+ CheckoutPaymentMethod
+ .appleOrGooglePay
+ ? const WidgetStatePropertyAll(
+ Colors.white)
+ : const WidgetStatePropertyAll(sandColor),
+ foregroundColor:
+ const WidgetStatePropertyAll(Colors.white),
+ side: const WidgetStatePropertyAll(
+ BorderSide(color: colorDivider))),
child: Padding(
padding: const EdgeInsets.symmetric(vertical: 17.0),
- child: Text("checkout_page_payment_payment_title"
- .tr(args: [paymentMethod.stringId.tr()])),
+ child: Text(
+ "checkout_page_payment_payment_title".tr(),
+ style: theme.textTheme.bodyMedium
+ ?.copyWith(color: Colors.white),
+ ),
));
}
}),
diff --git a/comwell_key_app/lib/check_out/components/checkout_itemized_bill.dart b/comwell_key_app/lib/check_out/components/checkout_itemized_bill.dart
index e0609efc..3fa9025c 100644
--- a/comwell_key_app/lib/check_out/components/checkout_itemized_bill.dart
+++ b/comwell_key_app/lib/check_out/components/checkout_itemized_bill.dart
@@ -41,7 +41,7 @@ class CheckoutItemizedBill extends StatelessWidget {
color: colorDivider),
),
const SizedBox(width: 4),
- Text("${cubit.state.totalPriceAfterDiscount - cubit.state.clubPoints}"),
+ Text("${cubit.state.totalPriceAfterDiscount}"),
],
)
else
diff --git a/comwell_key_app/lib/check_out/components/confirm_check_out_dialog.dart b/comwell_key_app/lib/check_out/components/confirm_check_out_dialog.dart
index de89d638..0124ae90 100644
--- a/comwell_key_app/lib/check_out/components/confirm_check_out_dialog.dart
+++ b/comwell_key_app/lib/check_out/components/confirm_check_out_dialog.dart
@@ -2,7 +2,6 @@ import 'package:comwell_key_app/themes/light_theme.dart';
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
-
class ConfirmCheckOutDialog extends StatelessWidget {
final VoidCallback onConfirm;
@@ -10,6 +9,7 @@ class ConfirmCheckOutDialog extends StatelessWidget {
@override
Widget build(BuildContext context) {
+ final theme = Theme.of(context);
return Dialog(
backgroundColor: Colors.white,
child: Padding(
@@ -25,10 +25,7 @@ class ConfirmCheckOutDialog extends StatelessWidget {
Text(
"checkout_page_payment_dialog_subtitle".tr(),
textAlign: TextAlign.center,
- style: Theme.of(context)
- .textTheme
- .bodySmall
- ?.copyWith(color: colorBlack[65]),
+ style: theme.textTheme.bodySmall?.copyWith(color: colorBlack[65]),
),
const SizedBox(height: 32),
Row(
@@ -44,6 +41,8 @@ class ConfirmCheckOutDialog extends StatelessWidget {
padding: const EdgeInsets.symmetric(vertical: 17.0),
child: Text(
"checkout_page_payment_dialog_confirm".tr(),
+ style: theme.textTheme.bodyMedium
+ ?.copyWith(color: Colors.white),
),
),
),
@@ -59,10 +58,13 @@ class ConfirmCheckOutDialog extends StatelessWidget {
Navigator.of(context).pop();
},
style: const ButtonStyle(
+ side: WidgetStatePropertyAll(
+ BorderSide(color: colorDivider)),
backgroundColor: WidgetStatePropertyAll(Colors.white)),
child: Padding(
padding: const EdgeInsets.symmetric(vertical: 17.0),
- child: Text("checkout_page_payment_dialog_cancel".tr()),
+ child: Text("checkout_page_payment_dialog_cancel".tr(),
+ style: theme.textTheme.bodyMedium),
),
),
),
diff --git a/comwell_key_app/lib/check_out/models/check_out_item.dart b/comwell_key_app/lib/check_out/models/check_out_item.dart
index 96547382..e3568b54 100644
--- a/comwell_key_app/lib/check_out/models/check_out_item.dart
+++ b/comwell_key_app/lib/check_out/models/check_out_item.dart
@@ -1,11 +1,22 @@
-class CheckoutItem {
- final String name;
- final int price;
+import 'package:json_annotation/json_annotation.dart';
- CheckoutItem(this.name, this.price);
+part '../../.generated/check_out/models/check_out_item.g.dart';
+
+@JsonSerializable()
+class AddOnItem {
+ final String code;
+ final String description;
+ final int quantity;
+ final num price;
+
+ AddOnItem(this.code, this.description, this.quantity, this.price);
@override
String toString() {
- return 'CheckoutItem{name: $name, price: $price}';
+ return 'AddOnItem{code: $code, description: $description, quantity: $quantity, price: $price}';
}
+
+ factory AddOnItem.fromJson(Map<String, dynamic> json) => _$AddOnItemFromJson(json);
+
+ Map<String, dynamic> toJson() => _$AddOnItemToJson(this);
}
\ No newline at end of file
diff --git a/comwell_key_app/lib/check_out/models/checkout_processing_state.dart b/comwell_key_app/lib/check_out/models/checkout_processing_state.dart
index dd351f00..8f552073 100644
--- a/comwell_key_app/lib/check_out/models/checkout_processing_state.dart
+++ b/comwell_key_app/lib/check_out/models/checkout_processing_state.dart
@@ -12,8 +12,12 @@ class CheckoutProcessingStateSessionReceived extends CheckoutProcessingState {
CheckoutProcessingStateSessionReceived({required this.paymentConfigurations});
}
-class CheckoutProcessingStateSuccess extends CheckoutProcessingState {}
+class CheckoutProcessingPaymentStateSuccess extends CheckoutProcessingState {}
class CheckoutProcessingStateConfirmed extends CheckoutProcessingState {}
-class CheckoutProcessingStateError extends CheckoutProcessingState {}
+class CheckoutProcessingStateError extends CheckoutProcessingState {
+ final String message;
+
+ CheckoutProcessingStateError({required this.message});
+}
diff --git a/comwell_key_app/lib/check_out/models/payment_method.dart b/comwell_key_app/lib/check_out/models/payment_method.dart
index 76ad72a4..406d1808 100644
--- a/comwell_key_app/lib/check_out/models/payment_method.dart
+++ b/comwell_key_app/lib/check_out/models/payment_method.dart
@@ -9,8 +9,8 @@ enum CheckoutPaymentMethod {
Widget get iconWidget {
if (this == CheckoutPaymentMethod.creditCard) return SvgPicture.asset("assets/icons/ic_card.svg");
- if (Platform.isIOS) return const Icon(Icons.apple);
- return SvgPicture.asset("assets/icons/ic_google.svg");
+ if (Platform.isIOS) return const Icon(Icons.apple, size: 24);
+ return SvgPicture.asset("assets/icons/ic_google.svg", width: 20, height: 20);
}
String get stringId {
diff --git a/comwell_key_app/lib/check_out/pages/check_out_error_page.dart b/comwell_key_app/lib/check_out/pages/check_out_error_page.dart
new file mode 100644
index 00000000..3152a987
--- /dev/null
+++ b/comwell_key_app/lib/check_out/pages/check_out_error_page.dart
@@ -0,0 +1,69 @@
+import 'package:comwell_key_app/check_out/bloc/check_out_cubit.dart';
+import 'package:comwell_key_app/check_out/components/check_out_countdown.dart';
+import 'package:comwell_key_app/themes/light_theme.dart';
+import 'package:easy_localization/easy_localization.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter_bloc/flutter_bloc.dart';
+import 'package:go_router/go_router.dart';
+
+class CheckOutErrorPage extends StatelessWidget {
+ final String message;
+ const CheckOutErrorPage({super.key, required this.message});
+
+ @override
+ Widget build(BuildContext context) {
+ final booking = context.read<CheckoutCubit>().booking;
+
+ return Padding(
+ padding: const EdgeInsets.symmetric(horizontal: 16.0),
+ child: Padding(
+ padding: const EdgeInsets.symmetric(vertical: 40.0),
+ child: Column(
+ crossAxisAlignment: CrossAxisAlignment.center,
+ mainAxisAlignment: MainAxisAlignment.spaceBetween,
+ children: [
+ const SizedBox(),
+ Column(
+ children: [
+ Text(
+ "checkout_page_processing_error_title".tr(),
+ style: Theme.of(context)
+ .textTheme
+ .headlineMedium
+ ?.copyWith(color: Colors.white),
+ ),
+ Text(
+ message,
+ textAlign: TextAlign.center,
+ style: Theme.of(context)
+ .textTheme
+ .bodySmall
+ ?.copyWith(color: colorDivider))
+ ],
+ ),
+ Row(
+ children: [
+ Expanded(
+ child: ElevatedButton(
+ onPressed: () {
+ context.pop();
+ },
+ style: const ButtonStyle(
+ backgroundColor:
+ WidgetStatePropertyAll(Colors.white)),
+ child: Padding(
+ padding: const EdgeInsets.all(16.0),
+ child: Text(
+ "generic_ok".tr(),
+ style: const TextStyle(color: Colors.black),
+ ),
+ )),
+ ),
+ ],
+ )
+ ],
+ ),
+ ),
+ );
+ }
+}
diff --git a/comwell_key_app/lib/check_out/pages/check_out_processing_page.dart b/comwell_key_app/lib/check_out/pages/check_out_processing_page.dart
index 48bc3ad0..48c67326 100644
--- a/comwell_key_app/lib/check_out/pages/check_out_processing_page.dart
+++ b/comwell_key_app/lib/check_out/pages/check_out_processing_page.dart
@@ -4,6 +4,7 @@ import 'package:adyen_checkout/adyen_checkout.dart';
import 'package:comwell_key_app/check_out/bloc/check_out_cubit.dart';
import 'package:comwell_key_app/check_out/models/checkout_processing_state.dart';
import 'package:comwell_key_app/check_out/models/payment_method.dart';
+import 'package:comwell_key_app/check_out/pages/check_out_error_page.dart';
import 'package:comwell_key_app/check_out/pages/check_out_success_page.dart';
import 'package:comwell_key_app/themes/dark_theme.dart';
import 'package:comwell_key_app/utils/lottie_utils.dart';
@@ -49,8 +50,14 @@ class _CheckOutProcessingPageState extends State<CheckOutProcessingPage>
);
}
- void playError() {
- loadingComposition?.playBetween(animationController, "error");
+ void playError() async {
+ loadingComposition?.playBetween(
+ animationController,
+ "error",
+ repeat: true,
+ );
+ await Future<void>.delayed(const Duration(seconds: 1));
+ if (mounted) Navigator.of(context).pop();
}
void playSuccess() async {
@@ -66,117 +73,18 @@ class _CheckOutProcessingPageState extends State<CheckOutProcessingPage>
void showAdyenModal(BuildContext context) async {
final cubit = context.read<CheckoutCubit>();
final processingState = cubit.state.processingState;
- final paymentMethod = cubit.state.paymentMethod;
dynamic response;
if (processingState is! CheckoutProcessingStateSessionReceived) return;
final paymentConfig = processingState.paymentConfigurations;
if (!mounted) return;
- if (paymentMethod == CheckoutPaymentMethod.creditCard) {
- final dropInConfig = paymentConfig.dropInConfiguration;
- response = await AdyenCheckout.session.startDropIn(
- dropInConfiguration: dropInConfig,
- checkout: paymentConfig.sessionCheckout,
- );
- } else {
- if (Platform.isIOS) {
- await _showApplePay(context, paymentConfig.sessionCheckout,
- paymentConfig.applePayConfiguration);
- } else {
- await _showGooglePlayComponent(context, paymentConfig.sessionCheckout,
- paymentConfig.googlePayConfiguration);
- }
- }
- if (!mounted) return;
- if (response is PaymentResult) {
- cubit.onPaymentResult(response);
- } else {
- cubit.onUserDismissPaymentPopup();
- }
- }
- Future<void> _showApplePay(
- BuildContext context,
- SessionCheckout session,
- ApplePayComponentConfiguration applePayComponentConfiguration,
- ) async {
- final cubit = context.read<CheckoutCubit>();
- await Future<void>.delayed(const Duration(milliseconds: 500));
- if (!context.mounted) return;
- final response = await showModalBottomSheet<dynamic>(
- context: context,
- builder: (context) {
- return Padding(
- padding: const EdgeInsets.all(16.0),
- child: Row(
- mainAxisAlignment: MainAxisAlignment.center,
- children: [
- AdyenApplePayComponent(
- configuration: applePayComponentConfiguration,
- checkout: session,
- width: 200,
- loadingIndicator: const CircularProgressIndicator(),
- paymentMethod: const {
- "type": "applepay",
- "name": "Apple Pay",
- "brands": ["mc", "visa"]
- },
- onPaymentResult: (result) {
- context.pop(result);
- },
- onUnavailable: () {
- debugPrint("qqq unavailable");
- },
- ),
- const SizedBox(height: 100),
- ],
- ),
- );
- },
+ final dropInConfig = paymentConfig.dropInConfiguration;
+ response = await AdyenCheckout.session.startDropIn(
+ dropInConfiguration: dropInConfig,
+ checkout: paymentConfig.sessionCheckout,
);
- if (response is PaymentResult) {
- cubit.onPaymentResult(response);
- } else {
- cubit.onUserDismissPaymentPopup();
- }
- }
- Future<void> _showGooglePlayComponent(
- BuildContext context,
- SessionCheckout session,
- GooglePayComponentConfiguration googlePayComponentConfiguration,
- ) async {
- final cubit = context.read<CheckoutCubit>();
- await Future<void>.delayed(const Duration(milliseconds: 500));
- if (!context.mounted) return;
- final response = await showModalBottomSheet<dynamic>(
- context: context,
- builder: (context) {
- return Padding(
- padding: const EdgeInsets.all(16.0),
- child: Row(
- mainAxisAlignment: MainAxisAlignment.center,
- children: [
- AdyenGooglePayComponent(
- configuration: googlePayComponentConfiguration,
- loadingIndicator: const CircularProgressIndicator(),
- paymentMethod: const {
- "type": "googlepay",
- "name": "Google Pay",
- "configuration": {
- "merchantId": 50,
- "gatewayMerchantId": "ComwellHotelsECOM"
- }
- },
- onPaymentResult: (result) {
- context.pop(result);
- },
- checkout: session,
- ),
- ],
- ),
- );
- },
- );
+ if (!mounted) return;
if (response is PaymentResult) {
cubit.onPaymentResult(response);
} else {
@@ -195,6 +103,8 @@ class _CheckOutProcessingPageState extends State<CheckOutProcessingPage>
final processingState = cubit.state.processingState;
if (processingState is CheckoutProcessingStateConfirmed) {
return const CheckOutSuccessPage();
+ } else if (processingState is CheckoutProcessingStateError) {
+ return CheckOutErrorPage(message: processingState.message);
} else if (processingState
is CheckoutProcessingStateSessionReceived) {
showAdyenModal(context);
@@ -207,7 +117,7 @@ class _CheckOutProcessingPageState extends State<CheckOutProcessingPage>
loadingComposition = composition;
animationController.duration = composition.duration;
switch (cubit.state.processingState) {
- case CheckoutProcessingStateSuccess _:
+ case CheckoutProcessingStateConfirmed _:
playSuccess();
case CheckoutProcessingStateError _:
playError();
diff --git a/comwell_key_app/lib/check_out/pages/check_out_success_page.dart b/comwell_key_app/lib/check_out/pages/check_out_success_page.dart
index 514c6bf4..efe3b7e8 100644
--- a/comwell_key_app/lib/check_out/pages/check_out_success_page.dart
+++ b/comwell_key_app/lib/check_out/pages/check_out_success_page.dart
@@ -1,5 +1,6 @@
import 'package:comwell_key_app/check_out/bloc/check_out_cubit.dart';
import 'package:comwell_key_app/check_out/components/check_out_countdown.dart';
+import 'package:comwell_key_app/themes/light_theme.dart';
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
@@ -36,10 +37,11 @@ class CheckOutSuccessPage extends StatelessWidget {
? "checkout_page_processing_success_subtitle".tr()
: "checkout_page_processing_success_subtitle_no_digital_card"
.tr(),
+ textAlign: TextAlign.center,
style: Theme.of(context)
.textTheme
.bodySmall
- ?.copyWith(color: const Color(0xBBFFFFFF)))
+ ?.copyWith(color: colorDivider))
],
),
Row(
@@ -47,7 +49,7 @@ class CheckOutSuccessPage extends StatelessWidget {
Expanded(
child: ElevatedButton(
onPressed: () {
- context.pop();
+ context.pop(true);
},
style: const ButtonStyle(
backgroundColor:
diff --git a/comwell_key_app/lib/check_out/pages/checkout_payment_page.dart b/comwell_key_app/lib/check_out/pages/checkout_payment_page.dart
index 1ace62a3..500bdf47 100644
--- a/comwell_key_app/lib/check_out/pages/checkout_payment_page.dart
+++ b/comwell_key_app/lib/check_out/pages/checkout_payment_page.dart
@@ -1,7 +1,6 @@
import 'package:comwell_key_app/check_out/components/accept_terms_toggle.dart';
import 'package:comwell_key_app/check_out/components/apply_club_points.dart';
import 'package:comwell_key_app/check_out/components/checkout_itemized_bill.dart';
-import 'package:comwell_key_app/check_out/components/change_payment_button.dart';
import 'package:comwell_key_app/themes/light_theme.dart';
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
@@ -12,6 +11,11 @@ class CheckoutPaymentPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
+ // Calculate dynamic bottom padding to account for bottom sheet
+ const bottomSheetHeight = 120.0; // Approximate height of bottom sheet
+ final safeAreaBottom = MediaQuery.of(context).padding.bottom;
+ final dynamicBottomPadding = bottomSheetHeight + safeAreaBottom + 20.0; // Extra 20px for comfort
+
return SingleChildScrollView(
key: PageStorageKey("$runtimeType"),
child: Padding(
@@ -31,10 +35,8 @@ class CheckoutPaymentPage extends StatelessWidget {
const SizedBox(height: 20),
const Divider(color: colorDivider),
const SizedBox(height: 20),
- const ChangePaymentButton(),
- const SizedBox(height: 30),
const AcceptTermsToggle(),
- const SizedBox(height: 100),
+ SizedBox(height: dynamicBottomPadding),
],
),
),
diff --git a/comwell_key_app/lib/overview/models/booking.dart b/comwell_key_app/lib/overview/models/booking.dart
index 7b889ebf..d72e7004 100644
--- a/comwell_key_app/lib/overview/models/booking.dart
+++ b/comwell_key_app/lib/overview/models/booking.dart
@@ -1,3 +1,4 @@
+import 'package:comwell_key_app/check_out/models/check_out_item.dart';
import 'package:comwell_key_app/overview/models/guest.dart';
import 'package:comwell_key_app/overview/models/payment_details.dart';
import 'package:comwell_key_app/overview/models/room.dart';
@@ -25,6 +26,7 @@ class Booking extends Equatable {
final num? balance;
final String? maskedCardNumber;
final List<Room> rooms;
+ final List<AddOnItem>? addOnItems;
Booking({
required this.id,
@@ -48,6 +50,7 @@ class Booking extends Equatable {
required this.maskedCardNumber,
required this.rooms,
Iterable<Guest>? guests,
+ this.addOnItems,
}) : guests = _ensureBookerInGuestList(booker, guests ?? []);
static Iterable<Guest> _ensureBookerInGuestList(
@@ -64,7 +67,7 @@ class Booking extends Equatable {
@override
String toString() {
- return "Booking(id: $id, confirmationId: $confirmationId, roomNumber: $roomNumber, startDate: $startDate, endDate: $endDate, status: $bookingStatus, reservationStatus: $reservationStatus, image: $image, hotelName: $hotelName, hotelCode: $hotelCode, roomType: $roomType, adults: $adults, children: $children, booker: $booker, bookingDate: $bookingDate, digitalCard: $digitalCard, guests: $guests)";
+ return "Booking(id: $id, confirmationId: $confirmationId, roomNumber: $roomNumber, startDate: $startDate, endDate: $endDate, status: $bookingStatus, reservationStatus: $reservationStatus, image: $image, hotelName: $hotelName, hotelCode: $hotelCode, roomType: $roomType, adults: $adults, children: $children, booker: $booker, bookingDate: $bookingDate, digitalCard: $digitalCard, guests: $guests, addOnItems: $addOnItems)";
}
@override
@@ -88,6 +91,7 @@ class Booking extends Equatable {
maskedCardNumber,
reservationStatus,
rooms,
+ addOnItems,
];
Booking copyWith({
@@ -111,6 +115,7 @@ class Booking extends Equatable {
Iterable<Guest>? guests,
num? totalCharge,
List<Room>? rooms,
+ List<AddOnItem>? addOnItems,
}) {
return Booking(
id: id ?? this.id,
@@ -134,6 +139,7 @@ class Booking extends Equatable {
balance: balance,
maskedCardNumber: maskedCardNumber,
rooms: rooms ?? this.rooms,
+ addOnItems: addOnItems ?? this.addOnItems,
);
}
diff --git a/comwell_key_app/lib/overview/repository/overview_repository.dart b/comwell_key_app/lib/overview/repository/overview_repository.dart
index fa13b46a..fffcbfda 100644
--- a/comwell_key_app/lib/overview/repository/overview_repository.dart
+++ b/comwell_key_app/lib/overview/repository/overview_repository.dart
@@ -1,3 +1,4 @@
+import 'package:comwell_key_app/check_out/models/check_out_item.dart';
import 'package:comwell_key_app/choose_share_room/choose_share_room_repository.dart';
import 'package:comwell_key_app/database/comwell_db.dart';
import 'package:comwell_key_app/overview/models/booking.dart';
@@ -57,7 +58,8 @@ class OverviewRepository {
children: 5,
totalCharge: 12345,
balance: 0,
- maskedCardNumber: "1234567890");
+ maskedCardNumber: "1234567890",
+ addOnItems: [AddOnItem("addOnItem1", "addOnItem1", 1, 100), AddOnItem("addOnItem2", "addOnItem2", 1, 200), AddOnItem("addOnItem3", "addOnItem3", 1, 300)]);
return dto.toBooking(user.id, BookingStatus.current, []);
}
}
@@ -91,5 +93,6 @@ final mockBookings = [1, 2, 3].map((i) => Booking(
guests: 3,
imageAssets: ["roomImageAsset$i"],
roomFacilities: [],
- tags: ["10 M2"])
- ]));
+ tags: ["10 M2"]),
+ ],
+ addOnItems: [AddOnItem("addOnItem$i", "addOnItem$i", 1, 100)]));
diff --git a/comwell_key_app/lib/pregistration/components/prereg_bottom_button.dart b/comwell_key_app/lib/pregistration/components/prereg_bottom_button.dart
index 438ce69f..e572eb40 100644
--- a/comwell_key_app/lib/pregistration/components/prereg_bottom_button.dart
+++ b/comwell_key_app/lib/pregistration/components/prereg_bottom_button.dart
@@ -13,7 +13,6 @@ class PreregBottomButton extends StatelessWidget {
return Builder(builder: (context) {
if (loading) return const SizedBox();
return Column(
- // BOTTOM NAVIGATION
mainAxisSize: MainAxisSize.min,
children: [
Row(
@@ -22,19 +21,12 @@ class PreregBottomButton extends StatelessWidget {
child: Padding(
padding: const EdgeInsets.fromLTRB(16.0, 16.0, 16.0, 40.0),
child: ElevatedButton(
- onPressed: cubit.canContinue
- ? () => cubit.onContinueClicked(context)
- : null,
- style: ButtonStyle(
- backgroundColor:
- WidgetStateProperty.resolveWith((states) {
- if (states.contains(WidgetState.disabled)) {
- return Colors.grey;
- }
- return sandColor;
- }),
- foregroundColor:
- const WidgetStatePropertyAll(Colors.white)),
+ onPressed:
+ () => cubit.onContinueClicked(context),
+
+ style: ElevatedButton.styleFrom(
+ backgroundColor: sandColor,
+ foregroundColor: Colors.white),
child: Padding(
padding: const EdgeInsets.symmetric(vertical: 16.0),
child: Text(buttonText),
diff --git a/comwell_key_app/lib/pregistration/cubit/preregistration_cubit.dart b/comwell_key_app/lib/pregistration/cubit/preregistration_cubit.dart
index 6848ca94..53a8e016 100644
--- a/comwell_key_app/lib/pregistration/cubit/preregistration_cubit.dart
+++ b/comwell_key_app/lib/pregistration/cubit/preregistration_cubit.dart
@@ -74,10 +74,10 @@ class PreregistrationCubit extends Cubit<PreregistrationState> {
emit(state.copyWith(isLoading: true, error: null));
try {
final user = await _profileRepository.fetchProfileSettings();
- addressTextController.text = "Bernard Bangs Alle 25";
- postalCodeTextController.text = "2000";
- cityTextController.text = "Copenhagen";
- selectedCountry = "DK";
+ addressTextController.text = user.address.street;
+ postalCodeTextController.text = user.address.zipCode;
+ cityTextController.text = user.address.city;
+ selectedCountry = user.address.country;
countryCode = getCountryCodeFromPhoneNumber(user.phoneNumber).$1;
phoneNumber = getCountryCodeFromPhoneNumber(user.phoneNumber).$2;
@@ -85,7 +85,7 @@ class PreregistrationCubit extends Cubit<PreregistrationState> {
firstNameTextController.text = user.firstName;
lastNameTextController.text = user.lastName;
emailTextController.text = user.email;
- phoneNumberTextController.text = "701234567";
+ phoneNumberTextController.text = user.phoneNumber;
upSales = await _upSalesRepository.getMockUpSales();
diff --git a/comwell_key_app/lib/pregistration/pregistration_repository.dart b/comwell_key_app/lib/pregistration/pregistration_repository.dart
index 12b0a744..31b63a6c 100644
--- a/comwell_key_app/lib/pregistration/pregistration_repository.dart
+++ b/comwell_key_app/lib/pregistration/pregistration_repository.dart
@@ -1,5 +1,6 @@
import 'package:adyen_checkout/adyen_checkout.dart';
import 'package:comwell_key_app/check_out/models/payment_configurations.dart';
+import 'package:comwell_key_app/profile/utils/constants.dart';
import 'package:comwell_key_app/profile_settings/repostiory/profile_settings_repository.dart';
import 'package:comwell_key_app/services/adyen/stored_payment_method.dart';
import 'package:comwell_key_app/services/api.dart';
@@ -22,18 +23,21 @@ class PreregistrationRepository {
final id = sessionResponse["id"] as String;
final sessionData = sessionResponse["sessionData"] as String;
+ // Use the server response amount for consistency across all payment methods
+ final serverAmount = Amount(value: sessionResponse["amount"]["value"] as int, currency: "DKK");
+
final session = await AdyenCheckout.session.create(
sessionId: id,
sessionData: sessionData,
- configuration: dropInConfiguration(Amount(value: sessionResponse["amount"]["value"] as int, currency: "DKK"), clientKey));
+ configuration: dropInConfiguration(serverAmount, clientKey));
return PaymentConfigurations(
sessionCheckout: session,
googlePayConfiguration: _getGooglePayComponentConfig(clientKey),
- dropInConfiguration: dropInConfiguration(amount, clientKey),
+ dropInConfiguration: dropInConfiguration(serverAmount, clientKey),
cardComponentConfiguration:
- cardComponentConfiguration(amount, clientKey),
+ cardComponentConfiguration(serverAmount, clientKey),
applePayConfiguration:
- _applePayComponentConfiguration(clientKey, amount));
+ _applePayComponentConfiguration(clientKey, serverAmount));
}
@@ -60,6 +64,7 @@ class PreregistrationRepository {
}
DropInConfiguration dropInConfiguration(Amount amount, String clientKey) {
+ print("qqq amount: ${amount.value}");
// TODO: missing endpoint to retrieve client key
return DropInConfiguration(
environment: Environment.test,
@@ -105,8 +110,8 @@ class PreregistrationRepository {
ApplePayConfiguration _getApplePlayConfig(Amount amount) {
return ApplePayConfiguration(
- merchantId: "merchant.ComwellHotelsECOM",
- merchantName: "Comwell",
+ merchantId: merchantId,
+ merchantName: merchantName,
allowOnboarding: true,
allowShippingContactEditing: true,
applePaySummaryItems: [
diff --git a/comwell_key_app/lib/profile/utils/constants.dart b/comwell_key_app/lib/profile/utils/constants.dart
index 8a421c69..a9665db6 100644
--- a/comwell_key_app/lib/profile/utils/constants.dart
+++ b/comwell_key_app/lib/profile/utils/constants.dart
@@ -1,3 +1,7 @@
class ComwellClubConstants {
static const double imageHeightRatio = 0.7;
}
+
+const String merchantId = "merchant.ComwellHotelsECOM";
+const String merchantName = "Comwell";
+
diff --git a/comwell_key_app/lib/services/api.dart b/comwell_key_app/lib/services/api.dart
index 78343784..5a9865f0 100644
--- a/comwell_key_app/lib/services/api.dart
+++ b/comwell_key_app/lib/services/api.dart
@@ -176,6 +176,7 @@ class Api {
};
final data = jsonEncode(body);
final response = await dio.post<Json>(ApiEndpoints.checkOut, data: data);
+
return response.data;
}
diff --git a/comwell_key_app/lib/services/interceptors/response_handle_interceptor.dart b/comwell_key_app/lib/services/interceptors/response_handle_interceptor.dart
index 6e0d6c74..5c78b3e9 100644
--- a/comwell_key_app/lib/services/interceptors/response_handle_interceptor.dart
+++ b/comwell_key_app/lib/services/interceptors/response_handle_interceptor.dart
@@ -64,51 +64,63 @@ class ResponseHandleInterceptor extends Interceptor {
}
final statusCode = response.statusCode;
try {
- if (response.statusCode == 404) {
- final err = DioException(
- requestOptions: response.requestOptions, error: 'Not found');
- handler.next(err);
- } else if (statusCode == 401) {
- retryCount++;
- if (retryCount < 10) {
- final newToken = await _refreshToken();
- if (newToken != null) {
- // Retry the original request with the new token
- final options = response.requestOptions;
- options.headers['Authorization'] = newToken;
- final opts = Options(
- method: response.requestOptions.method,
- headers: response.requestOptions.headers);
- final retryRequest = await _dio.request<dynamic>(
- response.requestOptions.path,
- options: opts,
- data: response.requestOptions.data,
- queryParameters: response.requestOptions.queryParameters);
-
- return handler.resolve(retryRequest);
+ switch (statusCode) {
+ case 404:
+ final err = DioException(
+ requestOptions: response.requestOptions, error: 'Not found');
+ handler.next(err);
+ break;
+ case 401:
+ retryCount++;
+ if (retryCount < 10) {
+ final newToken = await _refreshToken();
+ if (newToken != null) {
+ // Retry the original request with the new token
+ final options = response.requestOptions;
+ options.headers['Authorization'] = newToken;
+ final opts = Options(
+ method: response.requestOptions.method,
+ headers: response.requestOptions.headers);
+ final retryRequest = await _dio.request<dynamic>(
+ response.requestOptions.path,
+ options: opts,
+ data: response.requestOptions.data,
+ queryParameters: response.requestOptions.queryParameters);
+
+ return handler.resolve(retryRequest);
+ }
+ } else {
+ retryCount = 0;
+ _authenticationRepository.logOut(forced: true);
+ return handler.reject(err);
}
- } else {
- retryCount = 0;
- _authenticationRepository.logOut(forced: true);
- return handler.reject(err);
- }
- } else if (statusCode == 426) {
- // Navigate to force update page
- final navigatorKey = locator<GlobalKey<NavigatorState>>();
- final context = navigatorKey.currentContext;
- if (context != null) {
- GoRouter.of(context).go('/forceUpdate');
- }
-
- final err = DioException(
- requestOptions: response.requestOptions, error: 'Update required');
- handler.next(err);
- } else {
- final err = DioException(
- requestOptions: response.requestOptions,
- error:
- 'HTTP request error, status code: \\${response.statusCode} - message: \\${response.data['detail']}');
- handler.next(err);
+ break;
+ case 500:
+ final errorMessage = response.data['detail'] as String;
+
+ final err = DioException(
+ requestOptions: response.requestOptions, error: errorMessage);
+ handler.next(err);
+ break;
+ case 426:
+ // Navigate to force update page
+ final navigatorKey = locator<GlobalKey<NavigatorState>>();
+ final context = navigatorKey.currentContext;
+ if (context != null) {
+ GoRouter.of(context).go('/forceUpdate');
+ }
+
+ final err = DioException(
+ requestOptions: response.requestOptions, error: 'Update required');
+ handler.next(err);
+ break;
+ default:
+ final err = DioException(
+ requestOptions: response.requestOptions,
+ error:
+ 'HTTP request error, status code: \\${response.statusCode} - message: \\${response.data['detail']}');
+ handler.next(err);
+ break;
}
} catch (e) {
final err = DioException(
diff --git a/comwell_key_app/lib/services/mappers/booking_mapper.dart b/comwell_key_app/lib/services/mappers/booking_mapper.dart
index 48f46600..efbba350 100644
--- a/comwell_key_app/lib/services/mappers/booking_mapper.dart
+++ b/comwell_key_app/lib/services/mappers/booking_mapper.dart
@@ -21,6 +21,7 @@ extension BookingDTOMapper on BookingDTO {
image: "assets/images/no_current_bookings_background.jpeg",
hotelName: "Hotel $hotelCode",
roomType: roomType ?? '',
+ addOnItems: addOnItems,
totalCharge: totalCharge ?? 0,
children: children,
booker: Guest(name: "$firstName $lastName", id: "$userId"),
@@ -55,6 +56,7 @@ extension BookingMapper on Booking {
children: children,
totalCharge: 200,
balance: 0,
+ addOnItems: addOnItems ?? [],
maskedCardNumber: "1234567890");
}
}
@@ -72,6 +74,7 @@ extension BookingWithRoomsMapper on Booking {
image: image,
hotelName: hotelName,
roomType: roomType,
+ addOnItems: addOnItems,
totalCharge: totalCharge,
children: children,
booker: booker,
diff --git a/comwell_key_app/lib/services/models/booking_dto.dart b/comwell_key_app/lib/services/models/booking_dto.dart
index b7a132ac..bd63ad00 100644
--- a/comwell_key_app/lib/services/models/booking_dto.dart
+++ b/comwell_key_app/lib/services/models/booking_dto.dart
@@ -1,3 +1,4 @@
+import 'package:comwell_key_app/check_out/models/check_out_item.dart';
import 'package:comwell_key_app/utils/json.dart';
import 'package:json_annotation/json_annotation.dart';
@@ -23,6 +24,7 @@ class BookingDTO {
final num? totalCharge;
final num? balance;
final String? maskedCardNumber;
+ final List<AddOnItem>? addOnItems;
BookingDTO({
required this.roomNumber,
@@ -43,6 +45,7 @@ class BookingDTO {
required this.totalCharge,
required this.balance,
required this.maskedCardNumber,
+ this.addOnItems,
});
Json toJson() => _$BookingDTOToJson(this);