6177214e-ce7c-49e3-99de-ff9721b26f63 — Commit 24f47e07

AuthorEdmir Suljic<esu@dwarf.dk>
Date2026-02-23 10:47:05 +0100
Updates to prereg

Changed files

.../hotel_information/models/addon_upgrade.g.dart  |   4 +-
 .../cubit/preregistration_state.freezed.dart       | 346 +++++++++++++
 .../lib/check_out/bloc/check_out_cubit.dart        |  18 +-
 comwell_key_app/lib/check_out/check_out_flow.dart  |   1 +
 .../components/check_out_bottom_sheet.dart         |   6 +-
 .../check_out/pages/check_out_processing_page.dart |   1 +
 .../repositories/pregistration_repository.dart     | 207 ++++++++
 .../cubit/hotel_information_cubit.dart             |  17 +-
 .../hotel_information/hotel_information_route.dart |   4 +-
 .../hotel_information/models/addon_upgrade.dart    |   3 +-
 .../pregistration/components/information_card.dart |  42 --
 .../components/prereg_bottom_button.dart           |  43 --
 .../pregistration/cubit/preregistration_cubit.dart | 539 ---------------------
 .../pregistration/cubit/preregistration_state.dart | 200 --------
 .../pregistration/pages/prereg_address_page.dart   | 152 ------
 .../pages/prereg_confirmation_page.dart            | 123 -----
 .../pregistration/pages/prereg_profile_page.dart   | 114 -----
 .../pages/prereg_up_sales_catalog_page.dart        | 125 -----
 .../pregistration/pregistration_repository.dart    | 206 --------
 .../lib/pregistration/prereg_request_model.dart    |  50 --
 .../lib/pregistration/preregistration_flow.dart    | 112 -----
 .../lib/pregistration/preregistration_route.dart   |  18 -
 comwell_key_app/lib/pregistration/utils/utils.dart |  34 --
 .../bloc/booking_details_cubit.dart                |   3 +-
 .../pregistration/components/information_card.dart |  42 ++
 .../components/prereg_bottom_button.dart           |  43 ++
 .../pregistration/cubit/preregistration_cubit.dart | 531 ++++++++++++++++++++
 .../pregistration/cubit/preregistration_state.dart |  38 ++
 .../pregistration/pages/prereg_address_page.dart   | 152 ++++++
 .../pages/prereg_confirmation_page.dart            | 123 +++++
 .../pregistration/pages/prereg_profile_page.dart   | 116 +++++
 .../pages/prereg_up_sales_catalog_page.dart        | 125 +++++
 .../pregistration/prereg_request_model.dart        |  50 ++
 .../pregistration/preregistration_flow.dart        | 113 +++++
 .../pregistration/preregistration_route.dart       |  18 +
 .../screens/pregistration/utils/utils.dart         |  34 ++
 comwell_key_app/lib/routing/app_router.dart        |   2 +-
 comwell_key_app/lib/services/api.dart              |  10 +-
 comwell_key_app/lib/utils/locator.dart             |   2 +-
 .../_generated/data/remote/api/api_client.g.dart   |   4 +-
 payment_plugin/lib/data/remote/api/api_client.dart |   2 +-
 .../lib/presentation/app/bloc/payment_cubit.dart   |   1 -
 .../screens/payment_processing_page.dart           |  42 +-
 43 files changed, 2001 insertions(+), 1815 deletions(-)

Diff

diff --git a/comwell_key_app/lib/.generated/hotel_information/models/addon_upgrade.g.dart b/comwell_key_app/lib/.generated/hotel_information/models/addon_upgrade.g.dart
index fae7255f..6120ec26 100644
--- a/comwell_key_app/lib/.generated/hotel_information/models/addon_upgrade.g.dart
+++ b/comwell_key_app/lib/.generated/hotel_information/models/addon_upgrade.g.dart
@@ -9,7 +9,9 @@ part of '../../../hotel_information/models/addon_upgrade.dart';
AddonUpgrade _$AddonUpgradeFromJson(Map json) => AddonUpgrade(
id: json['id'] as String,
name: json['name'] as String,
- images: (json['images'] as List<dynamic>).map((e) => e as String).toList(),
+ images:
+ (json['images'] as List<dynamic>?)?.map((e) => e as String?).toList() ??
+ [],
description: json['description'] as String,
isService: json['isService'] as bool,
onlyAvailableBeforeCheckin: json['onlyAvailableBeforeCheckin'] as bool,
diff --git a/comwell_key_app/lib/.generated/presentation/screens/pregistration/cubit/preregistration_state.freezed.dart b/comwell_key_app/lib/.generated/presentation/screens/pregistration/cubit/preregistration_state.freezed.dart
new file mode 100644
index 00000000..6f05be56
--- /dev/null
+++ b/comwell_key_app/lib/.generated/presentation/screens/pregistration/cubit/preregistration_state.freezed.dart
@@ -0,0 +1,346 @@
+// GENERATED CODE - DO NOT MODIFY BY HAND
+// coverage:ignore-file
+// ignore_for_file: type=lint
+// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark
+
+part of '../../../../../presentation/screens/pregistration/cubit/preregistration_state.dart';
+
+// **************************************************************************
+// FreezedGenerator
+// **************************************************************************
+
+// dart format off
+T _$identity<T>(T value) => value;
+/// @nodoc
+mixin _$PreregistrationState {
+
+ bool get isLoading; bool get selected; List<AddOnUpgrade> get addOnUpgrades; List<RoomUpgrade> get availableRoomUpgrades; String get selectedRoomUpgrade; bool get missingInformation; int get extrasTotalPrice; bool get termsAndConditionsAccepted; bool get forceUpdate; User? get user; CountryCode? get countryCode; String get selectedCountry; String? get phoneNumber; bool get isPhoneNumberValid; bool get isFirstNameValid; bool get isLastNameValid; bool get isAddressValid; bool get isPostalCodeValid; bool get isCityValid; String get selectedDocumentType; StoredPaymentMethod? get selectedPaymentMethod; AppError get error;
+/// Create a copy of PreregistrationState
+/// with the given fields replaced by the non-null parameter values.
+@JsonKey(includeFromJson: false, includeToJson: false)
+@pragma('vm:prefer-inline')
+$PreregistrationStateCopyWith<PreregistrationState> get copyWith => _$PreregistrationStateCopyWithImpl<PreregistrationState>(this as PreregistrationState, _$identity);
+
+
+
+@override
+bool operator ==(Object other) {
+ return identical(this, other) || (other.runtimeType == runtimeType&&other is PreregistrationState&&(identical(other.isLoading, isLoading) || other.isLoading == isLoading)&&(identical(other.selected, selected) || other.selected == selected)&&const DeepCollectionEquality().equals(other.addOnUpgrades, addOnUpgrades)&&const DeepCollectionEquality().equals(other.availableRoomUpgrades, availableRoomUpgrades)&&(identical(other.selectedRoomUpgrade, selectedRoomUpgrade) || other.selectedRoomUpgrade == selectedRoomUpgrade)&&(identical(other.missingInformation, missingInformation) || other.missingInformation == missingInformation)&&(identical(other.extrasTotalPrice, extrasTotalPrice) || other.extrasTotalPrice == extrasTotalPrice)&&(identical(other.termsAndConditionsAccepted, termsAndConditionsAccepted) || other.termsAndConditionsAccepted == termsAndConditionsAccepted)&&(identical(other.forceUpdate, forceUpdate) || other.forceUpdate == forceUpdate)&&(identical(other.user, user) || other.user == user)&&(identical(other.countryCode, countryCode) || other.countryCode == countryCode)&&(identical(other.selectedCountry, selectedCountry) || other.selectedCountry == selectedCountry)&&(identical(other.phoneNumber, phoneNumber) || other.phoneNumber == phoneNumber)&&(identical(other.isPhoneNumberValid, isPhoneNumberValid) || other.isPhoneNumberValid == isPhoneNumberValid)&&(identical(other.isFirstNameValid, isFirstNameValid) || other.isFirstNameValid == isFirstNameValid)&&(identical(other.isLastNameValid, isLastNameValid) || other.isLastNameValid == isLastNameValid)&&(identical(other.isAddressValid, isAddressValid) || other.isAddressValid == isAddressValid)&&(identical(other.isPostalCodeValid, isPostalCodeValid) || other.isPostalCodeValid == isPostalCodeValid)&&(identical(other.isCityValid, isCityValid) || other.isCityValid == isCityValid)&&(identical(other.selectedDocumentType, selectedDocumentType) || other.selectedDocumentType == selectedDocumentType)&&(identical(other.selectedPaymentMethod, selectedPaymentMethod) || other.selectedPaymentMethod == selectedPaymentMethod)&&(identical(other.error, error) || other.error == error));
+}
+
+
+@override
+int get hashCode => Object.hashAll([runtimeType,isLoading,selected,const DeepCollectionEquality().hash(addOnUpgrades),const DeepCollectionEquality().hash(availableRoomUpgrades),selectedRoomUpgrade,missingInformation,extrasTotalPrice,termsAndConditionsAccepted,forceUpdate,user,countryCode,selectedCountry,phoneNumber,isPhoneNumberValid,isFirstNameValid,isLastNameValid,isAddressValid,isPostalCodeValid,isCityValid,selectedDocumentType,selectedPaymentMethod,error]);
+
+@override
+String toString() {
+ return 'PreregistrationState(isLoading: $isLoading, selected: $selected, addOnUpgrades: $addOnUpgrades, availableRoomUpgrades: $availableRoomUpgrades, selectedRoomUpgrade: $selectedRoomUpgrade, missingInformation: $missingInformation, extrasTotalPrice: $extrasTotalPrice, termsAndConditionsAccepted: $termsAndConditionsAccepted, forceUpdate: $forceUpdate, user: $user, countryCode: $countryCode, selectedCountry: $selectedCountry, phoneNumber: $phoneNumber, isPhoneNumberValid: $isPhoneNumberValid, isFirstNameValid: $isFirstNameValid, isLastNameValid: $isLastNameValid, isAddressValid: $isAddressValid, isPostalCodeValid: $isPostalCodeValid, isCityValid: $isCityValid, selectedDocumentType: $selectedDocumentType, selectedPaymentMethod: $selectedPaymentMethod, error: $error)';
+}
+
+
+}
+
+/// @nodoc
+abstract mixin class $PreregistrationStateCopyWith<$Res> {
+ factory $PreregistrationStateCopyWith(PreregistrationState value, $Res Function(PreregistrationState) _then) = _$PreregistrationStateCopyWithImpl;
+@useResult
+$Res call({
+ bool isLoading, bool selected, List<AddOnUpgrade> addOnUpgrades, List<RoomUpgrade> availableRoomUpgrades, String selectedRoomUpgrade, bool missingInformation, int extrasTotalPrice, bool termsAndConditionsAccepted, bool forceUpdate, User? user, CountryCode? countryCode, String selectedCountry, String? phoneNumber, bool isPhoneNumberValid, bool isFirstNameValid, bool isLastNameValid, bool isAddressValid, bool isPostalCodeValid, bool isCityValid, String selectedDocumentType, StoredPaymentMethod? selectedPaymentMethod, AppError error
+});
+
+
+
+
+}
+/// @nodoc
+class _$PreregistrationStateCopyWithImpl<$Res>
+ implements $PreregistrationStateCopyWith<$Res> {
+ _$PreregistrationStateCopyWithImpl(this._self, this._then);
+
+ final PreregistrationState _self;
+ final $Res Function(PreregistrationState) _then;
+
+/// Create a copy of PreregistrationState
+/// with the given fields replaced by the non-null parameter values.
+@pragma('vm:prefer-inline') @override $Res call({Object? isLoading = null,Object? selected = null,Object? addOnUpgrades = null,Object? availableRoomUpgrades = null,Object? selectedRoomUpgrade = null,Object? missingInformation = null,Object? extrasTotalPrice = null,Object? termsAndConditionsAccepted = null,Object? forceUpdate = null,Object? user = freezed,Object? countryCode = freezed,Object? selectedCountry = null,Object? phoneNumber = freezed,Object? isPhoneNumberValid = null,Object? isFirstNameValid = null,Object? isLastNameValid = null,Object? isAddressValid = null,Object? isPostalCodeValid = null,Object? isCityValid = null,Object? selectedDocumentType = null,Object? selectedPaymentMethod = freezed,Object? error = null,}) {
+ return _then(_self.copyWith(
+isLoading: null == isLoading ? _self.isLoading : isLoading // ignore: cast_nullable_to_non_nullable
+as bool,selected: null == selected ? _self.selected : selected // ignore: cast_nullable_to_non_nullable
+as bool,addOnUpgrades: null == addOnUpgrades ? _self.addOnUpgrades : addOnUpgrades // ignore: cast_nullable_to_non_nullable
+as List<AddOnUpgrade>,availableRoomUpgrades: null == availableRoomUpgrades ? _self.availableRoomUpgrades : availableRoomUpgrades // ignore: cast_nullable_to_non_nullable
+as List<RoomUpgrade>,selectedRoomUpgrade: null == selectedRoomUpgrade ? _self.selectedRoomUpgrade : selectedRoomUpgrade // ignore: cast_nullable_to_non_nullable
+as String,missingInformation: null == missingInformation ? _self.missingInformation : missingInformation // ignore: cast_nullable_to_non_nullable
+as bool,extrasTotalPrice: null == extrasTotalPrice ? _self.extrasTotalPrice : extrasTotalPrice // ignore: cast_nullable_to_non_nullable
+as int,termsAndConditionsAccepted: null == termsAndConditionsAccepted ? _self.termsAndConditionsAccepted : termsAndConditionsAccepted // ignore: cast_nullable_to_non_nullable
+as bool,forceUpdate: null == forceUpdate ? _self.forceUpdate : forceUpdate // ignore: cast_nullable_to_non_nullable
+as bool,user: freezed == user ? _self.user : user // ignore: cast_nullable_to_non_nullable
+as User?,countryCode: freezed == countryCode ? _self.countryCode : countryCode // ignore: cast_nullable_to_non_nullable
+as CountryCode?,selectedCountry: null == selectedCountry ? _self.selectedCountry : selectedCountry // ignore: cast_nullable_to_non_nullable
+as String,phoneNumber: freezed == phoneNumber ? _self.phoneNumber : phoneNumber // ignore: cast_nullable_to_non_nullable
+as String?,isPhoneNumberValid: null == isPhoneNumberValid ? _self.isPhoneNumberValid : isPhoneNumberValid // ignore: cast_nullable_to_non_nullable
+as bool,isFirstNameValid: null == isFirstNameValid ? _self.isFirstNameValid : isFirstNameValid // ignore: cast_nullable_to_non_nullable
+as bool,isLastNameValid: null == isLastNameValid ? _self.isLastNameValid : isLastNameValid // ignore: cast_nullable_to_non_nullable
+as bool,isAddressValid: null == isAddressValid ? _self.isAddressValid : isAddressValid // ignore: cast_nullable_to_non_nullable
+as bool,isPostalCodeValid: null == isPostalCodeValid ? _self.isPostalCodeValid : isPostalCodeValid // ignore: cast_nullable_to_non_nullable
+as bool,isCityValid: null == isCityValid ? _self.isCityValid : isCityValid // ignore: cast_nullable_to_non_nullable
+as bool,selectedDocumentType: null == selectedDocumentType ? _self.selectedDocumentType : selectedDocumentType // ignore: cast_nullable_to_non_nullable
+as String,selectedPaymentMethod: freezed == selectedPaymentMethod ? _self.selectedPaymentMethod : selectedPaymentMethod // ignore: cast_nullable_to_non_nullable
+as StoredPaymentMethod?,error: null == error ? _self.error : error // ignore: cast_nullable_to_non_nullable
+as AppError,
+ ));
+}
+
+}
+
+
+/// Adds pattern-matching-related methods to [PreregistrationState].
+extension PreregistrationStatePatterns on PreregistrationState {
+/// A variant of `map` that fallback to returning `orElse`.
+///
+/// It is equivalent to doing:
+/// ```dart
+/// switch (sealedClass) {
+/// case final Subclass value:
+/// return ...;
+/// case _:
+/// return orElse();
+/// }
+/// ```
+
+@optionalTypeArgs TResult maybeMap<TResult extends Object?>(TResult Function( _PreregistrationState value)? $default,{required TResult orElse(),}){
+final _that = this;
+switch (_that) {
+case _PreregistrationState() when $default != null:
+return $default(_that);case _:
+ return orElse();
+
+}
+}
+/// A `switch`-like method, using callbacks.
+///
+/// Callbacks receives the raw object, upcasted.
+/// It is equivalent to doing:
+/// ```dart
+/// switch (sealedClass) {
+/// case final Subclass value:
+/// return ...;
+/// case final Subclass2 value:
+/// return ...;
+/// }
+/// ```
+
+@optionalTypeArgs TResult map<TResult extends Object?>(TResult Function( _PreregistrationState value) $default,){
+final _that = this;
+switch (_that) {
+case _PreregistrationState():
+return $default(_that);case _:
+ throw StateError('Unexpected subclass');
+
+}
+}
+/// A variant of `map` that fallback to returning `null`.
+///
+/// It is equivalent to doing:
+/// ```dart
+/// switch (sealedClass) {
+/// case final Subclass value:
+/// return ...;
+/// case _:
+/// return null;
+/// }
+/// ```
+
+@optionalTypeArgs TResult? mapOrNull<TResult extends Object?>(TResult? Function( _PreregistrationState value)? $default,){
+final _that = this;
+switch (_that) {
+case _PreregistrationState() when $default != null:
+return $default(_that);case _:
+ return null;
+
+}
+}
+/// A variant of `when` that fallback to an `orElse` callback.
+///
+/// It is equivalent to doing:
+/// ```dart
+/// switch (sealedClass) {
+/// case Subclass(:final field):
+/// return ...;
+/// case _:
+/// return orElse();
+/// }
+/// ```
+
+@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( bool isLoading, bool selected, List<AddOnUpgrade> addOnUpgrades, List<RoomUpgrade> availableRoomUpgrades, String selectedRoomUpgrade, bool missingInformation, int extrasTotalPrice, bool termsAndConditionsAccepted, bool forceUpdate, User? user, CountryCode? countryCode, String selectedCountry, String? phoneNumber, bool isPhoneNumberValid, bool isFirstNameValid, bool isLastNameValid, bool isAddressValid, bool isPostalCodeValid, bool isCityValid, String selectedDocumentType, StoredPaymentMethod? selectedPaymentMethod, AppError error)? $default,{required TResult orElse(),}) {final _that = this;
+switch (_that) {
+case _PreregistrationState() when $default != null:
+return $default(_that.isLoading,_that.selected,_that.addOnUpgrades,_that.availableRoomUpgrades,_that.selectedRoomUpgrade,_that.missingInformation,_that.extrasTotalPrice,_that.termsAndConditionsAccepted,_that.forceUpdate,_that.user,_that.countryCode,_that.selectedCountry,_that.phoneNumber,_that.isPhoneNumberValid,_that.isFirstNameValid,_that.isLastNameValid,_that.isAddressValid,_that.isPostalCodeValid,_that.isCityValid,_that.selectedDocumentType,_that.selectedPaymentMethod,_that.error);case _:
+ return orElse();
+
+}
+}
+/// A `switch`-like method, using callbacks.
+///
+/// As opposed to `map`, this offers destructuring.
+/// It is equivalent to doing:
+/// ```dart
+/// switch (sealedClass) {
+/// case Subclass(:final field):
+/// return ...;
+/// case Subclass2(:final field2):
+/// return ...;
+/// }
+/// ```
+
+@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( bool isLoading, bool selected, List<AddOnUpgrade> addOnUpgrades, List<RoomUpgrade> availableRoomUpgrades, String selectedRoomUpgrade, bool missingInformation, int extrasTotalPrice, bool termsAndConditionsAccepted, bool forceUpdate, User? user, CountryCode? countryCode, String selectedCountry, String? phoneNumber, bool isPhoneNumberValid, bool isFirstNameValid, bool isLastNameValid, bool isAddressValid, bool isPostalCodeValid, bool isCityValid, String selectedDocumentType, StoredPaymentMethod? selectedPaymentMethod, AppError error) $default,) {final _that = this;
+switch (_that) {
+case _PreregistrationState():
+return $default(_that.isLoading,_that.selected,_that.addOnUpgrades,_that.availableRoomUpgrades,_that.selectedRoomUpgrade,_that.missingInformation,_that.extrasTotalPrice,_that.termsAndConditionsAccepted,_that.forceUpdate,_that.user,_that.countryCode,_that.selectedCountry,_that.phoneNumber,_that.isPhoneNumberValid,_that.isFirstNameValid,_that.isLastNameValid,_that.isAddressValid,_that.isPostalCodeValid,_that.isCityValid,_that.selectedDocumentType,_that.selectedPaymentMethod,_that.error);case _:
+ throw StateError('Unexpected subclass');
+
+}
+}
+/// A variant of `when` that fallback to returning `null`
+///
+/// It is equivalent to doing:
+/// ```dart
+/// switch (sealedClass) {
+/// case Subclass(:final field):
+/// return ...;
+/// case _:
+/// return null;
+/// }
+/// ```
+
+@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( bool isLoading, bool selected, List<AddOnUpgrade> addOnUpgrades, List<RoomUpgrade> availableRoomUpgrades, String selectedRoomUpgrade, bool missingInformation, int extrasTotalPrice, bool termsAndConditionsAccepted, bool forceUpdate, User? user, CountryCode? countryCode, String selectedCountry, String? phoneNumber, bool isPhoneNumberValid, bool isFirstNameValid, bool isLastNameValid, bool isAddressValid, bool isPostalCodeValid, bool isCityValid, String selectedDocumentType, StoredPaymentMethod? selectedPaymentMethod, AppError error)? $default,) {final _that = this;
+switch (_that) {
+case _PreregistrationState() when $default != null:
+return $default(_that.isLoading,_that.selected,_that.addOnUpgrades,_that.availableRoomUpgrades,_that.selectedRoomUpgrade,_that.missingInformation,_that.extrasTotalPrice,_that.termsAndConditionsAccepted,_that.forceUpdate,_that.user,_that.countryCode,_that.selectedCountry,_that.phoneNumber,_that.isPhoneNumberValid,_that.isFirstNameValid,_that.isLastNameValid,_that.isAddressValid,_that.isPostalCodeValid,_that.isCityValid,_that.selectedDocumentType,_that.selectedPaymentMethod,_that.error);case _:
+ return null;
+
+}
+}
+
+}
+
+/// @nodoc
+
+
+class _PreregistrationState implements PreregistrationState {
+ const _PreregistrationState({this.isLoading = false, this.selected = false, final List<AddOnUpgrade> addOnUpgrades = const [], final List<RoomUpgrade> availableRoomUpgrades = const [], this.selectedRoomUpgrade = '', this.missingInformation = false, this.extrasTotalPrice = 0, this.termsAndConditionsAccepted = false, this.forceUpdate = false, this.user = null, this.countryCode = null, this.selectedCountry = '', this.phoneNumber = null, this.isPhoneNumberValid = false, this.isFirstNameValid = false, this.isLastNameValid = false, this.isAddressValid = false, this.isPostalCodeValid = false, this.isCityValid = false, this.selectedDocumentType = '', this.selectedPaymentMethod = null, this.error = AppError.none}): _addOnUpgrades = addOnUpgrades,_availableRoomUpgrades = availableRoomUpgrades;
+
+
+@override@JsonKey() final bool isLoading;
+@override@JsonKey() final bool selected;
+ final List<AddOnUpgrade> _addOnUpgrades;
+@override@JsonKey() List<AddOnUpgrade> get addOnUpgrades {
+ if (_addOnUpgrades is EqualUnmodifiableListView) return _addOnUpgrades;
+ // ignore: implicit_dynamic_type
+ return EqualUnmodifiableListView(_addOnUpgrades);
+}
+
+ final List<RoomUpgrade> _availableRoomUpgrades;
+@override@JsonKey() List<RoomUpgrade> get availableRoomUpgrades {
+ if (_availableRoomUpgrades is EqualUnmodifiableListView) return _availableRoomUpgrades;
+ // ignore: implicit_dynamic_type
+ return EqualUnmodifiableListView(_availableRoomUpgrades);
+}
+
+@override@JsonKey() final String selectedRoomUpgrade;
+@override@JsonKey() final bool missingInformation;
+@override@JsonKey() final int extrasTotalPrice;
+@override@JsonKey() final bool termsAndConditionsAccepted;
+@override@JsonKey() final bool forceUpdate;
+@override@JsonKey() final User? user;
+@override@JsonKey() final CountryCode? countryCode;
+@override@JsonKey() final String selectedCountry;
+@override@JsonKey() final String? phoneNumber;
+@override@JsonKey() final bool isPhoneNumberValid;
+@override@JsonKey() final bool isFirstNameValid;
+@override@JsonKey() final bool isLastNameValid;
+@override@JsonKey() final bool isAddressValid;
+@override@JsonKey() final bool isPostalCodeValid;
+@override@JsonKey() final bool isCityValid;
+@override@JsonKey() final String selectedDocumentType;
+@override@JsonKey() final StoredPaymentMethod? selectedPaymentMethod;
+@override@JsonKey() final AppError error;
+
+/// Create a copy of PreregistrationState
+/// with the given fields replaced by the non-null parameter values.
+@override @JsonKey(includeFromJson: false, includeToJson: false)
+@pragma('vm:prefer-inline')
+_$PreregistrationStateCopyWith<_PreregistrationState> get copyWith => __$PreregistrationStateCopyWithImpl<_PreregistrationState>(this, _$identity);
+
+
+
+@override
+bool operator ==(Object other) {
+ return identical(this, other) || (other.runtimeType == runtimeType&&other is _PreregistrationState&&(identical(other.isLoading, isLoading) || other.isLoading == isLoading)&&(identical(other.selected, selected) || other.selected == selected)&&const DeepCollectionEquality().equals(other._addOnUpgrades, _addOnUpgrades)&&const DeepCollectionEquality().equals(other._availableRoomUpgrades, _availableRoomUpgrades)&&(identical(other.selectedRoomUpgrade, selectedRoomUpgrade) || other.selectedRoomUpgrade == selectedRoomUpgrade)&&(identical(other.missingInformation, missingInformation) || other.missingInformation == missingInformation)&&(identical(other.extrasTotalPrice, extrasTotalPrice) || other.extrasTotalPrice == extrasTotalPrice)&&(identical(other.termsAndConditionsAccepted, termsAndConditionsAccepted) || other.termsAndConditionsAccepted == termsAndConditionsAccepted)&&(identical(other.forceUpdate, forceUpdate) || other.forceUpdate == forceUpdate)&&(identical(other.user, user) || other.user == user)&&(identical(other.countryCode, countryCode) || other.countryCode == countryCode)&&(identical(other.selectedCountry, selectedCountry) || other.selectedCountry == selectedCountry)&&(identical(other.phoneNumber, phoneNumber) || other.phoneNumber == phoneNumber)&&(identical(other.isPhoneNumberValid, isPhoneNumberValid) || other.isPhoneNumberValid == isPhoneNumberValid)&&(identical(other.isFirstNameValid, isFirstNameValid) || other.isFirstNameValid == isFirstNameValid)&&(identical(other.isLastNameValid, isLastNameValid) || other.isLastNameValid == isLastNameValid)&&(identical(other.isAddressValid, isAddressValid) || other.isAddressValid == isAddressValid)&&(identical(other.isPostalCodeValid, isPostalCodeValid) || other.isPostalCodeValid == isPostalCodeValid)&&(identical(other.isCityValid, isCityValid) || other.isCityValid == isCityValid)&&(identical(other.selectedDocumentType, selectedDocumentType) || other.selectedDocumentType == selectedDocumentType)&&(identical(other.selectedPaymentMethod, selectedPaymentMethod) || other.selectedPaymentMethod == selectedPaymentMethod)&&(identical(other.error, error) || other.error == error));
+}
+
+
+@override
+int get hashCode => Object.hashAll([runtimeType,isLoading,selected,const DeepCollectionEquality().hash(_addOnUpgrades),const DeepCollectionEquality().hash(_availableRoomUpgrades),selectedRoomUpgrade,missingInformation,extrasTotalPrice,termsAndConditionsAccepted,forceUpdate,user,countryCode,selectedCountry,phoneNumber,isPhoneNumberValid,isFirstNameValid,isLastNameValid,isAddressValid,isPostalCodeValid,isCityValid,selectedDocumentType,selectedPaymentMethod,error]);
+
+@override
+String toString() {
+ return 'PreregistrationState(isLoading: $isLoading, selected: $selected, addOnUpgrades: $addOnUpgrades, availableRoomUpgrades: $availableRoomUpgrades, selectedRoomUpgrade: $selectedRoomUpgrade, missingInformation: $missingInformation, extrasTotalPrice: $extrasTotalPrice, termsAndConditionsAccepted: $termsAndConditionsAccepted, forceUpdate: $forceUpdate, user: $user, countryCode: $countryCode, selectedCountry: $selectedCountry, phoneNumber: $phoneNumber, isPhoneNumberValid: $isPhoneNumberValid, isFirstNameValid: $isFirstNameValid, isLastNameValid: $isLastNameValid, isAddressValid: $isAddressValid, isPostalCodeValid: $isPostalCodeValid, isCityValid: $isCityValid, selectedDocumentType: $selectedDocumentType, selectedPaymentMethod: $selectedPaymentMethod, error: $error)';
+}
+
+
+}
+
+/// @nodoc
+abstract mixin class _$PreregistrationStateCopyWith<$Res> implements $PreregistrationStateCopyWith<$Res> {
+ factory _$PreregistrationStateCopyWith(_PreregistrationState value, $Res Function(_PreregistrationState) _then) = __$PreregistrationStateCopyWithImpl;
+@override @useResult
+$Res call({
+ bool isLoading, bool selected, List<AddOnUpgrade> addOnUpgrades, List<RoomUpgrade> availableRoomUpgrades, String selectedRoomUpgrade, bool missingInformation, int extrasTotalPrice, bool termsAndConditionsAccepted, bool forceUpdate, User? user, CountryCode? countryCode, String selectedCountry, String? phoneNumber, bool isPhoneNumberValid, bool isFirstNameValid, bool isLastNameValid, bool isAddressValid, bool isPostalCodeValid, bool isCityValid, String selectedDocumentType, StoredPaymentMethod? selectedPaymentMethod, AppError error
+});
+
+
+
+
+}
+/// @nodoc
+class __$PreregistrationStateCopyWithImpl<$Res>
+ implements _$PreregistrationStateCopyWith<$Res> {
+ __$PreregistrationStateCopyWithImpl(this._self, this._then);
+
+ final _PreregistrationState _self;
+ final $Res Function(_PreregistrationState) _then;
+
+/// Create a copy of PreregistrationState
+/// with the given fields replaced by the non-null parameter values.
+@override @pragma('vm:prefer-inline') $Res call({Object? isLoading = null,Object? selected = null,Object? addOnUpgrades = null,Object? availableRoomUpgrades = null,Object? selectedRoomUpgrade = null,Object? missingInformation = null,Object? extrasTotalPrice = null,Object? termsAndConditionsAccepted = null,Object? forceUpdate = null,Object? user = freezed,Object? countryCode = freezed,Object? selectedCountry = null,Object? phoneNumber = freezed,Object? isPhoneNumberValid = null,Object? isFirstNameValid = null,Object? isLastNameValid = null,Object? isAddressValid = null,Object? isPostalCodeValid = null,Object? isCityValid = null,Object? selectedDocumentType = null,Object? selectedPaymentMethod = freezed,Object? error = null,}) {
+ return _then(_PreregistrationState(
+isLoading: null == isLoading ? _self.isLoading : isLoading // ignore: cast_nullable_to_non_nullable
+as bool,selected: null == selected ? _self.selected : selected // ignore: cast_nullable_to_non_nullable
+as bool,addOnUpgrades: null == addOnUpgrades ? _self._addOnUpgrades : addOnUpgrades // ignore: cast_nullable_to_non_nullable
+as List<AddOnUpgrade>,availableRoomUpgrades: null == availableRoomUpgrades ? _self._availableRoomUpgrades : availableRoomUpgrades // ignore: cast_nullable_to_non_nullable
+as List<RoomUpgrade>,selectedRoomUpgrade: null == selectedRoomUpgrade ? _self.selectedRoomUpgrade : selectedRoomUpgrade // ignore: cast_nullable_to_non_nullable
+as String,missingInformation: null == missingInformation ? _self.missingInformation : missingInformation // ignore: cast_nullable_to_non_nullable
+as bool,extrasTotalPrice: null == extrasTotalPrice ? _self.extrasTotalPrice : extrasTotalPrice // ignore: cast_nullable_to_non_nullable
+as int,termsAndConditionsAccepted: null == termsAndConditionsAccepted ? _self.termsAndConditionsAccepted : termsAndConditionsAccepted // ignore: cast_nullable_to_non_nullable
+as bool,forceUpdate: null == forceUpdate ? _self.forceUpdate : forceUpdate // ignore: cast_nullable_to_non_nullable
+as bool,user: freezed == user ? _self.user : user // ignore: cast_nullable_to_non_nullable
+as User?,countryCode: freezed == countryCode ? _self.countryCode : countryCode // ignore: cast_nullable_to_non_nullable
+as CountryCode?,selectedCountry: null == selectedCountry ? _self.selectedCountry : selectedCountry // ignore: cast_nullable_to_non_nullable
+as String,phoneNumber: freezed == phoneNumber ? _self.phoneNumber : phoneNumber // ignore: cast_nullable_to_non_nullable
+as String?,isPhoneNumberValid: null == isPhoneNumberValid ? _self.isPhoneNumberValid : isPhoneNumberValid // ignore: cast_nullable_to_non_nullable
+as bool,isFirstNameValid: null == isFirstNameValid ? _self.isFirstNameValid : isFirstNameValid // ignore: cast_nullable_to_non_nullable
+as bool,isLastNameValid: null == isLastNameValid ? _self.isLastNameValid : isLastNameValid // ignore: cast_nullable_to_non_nullable
+as bool,isAddressValid: null == isAddressValid ? _self.isAddressValid : isAddressValid // ignore: cast_nullable_to_non_nullable
+as bool,isPostalCodeValid: null == isPostalCodeValid ? _self.isPostalCodeValid : isPostalCodeValid // ignore: cast_nullable_to_non_nullable
+as bool,isCityValid: null == isCityValid ? _self.isCityValid : isCityValid // ignore: cast_nullable_to_non_nullable
+as bool,selectedDocumentType: null == selectedDocumentType ? _self.selectedDocumentType : selectedDocumentType // ignore: cast_nullable_to_non_nullable
+as String,selectedPaymentMethod: freezed == selectedPaymentMethod ? _self.selectedPaymentMethod : selectedPaymentMethod // ignore: cast_nullable_to_non_nullable
+as StoredPaymentMethod?,error: null == error ? _self.error : error // ignore: cast_nullable_to_non_nullable
+as AppError,
+ ));
+}
+
+
+}
+
+// dart format on
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 0b01704c..c36460dc 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
@@ -4,8 +4,8 @@ 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/pages/check_out_page.dart';
import 'package:comwell_key_app/domain/repositories/booking_details_repository.dart';
+import 'package:comwell_key_app/domain/repositories/pregistration_repository.dart';
import 'package:comwell_key_app/overview/models/booking.dart';
-import 'package:comwell_key_app/pregistration/pregistration_repository.dart';
import 'package:comwell_key_app/profile/profile_repository.dart';
import 'package:comwell_key_app/profile/utils/urls.dart';
import 'package:comwell_key_app/routing/app_routes.dart';
@@ -102,10 +102,10 @@ class CheckoutCubit extends Cubit<CheckoutState> {
_isAnimating = true;
switch (currentPage) {
case CheckoutPage.confirmation:
- // if (booking.balance == 0 || booking.balance == null) {
- // emit(state.paymentProcessingNotNeeded());
- // return _navigateToProcessing(context);
- // }
+ if (booking.balance == 0 || booking.balance == null) {
+ emit(state.paymentProcessingNotNeeded());
+ return _navigateToProcessing(context);
+ }
return _navigateTo(CheckoutPage.payment);
case CheckoutPage.payment:
return _navigateToProcessing(context);
@@ -170,13 +170,9 @@ class CheckoutCubit extends Cubit<CheckoutState> {
booking.hotelCode,
);
- if (booking.balance == 0 || booking.balance == null) {
- await checkOutRepository.checkOut(booking.confirmationNumber);
+ await checkOutRepository.checkOut(booking.confirmationNumber);
- emit(state.checkoutSuccess());
- } else {
- emit(state.checkoutError());
- }
+ emit(state.checkoutSuccess());
} catch (e) {
emit(state.checkoutError());
await Future<void>.delayed(const Duration(milliseconds: 1000));
diff --git a/comwell_key_app/lib/check_out/check_out_flow.dart b/comwell_key_app/lib/check_out/check_out_flow.dart
index 4d88b76b..effa50f8 100644
--- a/comwell_key_app/lib/check_out/check_out_flow.dart
+++ b/comwell_key_app/lib/check_out/check_out_flow.dart
@@ -20,6 +20,7 @@ class CheckOutFlow extends StatelessWidget {
return const CheckOutProcessingPage();
} else {
return BlocListener<PaymentCubit, PaymentProcessingState>(
+ listenWhen: (previous, current) => previous is! PaymentProcessingStateConfirmed && current is PaymentProcessingStateConfirmed,
listener: (context, state) async {
if (state is PaymentProcessingStateConfirmed) {
//This is here to add time so that the payment is represented in the BookingDetails
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 d35f42ff..204e38dc 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
@@ -19,10 +19,12 @@ class CheckOutBottomSheet extends StatelessWidget {
final theme = Theme.of(context);
final isEnabled = state.isTermsAccepted;
+ print(cubit.booking.balance);
+
final buttonStyle = ButtonStyle(
backgroundColor: WidgetStateProperty.resolveWith((states) {
if (states.contains(WidgetState.disabled)) {
- return sandColor.withOpacity(0.5);
+ return sandColor.withValues(alpha: 0.5);
}
return sandColor;
}),
@@ -45,7 +47,7 @@ class CheckOutBottomSheet extends StatelessWidget {
child: Builder(builder: (context) {
if (cubit.state.page == CheckoutPage.confirmation) {
return ElevatedButton(
- onPressed: (cubit.booking.balance != 0
+ onPressed: (cubit.booking.balance == 0
? () async {
await showDialog<void>(
context: context,
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 b6b7e5ee..9d82df17 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
@@ -69,6 +69,7 @@ class _CheckOutProcessingPageState extends State<CheckOutProcessingPage>
Widget build(BuildContext context) {
final cubit = context.read<CheckoutCubit>();
return BlocListener<CheckoutCubit, CheckoutState>(
+ listenWhen: (previous, current) => previous.successfulCheckout != current.successfulCheckout,
listener: (context, state) {
if (state.successfulCheckout) {
context.push(AppRoutes.checkOutSuccess,
diff --git a/comwell_key_app/lib/domain/repositories/pregistration_repository.dart b/comwell_key_app/lib/domain/repositories/pregistration_repository.dart
new file mode 100644
index 00000000..7ac46d5b
--- /dev/null
+++ b/comwell_key_app/lib/domain/repositories/pregistration_repository.dart
@@ -0,0 +1,207 @@
+
+import 'package:comwell_key_app/presentation/screens/pregistration/prereg_request_model.dart';
+import 'package:comwell_key_app/profile_settings/repostiory/profile_settings_repository.dart';
+import 'package:comwell_key_app/services/api.dart';
+import 'package:comwell_key_app/utils/locator.dart';
+import 'package:flutter/material.dart';
+
+class PreregistrationRepository {
+ final Api _api = Api();
+ final ProfileSettingsRepository profileSettingsRepository =
+ locator<ProfileSettingsRepository>();
+
+ PreregistrationRepository();
+
+/* Future<PaymentConfigurations?> sessionCheckout(
+ String hotelCode,
+ String bookingId,
+ bool usePoints,
+ ) async {
+ final response = await _api.createAdyenSession(bookingId, usePoints, hotelCode);
+ final clientKey = response["clientKey"] as String;
+ final sessionResponse = response["sessionResponse"];
+ final payedWithPoints = response["isFullyPaidWithPoints"] as bool;
+ if (payedWithPoints) {
+ return null;
+ }
+ final id = sessionResponse["id"] as String;
+ final sessionData = sessionResponse["sessionData"] as String;
+ final availablePaymentMethods =
+ await _api.listAvailablePaymentMethods() as Map<String, dynamic>;
+
+ final scheme = _findPaymentMethod(availablePaymentMethods, "scheme");
+ final googlePay = _findPaymentMethod(availablePaymentMethods, "googlePay");
+ final applePay = _findPaymentMethod(availablePaymentMethods, "applePay");
+
+ // 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(serverAmount, clientKey, false));
+
+ return PaymentConfigurations(
+ sessionCheckout: session,
+ googlePayConfiguration: _getGooglePayComponentConfig(clientKey),
+ dropInConfiguration:
+ dropInConfiguration(serverAmount, clientKey, false),
+ cardComponentConfiguration:
+ cardComponentConfiguration(serverAmount, clientKey),
+ applePayConfiguration:
+ _applePayComponentConfiguration(clientKey, serverAmount, false),
+ isFullyPaidWithPoints: payedWithPoints,
+ availablePaymentMethods: [scheme!, googlePay!, applePay!]);
+ }
+
+ Future<PaymentConfigurations?> fetchSessionForAddingCard() async {
+ final response = await _api.createAdyenSessionForCards();
+ final availablePaymentMethods =
+ await _api.listAvailablePaymentMethods() as Map<String, dynamic>;
+
+ final clientKey = response["clientKey"] as String;
+ final sessionResponse = response["sessionResponse"];
+ final id = sessionResponse["id"] as String;
+ final sessionData = sessionResponse["sessionData"] as String;
+
+ final scheme = _findPaymentMethod(availablePaymentMethods, "scheme");
+ final googlePay = _findPaymentMethod(availablePaymentMethods, "googlePay");
+ final applePay = _findPaymentMethod(availablePaymentMethods, "applePay");
+
+ final session = await AdyenCheckout.session.create(
+ sessionId: id,
+ sessionData: sessionData,
+ configuration: cardComponentConfiguration(
+ Amount(value: 0, currency: "DKK"), clientKey),
+ );
+
+ return PaymentConfigurations(
+ sessionCheckout: session,
+ availablePaymentMethods: [scheme!, googlePay!, applePay!],
+ googlePayConfiguration: _getGooglePayComponentConfig(clientKey),
+ dropInConfiguration: dropInConfiguration(
+ Amount(value: 0, currency: "DKK"), clientKey, true),
+ cardComponentConfiguration: cardComponentConfiguration(
+ Amount(value: 0, currency: "DKK"), clientKey),
+ applePayConfiguration: _applePayComponentConfiguration(
+ clientKey, Amount(value: 0, currency: "DKK"), true),
+ isFullyPaidWithPoints: false);
+ } */
+
+ Future<dynamic> createPreregistration(PreregRequestDto request) async {
+ try {
+ debugPrint("request: $request.toString()");
+ final response = await _api.preRegistration(request);
+
+ return response.data!;
+ } catch (e) {
+ debugPrint("error: $e");
+ return null;
+ }
+ }
+}
+/*
+ CardComponentConfiguration cardComponentConfiguration(
+ Amount amount,
+ String clientKey,
+ ) {
+ return CardComponentConfiguration(
+ environment: Environment.test,
+ amount: amount,
+ cardConfiguration: const CardConfiguration(showStorePaymentField: false),
+ clientKey: clientKey,
+ countryCode: "DK",
+ );
+ }
+
+ DropInConfiguration dropInConfiguration(
+ Amount amount, String clientKey, bool addCard) {
+ return DropInConfiguration(
+ environment: Environment.test,
+ clientKey: clientKey,
+ countryCode: "DK",
+ skipListWhenSinglePaymentMethod: true,
+ googlePayConfiguration: _googlePayConfiguration,
+ applePayConfiguration: _getApplePlayConfig(amount, addCard),
+ cardConfiguration: const CardConfiguration(showStorePaymentField: false),
+ paymentMethodNames: {
+ "scheme": "Credit card",
+ },
+ );
+ }
+
+ GooglePayConfiguration get _googlePayConfiguration =>
+ const GooglePayConfiguration(
+ googlePayEnvironment: GooglePayEnvironment.test,
+ );
+
+ GooglePayComponentConfiguration _getGooglePayComponentConfig(
+ String clientKey,
+ ) {
+ return GooglePayComponentConfiguration(
+ environment: Environment.test,
+ countryCode: "DK",
+ clientKey: clientKey,
+ googlePayConfiguration: _googlePayConfiguration,
+ );
+ }
+
+ ApplePayComponentConfiguration _applePayComponentConfiguration(
+ String clientKey,
+ Amount amount,
+ bool addCard,
+ ) {
+ return ApplePayComponentConfiguration(
+ environment: Environment.test,
+ countryCode: "DK",
+ clientKey: clientKey,
+ applePayConfiguration: _getApplePlayConfig(amount, addCard),
+ );
+ }
+
+ ApplePayConfiguration _getApplePlayConfig(Amount amount, bool addCard) {
+ return ApplePayConfiguration(
+ merchantId: merchantId,
+ merchantName: merchantName,
+ allowOnboarding: true,
+ allowShippingContactEditing: true,
+ applePaySummaryItems: [
+ ApplePaySummaryItem(
+ label: addCard ? "add_card".tr() : "total".tr(),
+ amount: Amount(value: amount.value, currency: amount.currency),
+ type: ApplePaySummaryItemType.definite)
+ ]);
+ }
+
+ static final Iterable<StoredPaymentMethod> mockStoredPaymentData = [
+ 1,
+ 2,
+ 3,
+ 4
+ ].map((i) => StoredPaymentMethod(
+ expiryMonth: "12",
+ expiryYear: "2035",
+ holderName: "holder name",
+ id: "id $i",
+ lastFour: "$i$i$i$i",
+ brand: "visa"));
+}
+
+Map<String, dynamic>? _findPaymentMethod(
+ Map<String, dynamic> pmResponse,
+ String type,
+) {
+ final list =
+ (pmResponse['paymentMethods'] as List?)?.cast<Map<String, dynamic>>() ??
+ const <Map<String, dynamic>>[];
+
+ for (final m in list) {
+ final t = (m['type'] as String?)?.toLowerCase();
+ if (t == type.toLowerCase()) {
+ return m; // e.g. 'scheme', 'applepay', 'googlepay'
+ }
+ }
+ return null;
+}
+*/
\ No newline at end of file
diff --git a/comwell_key_app/lib/hotel_information/cubit/hotel_information_cubit.dart b/comwell_key_app/lib/hotel_information/cubit/hotel_information_cubit.dart
index cc8e3845..93aee03e 100644
--- a/comwell_key_app/lib/hotel_information/cubit/hotel_information_cubit.dart
+++ b/comwell_key_app/lib/hotel_information/cubit/hotel_information_cubit.dart
@@ -2,13 +2,14 @@ import 'package:bloc/bloc.dart';
import 'package:comwell_key_app/hotel_information/models/hotel.dart';
import 'package:comwell_key_app/hotel_information/repository/hotel_information_repository.dart';
import 'package:comwell_key_app/overview/models/booking.dart';
+import 'package:comwell_key_app/presentation/base/base_cubit.dart';
import 'package:comwell_key_app/services/api.dart';
import 'package:equatable/equatable.dart';
import 'package:flutter/foundation.dart';
part 'hotel_information_state.dart';
-class HotelInformationCubit extends Cubit<HotelInformationState> {
+class HotelInformationCubit extends BaseCubit<HotelInformationState> {
final api = Api();
final HotelInformationRepository hotelInformationRepository;
late final Hotel hotel;
@@ -20,14 +21,14 @@ class HotelInformationCubit extends Cubit<HotelInformationState> {
}
void init() async {
- emit(state.hotelLoading());
+ safeEmit(state.hotelLoading());
try {
hotel = await hotelInformationRepository.fetchHotelInformation(booking.hotelCode);
- emit(state.hotelSuccess());
- } catch (e) {
- debugPrint("error fetching hotel information for ${booking.hotelCode}: $e");
- emit(state.hotelError());
+ safeEmit(state.hotelSuccess());
+ } catch (e, st) {
+ logError(e, st);
+ safeEmit(state.hotelError());
}
}
@@ -40,12 +41,12 @@ class HotelInformationCubit extends Cubit<HotelInformationState> {
void onMoreInformationClicked() {}
void onBookSpaClicked() async {
- emit(state.bookingSpa(true));
+ safeEmit(state.bookingSpa(true));
try {
await api.bookSpa(hotel);
} catch (e, st) {
if (kDebugMode) {
- print("e=$e, $st");
+ logError(e, st);
}
}
emit(state.bookingSpa(false));
diff --git a/comwell_key_app/lib/hotel_information/hotel_information_route.dart b/comwell_key_app/lib/hotel_information/hotel_information_route.dart
index f480abf2..448c98b8 100644
--- a/comwell_key_app/lib/hotel_information/hotel_information_route.dart
+++ b/comwell_key_app/lib/hotel_information/hotel_information_route.dart
@@ -35,8 +35,8 @@ final hotelInformationRoute = ShellRoute(
},
),
GoRoute(
- path: "${AppRoutes.hotelInformation}/${AppRoutes.facility}",
- name: "${AppRoutes.hotelInformation}/${AppRoutes.facility}",
+ path: "${AppRoutes.hotelInformation}${AppRoutes.facility}",
+ name: "${AppRoutes.hotelInformation}${AppRoutes.facility}",
builder: (context, state) {
return FacilityPage(facility: state.extra as Facility);
},
diff --git a/comwell_key_app/lib/hotel_information/models/addon_upgrade.dart b/comwell_key_app/lib/hotel_information/models/addon_upgrade.dart
index 89fe2eb0..c6b355d9 100644
--- a/comwell_key_app/lib/hotel_information/models/addon_upgrade.dart
+++ b/comwell_key_app/lib/hotel_information/models/addon_upgrade.dart
@@ -7,7 +7,8 @@ part '../../.generated/hotel_information/models/addon_upgrade.g.dart';
class AddonUpgrade {
final String id;
final String name;
- final List<String> images;
+ @JsonKey(defaultValue: [])
+ final List<String?> images;
final String description;
final bool isService;
final bool onlyAvailableBeforeCheckin;
diff --git a/comwell_key_app/lib/pregistration/components/information_card.dart b/comwell_key_app/lib/pregistration/components/information_card.dart
deleted file mode 100644
index d4937e5a..00000000
--- a/comwell_key_app/lib/pregistration/components/information_card.dart
+++ /dev/null
@@ -1,42 +0,0 @@
-import 'package:comwell_key_app/themes/dark_theme.dart';
-import 'package:comwell_key_app/utils/l10n_utils.dart';
-import 'package:flutter/material.dart';
-
-class InformationCard extends StatelessWidget {
- final String title;
- final VoidCallback onEditClick;
- final Widget child;
- final TextStyle? titleStyle;
-
- const InformationCard({
- super.key,
- required this.title,
- required this.onEditClick,
- required this.child,
- this.titleStyle,
- });
-
- @override
- Widget build(BuildContext context) {
- return Container(
- padding: const EdgeInsets.all(12),
- decoration: BoxDecoration(
- color: sandColor[10],
- borderRadius: const BorderRadius.all(Radius.circular(10))),
- child: Column(
- crossAxisAlignment: CrossAxisAlignment.start,
- children: [
- Row(
- mainAxisAlignment: MainAxisAlignment.spaceBetween,
- children: [
- Text(title, style: titleStyle),
- TextButton(onPressed: onEditClick, child: Text(context.strings.edit, style: const TextStyle(decoration: TextDecoration.underline, decorationColor: sandColor, color: sandColor),))
- ],
- ),
- const SizedBox(height: 10),
- child
- ],
- ),
- );
- }
-}
diff --git a/comwell_key_app/lib/pregistration/components/prereg_bottom_button.dart b/comwell_key_app/lib/pregistration/components/prereg_bottom_button.dart
deleted file mode 100644
index e572eb40..00000000
--- a/comwell_key_app/lib/pregistration/components/prereg_bottom_button.dart
+++ /dev/null
@@ -1,43 +0,0 @@
-import 'package:comwell_key_app/pregistration/cubit/preregistration_cubit.dart';
-import 'package:comwell_key_app/themes/light_theme.dart';
-import 'package:flutter/material.dart';
-
-class PreregBottomButton extends StatelessWidget {
- final bool loading;
- final PreregistrationCubit cubit;
- final String buttonText;
- const PreregBottomButton({super.key, required this.loading, required this.cubit, required this.buttonText});
-
- @override
- Widget build(BuildContext context) {
- return Builder(builder: (context) {
- if (loading) return const SizedBox();
- return Column(
- mainAxisSize: MainAxisSize.min,
- children: [
- Row(
- children: [
- Expanded(
- child: Padding(
- padding: const EdgeInsets.fromLTRB(16.0, 16.0, 16.0, 40.0),
- child: ElevatedButton(
- 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
deleted file mode 100644
index a554066e..00000000
--- a/comwell_key_app/lib/pregistration/cubit/preregistration_cubit.dart
+++ /dev/null
@@ -1,539 +0,0 @@
-import 'package:bloc/bloc.dart';
-import 'package:comwell_key_app/overview/models/booking.dart';
-import 'package:comwell_key_app/pregistration/cubit/preregistration_state.dart';
-import 'package:comwell_key_app/pregistration/prereg_request_model.dart';
-import 'package:comwell_key_app/pregistration/pregistration_repository.dart';
-import 'package:comwell_key_app/pregistration/utils/utils.dart';
-import 'package:comwell_key_app/profile/profile_repository.dart';
-import 'package:comwell_key_app/profile_settings/model/address.dart';
-import 'package:comwell_key_app/profile_settings/repostiory/profile_settings_repository.dart';
-import 'package:comwell_key_app/tracking/comwell_tracking.dart';
-import 'package:comwell_key_app/tracking/models/analytics_event_item.dart';
-import 'package:comwell_key_app/up_sales/models/addon_list.dart';
-import 'package:comwell_key_app/up_sales/models/addon_upgrade.dart';
-import 'package:comwell_key_app/up_sales/models/room_upgrade.dart';
-import 'package:comwell_key_app/up_sales/models/upgrade.dart';
-import 'package:comwell_key_app/up_sales/up_sales_repository.dart';
-import 'package:comwell_key_app/utils/l10n_utils.dart';
-import 'package:comwell_key_app/utils/locator.dart';
-import 'package:comwell_key_app/utils/phone_utils.dart';
-import 'package:country_code_picker/country_code_picker.dart';
-import 'package:flutter/cupertino.dart';
-import 'package:flutter_bloc/flutter_bloc.dart';
-import 'package:go_router/go_router.dart';
-import 'package:payment_plugin/domain/models/stored_payment_method.dart';
-
-class PreregistrationCubit extends Cubit<PreregistrationState> {
- final _profileRepository = locator<ProfileRepository>();
- final _profileSettingsRepository = locator<ProfileSettingsRepository>();
- final _tracking = locator<ComwellTracking>();
- final _preregistrationRepository = locator<PreregistrationRepository>();
- final _upSalesRepository = locator<UpSalesRepository>();
-
- final Booking booking;
-
- final pageController = PageController();
- final addressTextController = TextEditingController();
- final postalCodeTextController = TextEditingController();
- final cityTextController = TextEditingController();
- final firstNameTextController = TextEditingController();
- final lastNameTextController = TextEditingController();
- final emailTextController = TextEditingController();
- final phoneNumberTextController = TextEditingController();
- final documentNumberTextController = TextEditingController();
-
- CountryCode? countryCode;
- String? phoneNumber;
-
- final List<String> favoriteCountries = ['DK', 'SE', 'NO', 'FI'];
- final List<String> documentTypes = [
- 'document_type_passport',
- 'document_type_id_card',
- 'document_type_driver_license',
- 'document_type_other',
- ];
- String selectedDocumentType = '';
-
- PreregistrationPage get currentPage =>
- PreregistrationPage.fromIndex(pageController.page?.toInt() ?? 0);
- bool _isAnimating = false;
-
- PreregistrationCubit({required this.booking})
- : super(
- const PreregistrationState(
- isLoading: false,
- selected: false,
- availableRoomUpgrades: [],
- addOnUpgrades: [],
- selectedRoomUpgrade: '',
- missingInformation: false,
- extrasTotalPrice: 0,
- termsAndConditionsAccepted: false,
- forceUpdate: false,
- user: null,
- phoneNumber: null,
- countryCode: null,
- isPhoneNumberValid: false,
- isFirstNameValid: false,
- isLastNameValid: false,
- isAddressValid: false,
- isPostalCodeValid: false,
- isCityValid: false,
- selectedCountry: '',
- ),
- ) {
- _tracking.trackScreenView(
- "Pre-registration - Betalingskort",
- "/pre-registration/betalingskort",
- );
- init();
- }
-
- void init() async {
- setupListeners();
- emit(state.copyWith(isLoading: true));
- try {
- final user = await _profileRepository.fetchProfileSettings();
- addressTextController.text = user.address.street;
- postalCodeTextController.text = user.address.zipCode;
- cityTextController.text = user.address.city;
-
- countryCode = getCountryCodeFromPhoneNumber(user.phoneNumber).$1;
- phoneNumber = getCountryCodeFromPhoneNumber(user.phoneNumber).$2;
-
- firstNameTextController.text = user.firstName;
- lastNameTextController.text = user.lastName;
- emailTextController.text = user.email;
- phoneNumberTextController.text = phoneNumber ?? '';
-
- final upSales = await _upSalesRepository.getUpSales(
- booking.confirmationNumber,
- booking.hotelCode,
- );
- emit(
- state
- .loaded(user: user, upSales: upSales)
- .copyWith(
- selectedCountry: countryCode?.code ?? 'DK',
- countryCode: countryCode,
- phoneNumber: phoneNumber,
- ),
- );
- } on Exception catch (e) {
- debugPrint("error fetching preregistration: $e");
- emit(state.copyWith(isLoading: false));
- }
- }
-
- void setupListeners() {
- phoneNumberTextController.addListener(() {
- emit(
- state.copyWith(
- isPhoneNumberValid: isPhoneNumberValid,
- missingInformation: false,
- ),
- );
- });
-
- addressTextController.addListener(() {
- emit(
- state.copyWith(
- isAddressValid: isAddressValid,
- missingInformation: false,
- ),
- );
- });
-
- postalCodeTextController.addListener(() {
- emit(
- state.copyWith(
- isPostalCodeValid: isPostalCodeValid,
- missingInformation: false,
- ),
- );
- });
-
- cityTextController.addListener(() {
- emit(
- state.copyWith(
- isCityValid: isCityValid,
- missingInformation: false,
- ),
- );
- });
- }
-
- void onDocumentTypeSelected(String documentType) {
- selectedDocumentType = documentType;
- emit(state.copyWith(selectedDocumentType: documentType));
- }
-
- void onAddressContinueClicked() {
- if (isAddressValid && isCityValid && isPostalCodeValid) {
- final updatedUser = state.user!.copyWith(
- address: Address(
- street: addressTextController.text,
- zipCode: postalCodeTextController.text,
- city: cityTextController.text,
- country: state.selectedCountry,
- ),
- );
-
- emit(state.copyWith(user: updatedUser));
- _navigateNextPage();
- } else {
- emit(state.copyWith(missingInformation: true));
- }
- }
-
- void onProfileContinueClicked() {
- if (isFirstNameValid && isLastNameValid && isPhoneNumberValid) {
- final phoneNumber = concatCountryCodeAndPhoneNumber(
- countryCode!,
- phoneNumberTextController.text,
- );
- final updatedUser = state.user!.copyWith(
- firstName: firstNameTextController.text,
- lastName: lastNameTextController.text,
- phoneNumber: phoneNumber,
- );
- emit(state.copyWith(user: updatedUser));
-
- _navigateNextPage();
- } else {
- emit(state.copyWith(missingInformation: true));
- }
- }
-
- bool onPaymentContinueClicked() {
- if (state.selectedPaymentMethod != null) {
- _navigateNextPage();
- return true;
- } else {
- return false;
- }
- }
-
- void onPaymentMethodValidationError() {
- emit(state.copyWith(missingInformation: true));
- }
-
- void onUpSalesContinueClicked() {
- _navigateNextPage();
- }
-
- void onContinueClicked(BuildContext context) {
- if (_isAnimating) return;
- switch (currentPage) {
- case PreregistrationPage.profile:
- onProfileContinueClicked();
- break;
- case PreregistrationPage.address:
- onAddressContinueClicked();
- break;
- /* case PreregistrationPage.payment:
- // Payment validation is handled in preregistration_flow.dart
- onPaymentContinueClicked();
- break; */
- case PreregistrationPage.upSales:
- onUpSalesContinueClicked();
- break;
- case PreregistrationPage.confirmation:
- _onConfirmPressed(context);
- break;
- }
- }
-
- void onPaymentMethodSelected(StoredPaymentMethod paymentMethod) {
- emit(
- state.copyWith(
- selectedPaymentMethod: paymentMethod,
- missingInformation: false,
- ),
- );
- }
-
- void addToCart() {
- final analyticsEventItem = AnalyticsEventItem(
- hotelName: "Comwell",
- currency: "DKK",
- value: 500,
- placement: "placement",
- items: ["items"],
- itemId: "itemId",
- itemName: "itemName",
- price: 200,
- quantity: 200,
- );
- _tracking.trackAddToCart(analyticsEventItem);
- }
-
- void removeToCard() {
- final analyticsEventItem = AnalyticsEventItem(
- hotelName: "Comwell",
- currency: "DKK",
- value: 500,
- placement: "placement",
- items: ["items"],
- itemId: "itemId",
- itemName: "itemName",
- price: 200,
- quantity: 200,
- );
- _tracking.trackRemoveFromCart(analyticsEventItem);
- }
-
- void _onConfirmPressed(BuildContext context) async {
- emit(state.copyWith(isLoading: true));
- try {
- final hasUpSales =
- state.addOnUpgrades.any((e) => e.isAddedToCart) || state.selectedRoomUpgrade.isNotEmpty;
-
- await _profileSettingsRepository.updateUser(state.user!);
- if (hasUpSales) {
- addUpSalesToBooking();
- }
-
- // Build the PreregRequestModel with all required fields
- final preregRequest = PreregRequestDto(
- firstName: state.user!.firstName,
- lastName: state.user!.lastName,
- email: state.user!.email,
- phoneNumber: state.user!.phoneNumber,
- birthDay: state.user!.birthDate.toIso8601String(),
- address: state.user!.address.street,
- zipCode: state.user!.address.zipCode,
- city: state.user!.address.city,
- country: state.user!.address.country,
- confirmationNumber: booking.confirmationNumber,
- hotelCode: booking.hotelCode,
- comwellClubTermsOfUseConsentChoice: state.termsAndConditionsAccepted,
- comwellClubMarketingConsentChoice: false,
- );
-
- final preRegResponse = await _preregistrationRepository.createPreregistration(preregRequest);
-
- if (preRegResponse != null) {
- Future.delayed(const Duration(seconds: 3), () {
- emit(state.copyWith(isLoading: false));
- if (!context.mounted) return;
- context.pop(preRegResponse);
- });
- } else {
- emit(state.setError(error: Error()));
- if (!context.mounted) return;
- context.pop(null);
- }
- } catch (e) {
- emit(state.setError(error: Error()));
- }
- }
-
- Future<void> addUpSalesToBooking() async {
- // Extract RoomUpgrade from selectedUpSales to get the roomType
- final roomType = state.selectedRoomUpgrade;
-
- // Convert selected up sales to AddOnList objects using their individual quantities
- final List<AddOnList> addonList = state.addOnUpgrades
- .map((upgrade) => AddOnList(itemCode: upgrade.id, quantity: upgrade.quantity))
- .toList();
-
- await _upSalesRepository.addUpSalesToBooking(
- booking.confirmationNumber,
- booking.hotelCode,
- roomType,
- addonList,
- );
- }
-
- void onEditProfileClicked() {
- _navigateTo(PreregistrationPage.profile);
- }
-
- void onEditAddressClicked() {
- _navigateTo(PreregistrationPage.address);
- }
-
- /* void onEditPaymentMethodCLickked() {
- _navigateTo(PreregistrationPage.payment);
- } */
-
- void onEditExtrasClicked() {
- _navigateTo(PreregistrationPage.upSales);
- }
-
- void onPhoneNumberChanged(String phoneNumber) {
- phoneNumberTextController.text = phoneNumber;
- emit(state.copyWith(isPhoneNumberValid: isPhoneNumberValid));
- }
-
- void onCountryCodeSelected(CountryCode country) {
- countryCode = country;
- emit(state.copyWith(countryCode: country, selectedCountry: country.code));
- }
-
- bool onBackClicked() {
- if (_isAnimating) return true;
- final hasPage = pageController.page != null;
- if (hasPage && pageController.page! >= 1.0) {
- _navigatePreviousPage();
- return true;
- }
- return false;
- }
-
- void _navigateTo(PreregistrationPage page) async {
- if (_isAnimating) return;
- _isAnimating = true;
- await pageController.animateToPage(
- page.index,
- duration: const Duration(milliseconds: 500),
- curve: Curves.fastOutSlowIn,
- );
- emit(state.copyWith(forceUpdate: true));
- _isAnimating = false;
- }
-
- void _navigateNextPage() async {
- if (_isAnimating) return;
- _isAnimating = true;
- await pageController.nextPage(
- duration: const Duration(milliseconds: 500),
- curve: Curves.fastOutSlowIn,
- );
- emit(state.copyWith(forceUpdate: true));
- _isAnimating = false;
- }
-
- void _navigatePreviousPage() async {
- if (_isAnimating) return;
- _isAnimating = true;
- await pageController.previousPage(
- duration: const Duration(milliseconds: 500),
- curve: Curves.fastOutSlowIn,
- );
- emit(state.copyWith(forceUpdate: true));
- _isAnimating = false;
- }
-
- int get extrasTotalPrice {
- //This is the total price of the selected up sales and the price of the selected
- //room upgrade if it is selected
-
- return selectedAddOnUpgrades.fold(0, (sum, upgrade) => sum + upgrade.price * upgrade.quantity) +
- (state.selectedRoomUpgrade.isNotEmpty
- ? state.availableRoomUpgrades.firstWhere((e) => e.id == state.selectedRoomUpgrade).price
- : 0);
- }
-
- int get numOfExtras =>
- selectedAddOnUpgrades.fold(0, (sum, upgrade) => sum + upgrade.quantity) +
- (state.selectedRoomUpgrade.isNotEmpty ? 1 : 0);
-
- List<AddOnUpgrade> get otherUpgrades {
- final selectedUpgrades = state.addOnUpgrades.where((upgrade) => !upgrade.isService).toList();
- return selectedUpgrades;
- }
-
- List<AddOnUpgrade> get selectedAddOnUpgrades {
- final selectedUpgrades = state.addOnUpgrades.where((upgrade) => upgrade.isAddedToCart).toList();
- return selectedUpgrades;
- }
-
- @override
- Future<void> close() {
- addressTextController.dispose();
- postalCodeTextController.dispose();
- cityTextController.dispose();
- pageController.dispose();
- firstNameTextController.dispose();
- lastNameTextController.dispose();
- emailTextController.dispose();
- phoneNumberTextController.dispose();
- documentNumberTextController.dispose();
- return super.close();
- }
-
- bool get isAddressValid => addressTextController.text.isNotEmpty;
-
- bool get isPostalCodeValid => postalCodeTextController.text.isNotEmpty;
-
- bool get isCityValid => cityTextController.text.isNotEmpty;
-
- bool get isDocumentNumberValid => documentNumberTextController.text.isNotEmpty;
-
- bool get isPhoneNumberValid =>
- phoneNumberTextController.text.length >= 7 && phoneNumberTextController.text.length < 16;
-
- bool get isFirstNameValid => firstNameTextController.text.isNotEmpty;
-
- bool get isLastNameValid => lastNameTextController.text.isNotEmpty;
-
- bool get canContinue {
- int page = pageController.page?.ceil() ?? 0;
-
- final preregPage = PreregistrationPage.fromIndex(page);
-
- switch (preregPage) {
- case PreregistrationPage.profile:
- return isFirstNameValid && isLastNameValid && isPhoneNumberValid;
- case PreregistrationPage.address:
- return isAddressValid && isPostalCodeValid && isCityValid;
- case PreregistrationPage.upSales:
- return true;
- case PreregistrationPage.confirmation:
- return true;
- }
- }
-
- String buttonText(BuildContext context) {
- int page = pageController.page?.ceil() ?? 0;
- final preregPage = PreregistrationPage.fromIndex(page);
- switch (preregPage) {
- case PreregistrationPage.profile:
- return context.strings.generic_continue;
- case PreregistrationPage.address:
- return context.strings.generic_continue;
- case PreregistrationPage.upSales:
- if (selectedAddOnUpgrades.isEmpty && state.selectedRoomUpgrade.isEmpty) {
- return context.strings.continue_without_up_sales;
- }
- return context.strings.generic_continue;
- case PreregistrationPage.confirmation:
- return context.strings.generic_confirm;
- }
- }
-
- void onTermsAndConditionsToggled(bool toggle) {
- emit(state.copyWith(termsAndConditionsAccepted: toggle));
- }
-
- void toggleSelectedUpgrade(Upgrade upgrade) {
- if (upgrade is RoomUpgrade) {
- emit(state.toggleRoomUpgrade(roomUpgrade: upgrade));
- } else if (upgrade is AddOnUpgrade) {
- emit(state.toggleSelectedAddonUpsale(upgrade: upgrade));
- }
- }
-
- void onContinue() {
- emit(state.copyWith(selected: false));
- }
-
- void updateAddonUpgradeQuantity(AddOnUpgrade upgrade, int quantity) {
- emit(state.updateSelectedUpgradeWithQuantity(upgrade, quantity));
- }
-
- String get paymentMethodImage {
- switch (state.selectedPaymentMethod?.brand) {
- case 'mastercard':
- return 'assets/images/master.svg';
- case 'visa':
- return 'assets/images/visa.svg';
- case 'maestro':
- return 'assets/images/maestro.svg';
- default:
- return 'assets/images/visa.png';
- }
- }
-}
diff --git a/comwell_key_app/lib/pregistration/cubit/preregistration_state.dart b/comwell_key_app/lib/pregistration/cubit/preregistration_state.dart
deleted file mode 100644
index 726174ac..00000000
--- a/comwell_key_app/lib/pregistration/cubit/preregistration_state.dart
+++ /dev/null
@@ -1,200 +0,0 @@
-
-import 'package:comwell_key_app/up_sales/models/addon_upgrade.dart';
-import 'package:comwell_key_app/up_sales/models/room_upgrade.dart';
-import 'package:comwell_key_app/up_sales/models/up_sales.dart';
-import 'package:comwell_key_app/up_sales/models/upgrade.dart';
-import 'package:country_code_picker/country_code_picker.dart';
-import 'package:equatable/equatable.dart';
-import 'package:payment_plugin/domain/models/stored_payment_method.dart';
-
-import '../../profile_settings/model/user.dart';
-
-class PreregistrationState extends Equatable {
- final bool isLoading;
- final bool selected;
- final List<AddOnUpgrade> addOnUpgrades;
- final List<RoomUpgrade> availableRoomUpgrades;
- final String selectedRoomUpgrade;
- final bool forceUpdate;
- final User? user;
- final CountryCode? countryCode;
- final String selectedCountry;
- final String? phoneNumber;
- final bool missingInformation;
- final int extrasTotalPrice;
- final bool termsAndConditionsAccepted;
- final bool isPhoneNumberValid;
- final bool isFirstNameValid;
- final bool isLastNameValid;
- final bool isAddressValid;
- final bool isPostalCodeValid;
- final bool isCityValid;
- final String selectedDocumentType;
- final StoredPaymentMethod? selectedPaymentMethod;
- final Error? error;
-
- const PreregistrationState({
- required this.isLoading,
- required this.selected,
- required this.addOnUpgrades,
- required this.availableRoomUpgrades,
- required this.selectedRoomUpgrade,
- this.missingInformation = false,
- this.extrasTotalPrice = 0,
- this.termsAndConditionsAccepted = false,
- this.forceUpdate = false,
- this.user,
- this.phoneNumber,
- this.countryCode,
- this.selectedCountry = '',
- this.isPhoneNumberValid = false,
- this.isFirstNameValid = false,
- this.isLastNameValid = false,
- this.isAddressValid = false,
- this.isPostalCodeValid = false,
- this.isCityValid = false,
- this.error,
- this.selectedDocumentType = '',
- this.selectedPaymentMethod,
- });
-
- PreregistrationState.initial()
- : isLoading = false,
- selected = false,
- addOnUpgrades = [],
- availableRoomUpgrades = [],
- selectedRoomUpgrade = '',
- missingInformation = false,
- extrasTotalPrice = 0,
- termsAndConditionsAccepted = false,
- forceUpdate = false,
- user = null,
- phoneNumber = null,
- countryCode = null,
- selectedCountry = '',
- isPhoneNumberValid = false,
- isFirstNameValid = false,
- isLastNameValid = false,
- isAddressValid = false,
- isPostalCodeValid = false,
- isCityValid = false,
- error = null,
- selectedDocumentType = '',
- selectedPaymentMethod = null;
-
- PreregistrationState loaded({required UpSales upSales, required User user}) =>
- copyWith(
- isLoading: false,
- availableRoomUpgrades: upSales.roomUpgrades,
- addOnUpgrades: upSales.addOnUpgrades,
- user: user);
-
- PreregistrationState updateUser({required User user}) => copyWith(user: user);
-
- PreregistrationState toggleSelectedAddonUpsale(
- {required AddOnUpgrade upgrade}) {
- final upgradeIsSelected = upgrade.isSelected;
- final updatedUpgrade =
- upgrade.copyWith(isSelected: !upgradeIsSelected, quantity: 1);
- return updateUpgrade(updatedUpgrade);
- }
-
- PreregistrationState updateUpgrade(AddOnUpgrade upgrade) {
- final updatedAddOnUpgrades = addOnUpgrades.toList();
- final index = updatedAddOnUpgrades.indexWhere((e) => e.id == upgrade.id);
- updatedAddOnUpgrades[index] = upgrade;
- return copyWith(addOnUpgrades: updatedAddOnUpgrades);
- }
-
- PreregistrationState toggleRoomUpgrade({required RoomUpgrade roomUpgrade}) {
- if (selectedRoomUpgrade == roomUpgrade.id) {
- return copyWith(selectedRoomUpgrade: '');
- } else {
- return copyWith(selectedRoomUpgrade: roomUpgrade.id);
- }
- }
-
- PreregistrationState updateSelectedUpgradeWithQuantity(
- AddOnUpgrade upgrade,
- int quantity,
- ) {
- return updateUpgrade(upgrade.copyWith(quantity: quantity));
- }
-
- PreregistrationState setError({required Error error}) =>
- copyWith(error: error, isLoading: false);
-
- PreregistrationState copyWith({
- bool? isLoading,
- bool? selected,
- List<AddOnUpgrade>? addOnUpgrades,
- List<RoomUpgrade>? availableRoomUpgrades,
- List<Upgrade>? selectedUpSales,
- String? selectedRoomUpgrade,
- bool? missingInformation,
- int? numOfExtras,
- int? extrasTotalPrice,
- bool? termsAndConditionsAccepted,
- bool? forceUpdate,
- User? user,
- String? phoneNumber,
- CountryCode? countryCode,
- String? selectedCountry,
- String? selectedDocumentType,
- bool? isPhoneNumberValid,
- bool? isFirstNameValid,
- bool? isLastNameValid,
- bool? isAddressValid,
- StoredPaymentMethod? selectedPaymentMethod,
- bool? isPostalCodeValid,
- bool? isCityValid,
- Error? error,
- }) {
- return PreregistrationState(
- isLoading: isLoading ?? this.isLoading,
- selected: selected ?? this.selected,
- addOnUpgrades: addOnUpgrades ?? this.addOnUpgrades,
- availableRoomUpgrades:
- availableRoomUpgrades ?? this.availableRoomUpgrades,
- selectedRoomUpgrade: selectedRoomUpgrade ?? this.selectedRoomUpgrade,
- missingInformation: missingInformation ?? this.missingInformation,
- extrasTotalPrice: extrasTotalPrice ?? this.extrasTotalPrice,
- termsAndConditionsAccepted:
- termsAndConditionsAccepted ?? this.termsAndConditionsAccepted,
- forceUpdate: forceUpdate ?? this.forceUpdate,
- user: user ?? this.user,
- error: error ?? this.error,
- selectedCountry: selectedCountry ?? this.selectedCountry,
- selectedDocumentType: selectedDocumentType ?? this.selectedDocumentType,
- selectedPaymentMethod: selectedPaymentMethod ?? this.selectedPaymentMethod,
- );
- }
-
- @override
- List<Object?> get props => [
- isLoading,
- selected,
- addOnUpgrades,
- availableRoomUpgrades,
- selectedRoomUpgrade,
- user,
- phoneNumber,
- countryCode,
- selectedCountry,
- missingInformation,
- extrasTotalPrice,
- termsAndConditionsAccepted,
- forceUpdate,
- isPhoneNumberValid,
- isFirstNameValid,
- isLastNameValid,
- isAddressValid,
- isPostalCodeValid,
- isCityValid,
- availableRoomUpgrades,
- selectedRoomUpgrade,
- selectedDocumentType,
- selectedPaymentMethod,
- error,
- ];
-}
diff --git a/comwell_key_app/lib/pregistration/pages/prereg_address_page.dart b/comwell_key_app/lib/pregistration/pages/prereg_address_page.dart
deleted file mode 100644
index 64ad17a5..00000000
--- a/comwell_key_app/lib/pregistration/pages/prereg_address_page.dart
+++ /dev/null
@@ -1,152 +0,0 @@
-import 'package:comwell_key_app/common/components/comwell_text_field.dart';
-import 'package:comwell_key_app/pregistration/cubit/preregistration_cubit.dart';
-import 'package:comwell_key_app/pregistration/cubit/preregistration_state.dart';
-import 'package:comwell_key_app/themes/light_theme.dart';
-import 'package:comwell_key_app/utils/l10n_utils.dart';
-import 'package:country_code_picker/country_code_picker.dart';
-import 'package:flutter/material.dart';
-import 'package:flutter_bloc/flutter_bloc.dart';
-import '../../common/components/shimmer_loader/prereg_address_shimmer_loader.dart';
-
-class PreregAddressPage extends StatelessWidget {
- const PreregAddressPage({super.key});
-
- @override
- Widget build(BuildContext context) {
- return BlocBuilder<PreregistrationCubit, PreregistrationState>(
- builder: (context, state) {
- final cubit = context.read<PreregistrationCubit>();
-
- if (state.isLoading) {
- return const Center(child: PreregAddressShimmerLoader());
- }
-
- final isFavoriteCountry = cubit.favoriteCountries.contains(state.selectedCountry);
-
- final addressErrorMessage = !cubit.isAddressValid && state.missingInformation
- ? context.strings.generic_information_required
- : null;
- final postalCodeErrorMessage = !cubit.isPostalCodeValid && state.missingInformation
- ? context.strings.generic_information_required
- : null;
- final cityErrorMessage = !cubit.isCityValid && state.missingInformation
- ? context.strings.generic_information_required
- : null;
-
- final documentNumberErrorMessage = !cubit.isDocumentNumberValid && state.missingInformation
- ? context.strings.generic_information_required
- : null;
-
- return ListView(
- padding: const EdgeInsets.symmetric(horizontal: 12.0),
- key: const PageStorageKey("information_form"),
- children: [
- const SizedBox(height: 40),
- Text(
- context.strings.preregistration_address_title,
- style: Theme.of(context).textTheme.headlineLarge,
- ),
- const SizedBox(height: 18),
- Text(
- context.strings.preregistration_address_subtitle,
- style: Theme.of(context).textTheme.bodySmall,
- ),
- const SizedBox(height: 40),
- ComwellTextField(
- key: const Key("address"),
- fieldName: context.strings.preregistration_address_label_address,
- initialValue: "",
- readOnly: false,
- errorMessage: addressErrorMessage,
- controller: cubit.addressTextController,
- ),
- const SizedBox(height: 12),
- ComwellTextField(
- fieldName: context.strings.preregistration_address_label_postal_code,
- initialValue: "",
- textInputType: TextInputType.number,
- errorMessage: postalCodeErrorMessage,
- readOnly: false,
- controller: cubit.postalCodeTextController,
- ),
- const SizedBox(height: 12),
- ComwellTextField(
- fieldName: context.strings.preregistration_address_label_city,
- initialValue: "",
- readOnly: false,
- errorMessage: cityErrorMessage,
- controller: cubit.cityTextController,
- ),
- const SizedBox(height: 12),
- Container(
- height: 62,
- width: double.infinity,
- decoration: BoxDecoration(
- borderRadius: BorderRadius.circular(8),
- border: Border.all(color: colorDivider),
- ),
- child: CountryCodePicker(
- alignLeft: true,
- textOverflow: TextOverflow.visible,
- initialSelection: cubit.countryCode?.name,
- showFlag: true,
- favorite: cubit.favoriteCountries,
- showDropDownButton: true,
- textStyle: Theme.of(context).textTheme.headlineSmall,
- showCountryOnly: true,
- showOnlyCountryWhenClosed: true,
- onChanged: (CountryCode countryCode) {
- cubit.onCountryCodeSelected(countryCode);
- },
- ),
- ),
- const SizedBox(height: 12),
- if (!isFavoriteCountry) ...[
- const Divider(color: colorDivider),
- const SizedBox(height: 12),
- Container(
- height: 62,
- width: double.infinity,
- decoration: BoxDecoration(
- borderRadius: BorderRadius.circular(8),
- border: Border.all(color: colorDivider),
- ),
- child: Padding(
- padding: const EdgeInsets.symmetric(vertical: 10, horizontal: 12),
- child: DropdownButtonFormField<String>(
- hint: Text(context.strings.document_type),
- initialValue: state.selectedDocumentType.isNotEmpty
- ? state.selectedDocumentType
- : null,
- style: Theme.of(context).textTheme.headlineSmall?.copyWith(color: Colors.black),
- items: cubit.documentTypes
- .map(
- (documentType) =>
- DropdownMenuItem(value: documentType, child: Text(documentType)),
- )
- .toList(),
- onChanged: (value) {
- if (value != null) {
- cubit.onDocumentTypeSelected(value);
- }
- },
- ),
- ),
- ),
- const SizedBox(height: 12),
- ComwellTextField(
- key: const Key("document_number"),
- fieldName: context.strings.document_number,
- textInputType: TextInputType.number,
- initialValue: "",
- readOnly: false,
- errorMessage: documentNumberErrorMessage,
- controller: cubit.documentNumberTextController,
- ),
- ],
- ],
- );
- },
- );
- }
-}
diff --git a/comwell_key_app/lib/pregistration/pages/prereg_confirmation_page.dart b/comwell_key_app/lib/pregistration/pages/prereg_confirmation_page.dart
deleted file mode 100644
index 21ad8d0d..00000000
--- a/comwell_key_app/lib/pregistration/pages/prereg_confirmation_page.dart
+++ /dev/null
@@ -1,123 +0,0 @@
-import 'package:comwell_key_app/pregistration/cubit/preregistration_cubit.dart';
-import 'package:comwell_key_app/pregistration/components/information_card.dart';
-import 'package:comwell_key_app/themes/light_theme.dart';
-import 'package:comwell_key_app/utils/l10n_utils.dart';
-import 'package:flutter/material.dart';
-import 'package:flutter_bloc/flutter_bloc.dart';
-import 'package:payment_plugin/presentation/app/bloc/payment_cards_cubit.dart';
-import 'package:payment_plugin/presentation/app/bloc/payment_cards_state.dart';
-
-class PreregConfirmationPage extends StatelessWidget {
- const PreregConfirmationPage({super.key});
-
- @override
- Widget build(BuildContext context) {
- return BlocBuilder<PaymentCardsCubit, PaymentCardsState>(
- builder: (context, state) {
- final cubit = context.read<PreregistrationCubit>();
-
- final state = cubit.state;
- final user = state.user!;
- final theme = Theme.of(context);
- final singularExtra =
- cubit.numOfExtras == 1 && cubit.state.selectedRoomUpgrade.isEmpty ||
- cubit.numOfExtras == 0 && cubit.state.selectedRoomUpgrade.isNotEmpty;
- String extrasTitleText;
-
- if (singularExtra) {
- extrasTitleText = context.strings.preregistration_confirmation_extras_card_title_singular;
- } else {
- extrasTitleText = context.strings.preregistration_confirmation_extras_card_title_plural(
- cubit.numOfExtras.toString(),
- );
- }
-
- return SafeArea(
- child: ListView(
- padding: const EdgeInsets.symmetric(horizontal: 12.0),
- children: [
- const SizedBox(height: 16),
- Text(
- context.strings.preregistration_confirmation_title,
- style: Theme.of(context).textTheme.headlineLarge,
- ),
- const SizedBox(height: 16),
- InformationCard(
- title: context.strings.preregistration_confirmation_profile_card_title,
- titleStyle: theme.textTheme.titleMedium?.copyWith(
- fontWeight: FontWeight.w500,
- color: colorHeadlineText,
- ),
- onEditClick: cubit.onEditProfileClicked,
- child: Column(
- crossAxisAlignment: CrossAxisAlignment.start,
- children: [
- Text(
- "${state.user!.firstName} ${state.user!.lastName}",
- style: Theme.of(context).textTheme.bodyMedium,
- ),
- Text(
- user.email,
- style: Theme.of(context).textTheme.bodyMedium,
- ),
- Text(
- state.user!.phoneNumber,
- style: Theme.of(context).textTheme.bodyMedium,
- ),
- ],
- ),
- ),
- const SizedBox(height: 12),
- InformationCard(
- title: context.strings.preregistration_confirmation_address_card_title,
- titleStyle: theme.textTheme.titleMedium?.copyWith(
- fontWeight: FontWeight.w500,
- color: colorHeadlineText,
- ),
- onEditClick: cubit.onEditAddressClicked,
- child: Column(
- crossAxisAlignment: CrossAxisAlignment.start,
- children: [
- Text(
- cubit.state.user!.address.street,
- style: theme.textTheme.bodyMedium,
- ),
- Text(
- "${state.user!.address.zipCode}, ${state.user!.address.city}${state.user!.address.country.isNotEmpty ? ', ${state.user!.address.country}' : ''}",
- style: theme.textTheme.bodyMedium,
- ),
- ],
- ),
- ),
- const SizedBox(height: 12),
- InformationCard(
- title: extrasTitleText,
- titleStyle: theme.textTheme.titleMedium?.copyWith(
- fontWeight: FontWeight.w500,
- color: colorHeadlineText,
- ),
- onEditClick: cubit.onEditExtrasClicked,
- child: Column(
- crossAxisAlignment: CrossAxisAlignment.start,
- children: [
- Text(
- context.strings.total_charge_value(cubit.extrasTotalPrice.toString()),
- style: theme.textTheme.bodyMedium,
- ),
- Text(
- context.strings.preregistration_confirmation_extras_card_subtitle,
- style: theme.textTheme.bodySmall?.copyWith(
- color: colorHeadlineText,
- ),
- ),
- ],
- ),
- ),
- const SizedBox(height: 40),
- ],
- ),
- );
- },
- );
- }
-}
diff --git a/comwell_key_app/lib/pregistration/pages/prereg_profile_page.dart b/comwell_key_app/lib/pregistration/pages/prereg_profile_page.dart
deleted file mode 100644
index fcf30da7..00000000
--- a/comwell_key_app/lib/pregistration/pages/prereg_profile_page.dart
+++ /dev/null
@@ -1,114 +0,0 @@
-import 'package:comwell_key_app/common/components/comwell_text_field.dart';
-import 'package:comwell_key_app/profile_settings/components/intl_phone_field.dart';
-import 'package:comwell_key_app/pregistration/cubit/preregistration_cubit.dart';
-import 'package:comwell_key_app/pregistration/cubit/preregistration_state.dart';
-import 'package:comwell_key_app/utils/l10n_utils.dart';
-import 'package:country_code_picker/country_code_picker.dart';
-import 'package:flutter/material.dart';
-import 'package:flutter_bloc/flutter_bloc.dart';
-import '../../common/components/shimmer_loader/prereg_profile_shimmer_loader.dart';
-
-class PreregProfilePage extends StatelessWidget {
- const PreregProfilePage({super.key});
-
- @override
- Widget build(BuildContext context) {
- final theme = Theme.of(context);
- return BlocBuilder<PreregistrationCubit, PreregistrationState>(
- builder: (context, state) {
- if (state.isLoading) {
- return const Center(child: PreregProfileShimmerLoader());
- }
-
- if (state.user != null) {
- return _buildProfilePage(theme, state, context);
- }
-
- return Center(
- child: Text(
- context.strings.generic_error,
- style: theme.textTheme.headlineLarge,
- ),
- );
- },
- );
- }
-
- Widget _buildProfilePage(ThemeData theme, PreregistrationState state, BuildContext context) {
- final cubit = context.read<PreregistrationCubit>();
-
- final firstNameErrorMessage = !cubit.isFirstNameValid && state.missingInformation
- ? context.strings.generic_information_required
- : null;
- final lastNameErrorMessage = !cubit.isLastNameValid && state.missingInformation
- ? context.strings.generic_information_required
- : null;
- final phoneNumberErrorMessage = !cubit.isPhoneNumberValid && state.missingInformation
- ? context.strings.generic_information_required
- : null;
-
- return ListView(
- children: [
- Padding(
- padding: const EdgeInsets.symmetric(horizontal: 12.0),
- child: Column(
- crossAxisAlignment: CrossAxisAlignment.start,
- children: [
- const SizedBox(height: 36),
- ComwellTextField(
- key: const Key("firstName"),
- fieldName: context.strings.profile_settings_firstname,
- initialValue: state.user!.firstName,
- readOnly: false,
- controller: cubit.firstNameTextController,
- errorMessage: firstNameErrorMessage,
- onChanged: (value) {
- cubit.firstNameTextController.text = value;
- },
- ),
- const SizedBox(height: 8),
- ComwellTextField(
- key: const Key("lastName"),
- fieldName: context.strings.profile_settings_lastname,
- initialValue: state.user!.lastName,
- readOnly: false,
- controller: cubit.lastNameTextController,
- errorMessage: lastNameErrorMessage,
- onChanged: (value) {
- cubit.lastNameTextController.text = value;
- },
- ),
- const SizedBox(height: 8),
- ComwellTextField(
- key: const Key("email"),
- fieldName: context.strings.profile_settings_email,
- initialValue: state.user!.email,
- readOnly: true,
- controller: cubit.emailTextController,
- ),
- const SizedBox(height: 8),
- IntlPhoneField(
- key: const Key("phone"),
- title: context.strings.profile_settings_phone,
- phoneNumber: cubit.phoneNumber!,
- countryCode: cubit.countryCode!,
- controller: cubit.phoneNumberTextController,
- readOnly: false,
- errorMessage: phoneNumberErrorMessage,
- onCountryCodeSelected: (CountryCode countryCode) {
- cubit.onCountryCodeSelected(countryCode);
- },
- onPhoneNumberChanged: (String phoneNumber) {
- cubit.onPhoneNumberChanged(phoneNumber);
- },
- onSubmitted: (_) {
- // NO OP
- },
- ),
- ],
- ),
- ),
- ],
- );
- }
-}
diff --git a/comwell_key_app/lib/pregistration/pages/prereg_up_sales_catalog_page.dart b/comwell_key_app/lib/pregistration/pages/prereg_up_sales_catalog_page.dart
deleted file mode 100644
index 4e43da47..00000000
--- a/comwell_key_app/lib/pregistration/pages/prereg_up_sales_catalog_page.dart
+++ /dev/null
@@ -1,125 +0,0 @@
-import 'package:comwell_key_app/common/components/comwell_app_bar.dart';
-import 'package:comwell_key_app/common/components/comwell_error_widget.dart';
-import 'package:comwell_key_app/common/components/shimmer_loader/up_sales_catalog_shimmer_loader.dart';
-import 'package:comwell_key_app/up_sales/components/catalog/addon_upgrade_catalog.dart';
-import 'package:comwell_key_app/up_sales/components/catalog/room_upgrade_catalog.dart';
-import 'package:comwell_key_app/up_sales/components/catalog/service_catalog.dart';
-import 'package:comwell_key_app/pregistration/cubit/preregistration_cubit.dart';
-import 'package:comwell_key_app/pregistration/cubit/preregistration_state.dart';
-import 'package:comwell_key_app/utils/l10n_utils.dart';
-import 'package:flutter/material.dart';
-import 'package:flutter_bloc/flutter_bloc.dart';
-
-class PreregUpSalesCatalogPage extends StatelessWidget {
- const PreregUpSalesCatalogPage({super.key});
-
- @override
- Widget build(BuildContext context) {
- final theme = Theme.of(context);
- return BlocBuilder<PreregistrationCubit, PreregistrationState>(
- builder: (context, state) {
- final cubit = context.read<PreregistrationCubit>();
-
- if (state.isLoading) {
- return Scaffold(
- appBar: const ComwellAppBar(),
- backgroundColor: Theme.of(context).colorScheme.surface,
- body: const UpSalesCatalogShimmerLoader(),
- );
- }
-
- final serviceUpgrades = cubit.state.addOnUpgrades
- .where((upgrade) => upgrade.isService)
- .toList();
- final addonUpgrades = cubit.state.addOnUpgrades
- .where((upgrade) => !upgrade.isService)
- .toList();
- final selectedRoomUpgrade = cubit.state.selectedRoomUpgrade.isEmpty
- ? null
- : cubit.state.availableRoomUpgrades
- .firstWhere((e) => e.id == cubit.state.selectedRoomUpgrade);
-
- return SingleChildScrollView(
- child: Padding(
- padding: const EdgeInsets.only(
- top: 24,
- bottom: 100,
- ),
- child: Column(
- crossAxisAlignment: CrossAxisAlignment.start,
- children: [
- Padding(
- padding: const EdgeInsets.symmetric(horizontal: 16),
- child: Text(context.strings.up_sales_catalog_title,
- style: theme.textTheme.headlineLarge),
- ),
- const SizedBox(height: 40),
- if (serviceUpgrades.isEmpty && addonUpgrades.isEmpty && cubit.state.availableRoomUpgrades.isEmpty) ...[
- ComwellErrorWidget(
- title: context.strings.up_sales_catalog_no_up_sales_title,
- subtitle: context.strings.up_sales_catalog_no_up_sales_subtitle,
- border: true)
- ],
- if (serviceUpgrades.isNotEmpty) ...[
- Padding(
- padding: const EdgeInsets.symmetric(horizontal: 16),
- child: Text(context.strings.services,
- style: theme.textTheme.headlineMedium),
- ),
- const SizedBox(height: 8),
- ServiceCatalog(
- booking: cubit.booking,
- upSales: serviceUpgrades,
- onServiceSelected: (upgrade, isSelected) {
- cubit.toggleSelectedUpgrade(upgrade);
- },
- onTap: (upgrade) {
- cubit.toggleSelectedUpgrade(upgrade);
- },
- ),
- ],
- if (cubit.state.availableRoomUpgrades.isNotEmpty) ...[
- const SizedBox(height: 24),
- Padding(
- padding: const EdgeInsets.symmetric(horizontal: 16),
- child: Text(context.strings.room_upgrades,
- style: theme.textTheme.headlineMedium),
- ),
- const SizedBox(height: 8),
- RoomUpgradeCatalog(
- booking: cubit.booking,
- availableRoomUpgrades: cubit.state.availableRoomUpgrades,
- selectedRoomUpgrade: cubit.state.selectedRoomUpgrade,
- onRoomUpgradeSelected: (upgrade, isSelected) {
- cubit.toggleSelectedUpgrade(upgrade);
- },
- onTap: (upgrade) {
- cubit.toggleSelectedUpgrade(upgrade);
- },
- ),
- ],
- if (addonUpgrades.isNotEmpty) ...[
- const SizedBox(height: 24),
- Padding(
- padding: const EdgeInsets.symmetric(horizontal: 16),
- child: Text(context.strings.other_up_sales,
- style: theme.textTheme.headlineMedium),
- ),
- const SizedBox(height: 8),
- AddOnUpgradeCatalog(
- addOnUpgrades: cubit.otherUpgrades,
- extrasTotalPrice: cubit.extrasTotalPrice,
- selectedRoomUpgrade: selectedRoomUpgrade?.id ?? '',
- onAddOnUpgradeSelected: (upgrade, quantity) {
- cubit.updateAddonUpgradeQuantity(upgrade, quantity);
- },
- ),
- ],
- const SizedBox(height: 24),
- ],
- ),
- ),
- );
- });
- }
-}
diff --git a/comwell_key_app/lib/pregistration/pregistration_repository.dart b/comwell_key_app/lib/pregistration/pregistration_repository.dart
deleted file mode 100644
index ca97b728..00000000
--- a/comwell_key_app/lib/pregistration/pregistration_repository.dart
+++ /dev/null
@@ -1,206 +0,0 @@
-import 'package:comwell_key_app/pregistration/prereg_request_model.dart';
-import 'package:comwell_key_app/profile_settings/repostiory/profile_settings_repository.dart';
-import 'package:comwell_key_app/services/api.dart';
-import 'package:comwell_key_app/utils/locator.dart';
-import 'package:flutter/material.dart';
-
-class PreregistrationRepository {
- final Api _api = Api();
- final ProfileSettingsRepository profileSettingsRepository =
- locator<ProfileSettingsRepository>();
-
- PreregistrationRepository();
-
-/* Future<PaymentConfigurations?> sessionCheckout(
- String hotelCode,
- String bookingId,
- bool usePoints,
- ) async {
- final response = await _api.createAdyenSession(bookingId, usePoints, hotelCode);
- final clientKey = response["clientKey"] as String;
- final sessionResponse = response["sessionResponse"];
- final payedWithPoints = response["isFullyPaidWithPoints"] as bool;
- if (payedWithPoints) {
- return null;
- }
- final id = sessionResponse["id"] as String;
- final sessionData = sessionResponse["sessionData"] as String;
- final availablePaymentMethods =
- await _api.listAvailablePaymentMethods() as Map<String, dynamic>;
-
- final scheme = _findPaymentMethod(availablePaymentMethods, "scheme");
- final googlePay = _findPaymentMethod(availablePaymentMethods, "googlePay");
- final applePay = _findPaymentMethod(availablePaymentMethods, "applePay");
-
- // 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(serverAmount, clientKey, false));
-
- return PaymentConfigurations(
- sessionCheckout: session,
- googlePayConfiguration: _getGooglePayComponentConfig(clientKey),
- dropInConfiguration:
- dropInConfiguration(serverAmount, clientKey, false),
- cardComponentConfiguration:
- cardComponentConfiguration(serverAmount, clientKey),
- applePayConfiguration:
- _applePayComponentConfiguration(clientKey, serverAmount, false),
- isFullyPaidWithPoints: payedWithPoints,
- availablePaymentMethods: [scheme!, googlePay!, applePay!]);
- }
-
- Future<PaymentConfigurations?> fetchSessionForAddingCard() async {
- final response = await _api.createAdyenSessionForCards();
- final availablePaymentMethods =
- await _api.listAvailablePaymentMethods() as Map<String, dynamic>;
-
- final clientKey = response["clientKey"] as String;
- final sessionResponse = response["sessionResponse"];
- final id = sessionResponse["id"] as String;
- final sessionData = sessionResponse["sessionData"] as String;
-
- final scheme = _findPaymentMethod(availablePaymentMethods, "scheme");
- final googlePay = _findPaymentMethod(availablePaymentMethods, "googlePay");
- final applePay = _findPaymentMethod(availablePaymentMethods, "applePay");
-
- final session = await AdyenCheckout.session.create(
- sessionId: id,
- sessionData: sessionData,
- configuration: cardComponentConfiguration(
- Amount(value: 0, currency: "DKK"), clientKey),
- );
-
- return PaymentConfigurations(
- sessionCheckout: session,
- availablePaymentMethods: [scheme!, googlePay!, applePay!],
- googlePayConfiguration: _getGooglePayComponentConfig(clientKey),
- dropInConfiguration: dropInConfiguration(
- Amount(value: 0, currency: "DKK"), clientKey, true),
- cardComponentConfiguration: cardComponentConfiguration(
- Amount(value: 0, currency: "DKK"), clientKey),
- applePayConfiguration: _applePayComponentConfiguration(
- clientKey, Amount(value: 0, currency: "DKK"), true),
- isFullyPaidWithPoints: false);
- } */
-
- Future<dynamic> createPreregistration(PreregRequestDto request) async {
- try {
- debugPrint("request: $request.toString()");
- final response = await _api.preRegistration(request);
-
- return response.data!;
- } catch (e) {
- debugPrint("error: $e");
- return null;
- }
- }
-}
-/*
- CardComponentConfiguration cardComponentConfiguration(
- Amount amount,
- String clientKey,
- ) {
- return CardComponentConfiguration(
- environment: Environment.test,
- amount: amount,
- cardConfiguration: const CardConfiguration(showStorePaymentField: false),
- clientKey: clientKey,
- countryCode: "DK",
- );
- }
-
- DropInConfiguration dropInConfiguration(
- Amount amount, String clientKey, bool addCard) {
- return DropInConfiguration(
- environment: Environment.test,
- clientKey: clientKey,
- countryCode: "DK",
- skipListWhenSinglePaymentMethod: true,
- googlePayConfiguration: _googlePayConfiguration,
- applePayConfiguration: _getApplePlayConfig(amount, addCard),
- cardConfiguration: const CardConfiguration(showStorePaymentField: false),
- paymentMethodNames: {
- "scheme": "Credit card",
- },
- );
- }
-
- GooglePayConfiguration get _googlePayConfiguration =>
- const GooglePayConfiguration(
- googlePayEnvironment: GooglePayEnvironment.test,
- );
-
- GooglePayComponentConfiguration _getGooglePayComponentConfig(
- String clientKey,
- ) {
- return GooglePayComponentConfiguration(
- environment: Environment.test,
- countryCode: "DK",
- clientKey: clientKey,
- googlePayConfiguration: _googlePayConfiguration,
- );
- }
-
- ApplePayComponentConfiguration _applePayComponentConfiguration(
- String clientKey,
- Amount amount,
- bool addCard,
- ) {
- return ApplePayComponentConfiguration(
- environment: Environment.test,
- countryCode: "DK",
- clientKey: clientKey,
- applePayConfiguration: _getApplePlayConfig(amount, addCard),
- );
- }
-
- ApplePayConfiguration _getApplePlayConfig(Amount amount, bool addCard) {
- return ApplePayConfiguration(
- merchantId: merchantId,
- merchantName: merchantName,
- allowOnboarding: true,
- allowShippingContactEditing: true,
- applePaySummaryItems: [
- ApplePaySummaryItem(
- label: addCard ? "add_card".tr() : "total".tr(),
- amount: Amount(value: amount.value, currency: amount.currency),
- type: ApplePaySummaryItemType.definite)
- ]);
- }
-
- static final Iterable<StoredPaymentMethod> mockStoredPaymentData = [
- 1,
- 2,
- 3,
- 4
- ].map((i) => StoredPaymentMethod(
- expiryMonth: "12",
- expiryYear: "2035",
- holderName: "holder name",
- id: "id $i",
- lastFour: "$i$i$i$i",
- brand: "visa"));
-}
-
-Map<String, dynamic>? _findPaymentMethod(
- Map<String, dynamic> pmResponse,
- String type,
-) {
- final list =
- (pmResponse['paymentMethods'] as List?)?.cast<Map<String, dynamic>>() ??
- const <Map<String, dynamic>>[];
-
- for (final m in list) {
- final t = (m['type'] as String?)?.toLowerCase();
- if (t == type.toLowerCase()) {
- return m; // e.g. 'scheme', 'applepay', 'googlepay'
- }
- }
- return null;
-}
-*/
\ No newline at end of file
diff --git a/comwell_key_app/lib/pregistration/prereg_request_model.dart b/comwell_key_app/lib/pregistration/prereg_request_model.dart
deleted file mode 100644
index 087b01a3..00000000
--- a/comwell_key_app/lib/pregistration/prereg_request_model.dart
+++ /dev/null
@@ -1,50 +0,0 @@
-class PreregRequestDto {
- final String firstName;
- final String lastName;
- final String email;
- final String phoneNumber;
- final String birthDay;
- final String address;
- final String zipCode;
- final String city;
- final String country;
- final String confirmationNumber;
-
- final String hotelCode;
- final bool comwellClubTermsOfUseConsentChoice;
- final bool comwellClubMarketingConsentChoice;
-
- PreregRequestDto({
- required this.firstName,
- required this.lastName,
- required this.email,
- required this.phoneNumber,
- required this.birthDay,
- required this.address,
- required this.zipCode,
- required this.city,
- required this.country,
- required this.confirmationNumber,
- required this.hotelCode,
- required this.comwellClubTermsOfUseConsentChoice,
- required this.comwellClubMarketingConsentChoice,
- });
-
- Map<String, dynamic> toJson() {
- return {
- 'firstName': firstName,
- 'lastName': lastName,
- 'email': email,
- 'phoneNumber': phoneNumber,
- 'birthDay': birthDay,
- 'address': address,
- 'zipCode': zipCode,
- 'city': city,
- 'country': country,
- 'confirmationNumber': confirmationNumber,
- 'hotelCode': hotelCode,
- 'comwellClubTermsOfUseConsentChoice': comwellClubTermsOfUseConsentChoice,
- 'comwellClubMarketingConsentChoice': comwellClubMarketingConsentChoice,
- };
- }
-}
diff --git a/comwell_key_app/lib/pregistration/preregistration_flow.dart b/comwell_key_app/lib/pregistration/preregistration_flow.dart
deleted file mode 100644
index 16fdad9c..00000000
--- a/comwell_key_app/lib/pregistration/preregistration_flow.dart
+++ /dev/null
@@ -1,112 +0,0 @@
-import 'package:comwell_key_app/common/components/comwell_app_bar.dart';
-
-import 'package:comwell_key_app/pregistration/cubit/preregistration_state.dart';
-import 'package:comwell_key_app/pregistration/cubit/preregistration_cubit.dart';
-import 'package:comwell_key_app/pregistration/utils/utils.dart';
-import 'package:comwell_key_app/themes/light_theme.dart';
-import 'package:comwell_key_app/utils/locator.dart';
-import 'package:flutter/material.dart';
-import 'package:flutter_bloc/flutter_bloc.dart';
-import 'package:go_router/go_router.dart';
-import 'package:payment_plugin/domain/repositories/adyen_repository.dart';
-import 'package:payment_plugin/presentation/app/bloc/payment_cards_cubit.dart';
-import 'package:payment_plugin/presentation/app/bloc/payment_cards_state.dart';
-import '../common/components/shimmer_loader/prereg_flow_shimmer_loader.dart';
-
-class PreregistrationFlow extends StatefulWidget {
- const PreregistrationFlow({super.key});
-
- @override
- State<PreregistrationFlow> createState() => _PreregistrationFlowState();
-}
-
-class _PreregistrationFlowState extends State<PreregistrationFlow> {
- @override
- Widget build(BuildContext context) {
- return BlocProvider<PaymentCardsCubit>(
- create: (context) => PaymentCardsCubit(
- adyenRepository: locator<AdyenRepository>(),
- onPaymentMethodSelected: (paymentMethod) {
- context.read<PreregistrationCubit>().onPaymentMethodSelected(paymentMethod);
- },
- onPaymentMethodValidationError: () {
- context.read<PreregistrationCubit>().onPaymentMethodValidationError();
- },
- initialSelectedPaymentMethod: context
- .read<PreregistrationCubit>()
- .state
- .selectedPaymentMethod,
- ),
- child: BlocBuilder<PaymentCardsCubit, PaymentCardsState>(
- builder: (context, state) {
- return BlocBuilder<PreregistrationCubit, PreregistrationState>(
- builder: (context, state) {
- final cubit = context.read<PreregistrationCubit>();
- return Scaffold(
- backgroundColor: Theme.of(context).colorScheme.surface,
- appBar: ComwellAppBar(
- shouldShowProfileButton: false,
- shouldShowBackButton: true,
- onBackPressed: () {
- if (cubit.currentPage == PreregistrationPage.profile) {
- context.pop();
- } else {
- cubit.onBackClicked();
- }
- },
- ),
- body: Builder(
- builder: (context) {
- if (state.isLoading) {
- return const Center(child: PreregFlowShimmerLoader());
- }
- return PageView(
- key: const PageStorageKey("prereg_flow"),
- physics: const NeverScrollableScrollPhysics(),
- controller: cubit.pageController,
- children: PreregistrationPage.getPages(ValueKey(state)).toList(),
- );
- },
- ),
- bottomNavigationBar: Builder(
- builder: (context) {
- if (state.isLoading) return const SizedBox();
- return Column(
- // BOTTOM NAVIGATION
- mainAxisSize: MainAxisSize.min,
- children: [
- const Divider(
- color: Colors.black12,
- height: 0,
- ),
- Row(
- children: [
- Expanded(
- child: Padding(
- padding: const EdgeInsets.fromLTRB(16.0, 16.0, 16.0, 40.0),
- child: ElevatedButton(
- onPressed: () {
- cubit.onContinueClicked(context);
- },
- style: ElevatedButton.styleFrom(foregroundColor: colorBackground),
- child: Padding(
- padding: const EdgeInsets.symmetric(vertical: 16.0),
- child: Text(cubit.buttonText(context)),
- ),
- ),
- ),
- ),
- ],
- ),
- ],
- );
- },
- ),
- );
- },
- );
- },
- ),
- );
- }
-}
diff --git a/comwell_key_app/lib/pregistration/preregistration_route.dart b/comwell_key_app/lib/pregistration/preregistration_route.dart
deleted file mode 100644
index c29b2565..00000000
--- a/comwell_key_app/lib/pregistration/preregistration_route.dart
+++ /dev/null
@@ -1,18 +0,0 @@
-import 'package:comwell_key_app/overview/models/booking.dart';
-import 'package:comwell_key_app/pregistration/cubit/preregistration_cubit.dart';
-import 'package:comwell_key_app/pregistration/preregistration_flow.dart';
-import 'package:comwell_key_app/routing/app_routes.dart';
-import 'package:flutter_bloc/flutter_bloc.dart';
-import 'package:go_router/go_router.dart';
-
-final preregistrationRoute = GoRoute(
- path: AppRoutes.preregistration,
- builder: (context, state) {
- final extras = state.extra as List<dynamic>;
- final booking = extras[0] as Booking;
- return BlocProvider(
- create: (context) => PreregistrationCubit(booking: booking),
- child: const PreregistrationFlow(),
- );
- },
-);
diff --git a/comwell_key_app/lib/pregistration/utils/utils.dart b/comwell_key_app/lib/pregistration/utils/utils.dart
deleted file mode 100644
index 73a58a55..00000000
--- a/comwell_key_app/lib/pregistration/utils/utils.dart
+++ /dev/null
@@ -1,34 +0,0 @@
-import 'package:comwell_key_app/pregistration/pages/prereg_address_page.dart';
-import 'package:comwell_key_app/pregistration/pages/prereg_confirmation_page.dart';
-import 'package:comwell_key_app/pregistration/pages/prereg_profile_page.dart';
-import 'package:comwell_key_app/pregistration/pages/prereg_up_sales_catalog_page.dart';
-import 'package:flutter/material.dart';
-
-enum PreregistrationPage {
- profile,
- address,
- //payment,
- upSales,
- confirmation;
-
- static PreregistrationPage fromIndex(int index) {
- return PreregistrationPage.values[index];
- }
-
- static Iterable<Widget> getPages(Key key) {
- return PreregistrationPage.values.map((page) {
- switch (page) {
- case PreregistrationPage.profile:
- return PreregProfilePage(key: key);
- case PreregistrationPage.address:
- return PreregAddressPage(key: key);
- /* case PreregistrationPage.payment:
- return const PaymentCardsPage(); */
- case PreregistrationPage.upSales:
- return const PreregUpSalesCatalogPage();
- case PreregistrationPage.confirmation:
- return PreregConfirmationPage(key: key);
- }
- });
- }
-}
diff --git a/comwell_key_app/lib/presentation/screens/booking_details/bloc/booking_details_cubit.dart b/comwell_key_app/lib/presentation/screens/booking_details/bloc/booking_details_cubit.dart
index 97da729a..cc069394 100644
--- a/comwell_key_app/lib/presentation/screens/booking_details/bloc/booking_details_cubit.dart
+++ b/comwell_key_app/lib/presentation/screens/booking_details/bloc/booking_details_cubit.dart
@@ -267,9 +267,10 @@ class BookingDetailsCubit extends BaseCubit<BookingDetailsState> {
bool get canOrderHousekeeping {
final now = DateTime.now();
+ final today = DateTime(now.year, now.month, now.day);
final tomorrow = DateTime(now.year, now.month, now.day + 1);
final checkoutDay = DateTime(booking.endDate.year, booking.endDate.month, booking.endDate.day);
- if (checkoutDay == tomorrow) return false;
+ if (checkoutDay == today || checkoutDay == tomorrow) return false;
return booking.endDate.difference(booking.startDate).inDays >= 2;
}
diff --git a/comwell_key_app/lib/presentation/screens/pregistration/components/information_card.dart b/comwell_key_app/lib/presentation/screens/pregistration/components/information_card.dart
new file mode 100644
index 00000000..d4937e5a
--- /dev/null
+++ b/comwell_key_app/lib/presentation/screens/pregistration/components/information_card.dart
@@ -0,0 +1,42 @@
+import 'package:comwell_key_app/themes/dark_theme.dart';
+import 'package:comwell_key_app/utils/l10n_utils.dart';
+import 'package:flutter/material.dart';
+
+class InformationCard extends StatelessWidget {
+ final String title;
+ final VoidCallback onEditClick;
+ final Widget child;
+ final TextStyle? titleStyle;
+
+ const InformationCard({
+ super.key,
+ required this.title,
+ required this.onEditClick,
+ required this.child,
+ this.titleStyle,
+ });
+
+ @override
+ Widget build(BuildContext context) {
+ return Container(
+ padding: const EdgeInsets.all(12),
+ decoration: BoxDecoration(
+ color: sandColor[10],
+ borderRadius: const BorderRadius.all(Radius.circular(10))),
+ child: Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ Row(
+ mainAxisAlignment: MainAxisAlignment.spaceBetween,
+ children: [
+ Text(title, style: titleStyle),
+ TextButton(onPressed: onEditClick, child: Text(context.strings.edit, style: const TextStyle(decoration: TextDecoration.underline, decorationColor: sandColor, color: sandColor),))
+ ],
+ ),
+ const SizedBox(height: 10),
+ child
+ ],
+ ),
+ );
+ }
+}
diff --git a/comwell_key_app/lib/presentation/screens/pregistration/components/prereg_bottom_button.dart b/comwell_key_app/lib/presentation/screens/pregistration/components/prereg_bottom_button.dart
new file mode 100644
index 00000000..88babb3f
--- /dev/null
+++ b/comwell_key_app/lib/presentation/screens/pregistration/components/prereg_bottom_button.dart
@@ -0,0 +1,43 @@
+import 'package:comwell_key_app/presentation/screens/pregistration/cubit/preregistration_cubit.dart';
+import 'package:comwell_key_app/themes/light_theme.dart';
+import 'package:flutter/material.dart';
+
+class PreregBottomButton extends StatelessWidget {
+ final bool loading;
+ final PreregistrationCubit cubit;
+ final String buttonText;
+ const PreregBottomButton({super.key, required this.loading, required this.cubit, required this.buttonText});
+
+ @override
+ Widget build(BuildContext context) {
+ return Builder(builder: (context) {
+ if (loading) return const SizedBox();
+ return Column(
+ mainAxisSize: MainAxisSize.min,
+ children: [
+ Row(
+ children: [
+ Expanded(
+ child: Padding(
+ padding: const EdgeInsets.fromLTRB(16.0, 16.0, 16.0, 40.0),
+ child: ElevatedButton(
+ 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/presentation/screens/pregistration/cubit/preregistration_cubit.dart b/comwell_key_app/lib/presentation/screens/pregistration/cubit/preregistration_cubit.dart
new file mode 100644
index 00000000..d8cb3511
--- /dev/null
+++ b/comwell_key_app/lib/presentation/screens/pregistration/cubit/preregistration_cubit.dart
@@ -0,0 +1,531 @@
+import 'package:comwell_key_app/domain/models/app_error.dart';
+import 'package:comwell_key_app/overview/models/booking.dart';
+import 'package:comwell_key_app/presentation/screens/pregistration/cubit/preregistration_state.dart';
+import 'package:comwell_key_app/presentation/screens/pregistration/prereg_request_model.dart';
+import 'package:comwell_key_app/domain/repositories/pregistration_repository.dart';
+import 'package:comwell_key_app/presentation/screens/pregistration/utils/utils.dart';
+import 'package:comwell_key_app/presentation/base/base_cubit.dart';
+import 'package:comwell_key_app/profile/profile_repository.dart';
+import 'package:comwell_key_app/profile_settings/model/address.dart';
+import 'package:comwell_key_app/profile_settings/repostiory/profile_settings_repository.dart';
+import 'package:comwell_key_app/tracking/comwell_tracking.dart';
+import 'package:comwell_key_app/tracking/models/analytics_event_item.dart';
+import 'package:comwell_key_app/up_sales/models/addon_list.dart';
+import 'package:comwell_key_app/up_sales/models/addon_upgrade.dart';
+import 'package:comwell_key_app/up_sales/models/room_upgrade.dart';
+import 'package:comwell_key_app/up_sales/models/upgrade.dart';
+import 'package:comwell_key_app/up_sales/up_sales_repository.dart';
+import 'package:comwell_key_app/utils/l10n_utils.dart';
+import 'package:comwell_key_app/utils/locator.dart';
+import 'package:comwell_key_app/utils/phone_utils.dart';
+import 'package:country_code_picker/country_code_picker.dart';
+import 'package:flutter/cupertino.dart';
+import 'package:go_router/go_router.dart';
+import 'package:payment_plugin/domain/models/stored_payment_method.dart';
+
+class PreregistrationCubit extends BaseCubit<PreregistrationState> {
+ final _profileRepository = locator<ProfileRepository>();
+ final _profileSettingsRepository = locator<ProfileSettingsRepository>();
+ final _tracking = locator<ComwellTracking>();
+ final _preregistrationRepository = locator<PreregistrationRepository>();
+ final _upSalesRepository = locator<UpSalesRepository>();
+
+ final Booking booking;
+
+ final pageController = PageController();
+ final addressTextController = TextEditingController();
+ final postalCodeTextController = TextEditingController();
+ final cityTextController = TextEditingController();
+ final firstNameTextController = TextEditingController();
+ final lastNameTextController = TextEditingController();
+ final emailTextController = TextEditingController();
+ final phoneNumberTextController = TextEditingController();
+ final documentNumberTextController = TextEditingController();
+
+ CountryCode? countryCode;
+ String? phoneNumber;
+
+ final List<String> favoriteCountries = ['DK', 'SE', 'NO', 'FI'];
+ final List<String> documentTypes = [
+ 'document_type_passport',
+ 'document_type_id_card',
+ 'document_type_driver_license',
+ 'document_type_other',
+ ];
+ String selectedDocumentType = '';
+
+ PreregistrationPage get currentPage =>
+ PreregistrationPage.fromIndex(pageController.page?.toInt() ?? 0);
+ bool _isAnimating = false;
+
+ PreregistrationCubit({required this.booking}) : super(const PreregistrationState()) {
+ _tracking.trackScreenView(
+ "Pre-registration - Betalingskort",
+ "/pre-registration/betalingskort",
+ );
+ init();
+ }
+
+ void init() async {
+ setupListeners();
+ safeEmit(state.copyWith(isLoading: true));
+ try {
+ final user = await _profileRepository.fetchProfileSettings();
+ addressTextController.text = user.address.street;
+ postalCodeTextController.text = user.address.zipCode;
+ cityTextController.text = user.address.city;
+
+ countryCode = getCountryCodeFromPhoneNumber(user.phoneNumber).$1;
+ phoneNumber = getCountryCodeFromPhoneNumber(user.phoneNumber).$2;
+
+ firstNameTextController.text = user.firstName;
+ lastNameTextController.text = user.lastName;
+ emailTextController.text = user.email;
+ phoneNumberTextController.text = phoneNumber ?? '';
+
+ safeEmit(state.copyWith(user: user));
+
+ final upSales = await _upSalesRepository.getUpSales(
+ booking.confirmationNumber,
+ booking.hotelCode,
+ );
+ safeEmit(
+ state.copyWith(
+ isLoading: false,
+ availableRoomUpgrades: upSales.roomUpgrades,
+ addOnUpgrades: upSales.addOnUpgrades,
+ selectedCountry: countryCode?.code ?? 'DK',
+ countryCode: countryCode,
+ phoneNumber: phoneNumber,
+ ),
+ );
+ } on Exception catch (e) {
+ debugPrint("error fetching preregistration: $e");
+ emit(state.copyWith(isLoading: false));
+ }
+ }
+
+ void setupListeners() {
+ phoneNumberTextController.addListener(() {
+ emit(
+ state.copyWith(
+ isPhoneNumberValid: isPhoneNumberValid,
+ missingInformation: false,
+ ),
+ );
+ });
+
+ addressTextController.addListener(() {
+ emit(
+ state.copyWith(
+ isAddressValid: isAddressValid,
+ missingInformation: false,
+ ),
+ );
+ });
+
+ postalCodeTextController.addListener(() {
+ emit(
+ state.copyWith(
+ isPostalCodeValid: isPostalCodeValid,
+ missingInformation: false,
+ ),
+ );
+ });
+
+ cityTextController.addListener(() {
+ emit(
+ state.copyWith(
+ isCityValid: isCityValid,
+ missingInformation: false,
+ ),
+ );
+ });
+ }
+
+ void onDocumentTypeSelected(String documentType) {
+ selectedDocumentType = documentType;
+ emit(state.copyWith(selectedDocumentType: documentType));
+ }
+
+ void onAddressContinueClicked() {
+ if (isAddressValid && isCityValid && isPostalCodeValid) {
+ final updatedUser = state.user!.copyWith(
+ address: Address(
+ street: addressTextController.text,
+ zipCode: postalCodeTextController.text,
+ city: cityTextController.text,
+ country: state.selectedCountry,
+ ),
+ );
+
+ emit(state.copyWith(user: updatedUser));
+ _navigateNextPage();
+ } else {
+ emit(state.copyWith(missingInformation: true));
+ }
+ }
+
+ void onProfileContinueClicked() {
+ if (isFirstNameValid && isLastNameValid && isPhoneNumberValid) {
+ final phoneNumber = concatCountryCodeAndPhoneNumber(
+ countryCode!,
+ phoneNumberTextController.text,
+ );
+ final updatedUser = state.user!.copyWith(
+ firstName: firstNameTextController.text,
+ lastName: lastNameTextController.text,
+ phoneNumber: phoneNumber,
+ );
+ emit(state.copyWith(user: updatedUser));
+
+ _navigateNextPage();
+ } else {
+ emit(state.copyWith(missingInformation: true));
+ }
+ }
+
+ bool onPaymentContinueClicked() {
+ if (state.selectedPaymentMethod != null) {
+ _navigateNextPage();
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ void onPaymentMethodValidationError() {
+ emit(state.copyWith(missingInformation: true));
+ }
+
+ void onUpSalesContinueClicked() {
+ _navigateNextPage();
+ }
+
+ void onContinueClicked(BuildContext context) {
+ if (_isAnimating) return;
+ switch (currentPage) {
+ case PreregistrationPage.profile:
+ onProfileContinueClicked();
+ break;
+ case PreregistrationPage.address:
+ onAddressContinueClicked();
+ break;
+ /* case PreregistrationPage.payment:
+ // Payment validation is handled in preregistration_flow.dart
+ onPaymentContinueClicked();
+ break; */
+ case PreregistrationPage.upSales:
+ onUpSalesContinueClicked();
+ break;
+ case PreregistrationPage.confirmation:
+ _onConfirmPressed(context);
+ break;
+ }
+ }
+
+ void onPaymentMethodSelected(StoredPaymentMethod paymentMethod) {
+ emit(
+ state.copyWith(
+ selectedPaymentMethod: paymentMethod,
+ missingInformation: false,
+ ),
+ );
+ }
+
+ void addToCart() {
+ final analyticsEventItem = AnalyticsEventItem(
+ hotelName: "Comwell",
+ currency: "DKK",
+ value: 500,
+ placement: "placement",
+ items: ["items"],
+ itemId: "itemId",
+ itemName: "itemName",
+ price: 200,
+ quantity: 200,
+ );
+ _tracking.trackAddToCart(analyticsEventItem);
+ }
+
+ void removeToCard() {
+ final analyticsEventItem = AnalyticsEventItem(
+ hotelName: "Comwell",
+ currency: "DKK",
+ value: 500,
+ placement: "placement",
+ items: ["items"],
+ itemId: "itemId",
+ itemName: "itemName",
+ price: 200,
+ quantity: 200,
+ );
+ _tracking.trackRemoveFromCart(analyticsEventItem);
+ }
+
+ void _onConfirmPressed(BuildContext context) async {
+ emit(state.copyWith(isLoading: true));
+ try {
+ final hasUpSales =
+ state.addOnUpgrades.any((e) => e.isAddedToCart) || state.selectedRoomUpgrade.isNotEmpty;
+
+ await _profileSettingsRepository.updateUser(state.user!);
+ if (hasUpSales) {
+ addUpSalesToBooking();
+ }
+
+ // Build the PreregRequestModel with all required fields
+ final preregRequest = PreregRequestDto(
+ firstName: state.user!.firstName,
+ lastName: state.user!.lastName,
+ email: state.user!.email,
+ phoneNumber: state.user!.phoneNumber,
+ birthDay: state.user!.birthDate.toIso8601String(),
+ address: state.user!.address.street,
+ zipCode: state.user!.address.zipCode,
+ city: state.user!.address.city,
+ country: state.user!.address.country,
+ confirmationNumber: booking.confirmationNumber,
+ hotelCode: booking.hotelCode,
+ comwellClubTermsOfUseConsentChoice: state.termsAndConditionsAccepted,
+ comwellClubMarketingConsentChoice: false,
+ );
+
+ final preRegResponse = await _preregistrationRepository.createPreregistration(preregRequest);
+
+ if (preRegResponse != null) {
+ Future.delayed(const Duration(seconds: 3), () {
+ emit(state.copyWith(isLoading: false));
+ if (!context.mounted) return;
+ context.pop(preRegResponse);
+ });
+ } else {
+ emit(state.copyWith(error: AppError.unknown('Pre-registration failed'), isLoading: false));
+ if (!context.mounted) return;
+ context.pop(null);
+ }
+ } catch (e) {
+ emit(state.copyWith(error: AppError.unknown(e.toString()), isLoading: false));
+ }
+ }
+
+ Future<void> addUpSalesToBooking() async {
+ // Extract RoomUpgrade from selectedUpSales to get the roomType
+ final roomType = state.selectedRoomUpgrade;
+
+ // Convert selected up sales to AddOnList objects using their individual quantities
+ final List<AddOnList> addonList = state.addOnUpgrades
+ .map((upgrade) => AddOnList(itemCode: upgrade.id, quantity: upgrade.quantity))
+ .toList();
+
+ await _upSalesRepository.addUpSalesToBooking(
+ booking.confirmationNumber,
+ booking.hotelCode,
+ roomType,
+ addonList,
+ );
+ }
+
+ void onEditProfileClicked() {
+ _navigateTo(PreregistrationPage.profile);
+ }
+
+ void onEditAddressClicked() {
+ _navigateTo(PreregistrationPage.address);
+ }
+
+ /* void onEditPaymentMethodCLickked() {
+ _navigateTo(PreregistrationPage.payment);
+ } */
+
+ void onEditExtrasClicked() {
+ _navigateTo(PreregistrationPage.upSales);
+ }
+
+ void onPhoneNumberChanged(String phoneNumber) {
+ phoneNumberTextController.text = phoneNumber;
+ emit(state.copyWith(isPhoneNumberValid: isPhoneNumberValid));
+ }
+
+ void onCountryCodeSelected(CountryCode country) {
+ countryCode = country;
+ emit(state.copyWith(countryCode: country, selectedCountry: country.code ?? ''));
+ }
+
+ bool onBackClicked() {
+ if (_isAnimating) return true;
+ final hasPage = pageController.page != null;
+ if (hasPage && pageController.page! >= 1.0) {
+ _navigatePreviousPage();
+ return true;
+ }
+ return false;
+ }
+
+ void _navigateTo(PreregistrationPage page) async {
+ if (_isAnimating) return;
+ _isAnimating = true;
+ await pageController.animateToPage(
+ page.index,
+ duration: const Duration(milliseconds: 500),
+ curve: Curves.fastOutSlowIn,
+ );
+ emit(state.copyWith(forceUpdate: true));
+ _isAnimating = false;
+ }
+
+ void _navigateNextPage() async {
+ if (_isAnimating) return;
+ _isAnimating = true;
+ await pageController.nextPage(
+ duration: const Duration(milliseconds: 500),
+ curve: Curves.fastOutSlowIn,
+ );
+ emit(state.copyWith(forceUpdate: true));
+ _isAnimating = false;
+ }
+
+ void _navigatePreviousPage() async {
+ if (_isAnimating) return;
+ _isAnimating = true;
+ await pageController.previousPage(
+ duration: const Duration(milliseconds: 500),
+ curve: Curves.fastOutSlowIn,
+ );
+ emit(state.copyWith(forceUpdate: true));
+ _isAnimating = false;
+ }
+
+ int get extrasTotalPrice {
+ //This is the total price of the selected up sales and the price of the selected
+ //room upgrade if it is selected
+
+ return selectedAddOnUpgrades.fold(0, (sum, upgrade) => sum + upgrade.price * upgrade.quantity) +
+ (state.selectedRoomUpgrade.isNotEmpty
+ ? state.availableRoomUpgrades.firstWhere((e) => e.id == state.selectedRoomUpgrade).price
+ : 0);
+ }
+
+ int get numOfExtras =>
+ selectedAddOnUpgrades.fold(0, (sum, upgrade) => sum + upgrade.quantity) +
+ (state.selectedRoomUpgrade.isNotEmpty ? 1 : 0);
+
+ List<AddOnUpgrade> get otherUpgrades {
+ final selectedUpgrades = state.addOnUpgrades.where((upgrade) => !upgrade.isService).toList();
+ return selectedUpgrades;
+ }
+
+ List<AddOnUpgrade> get selectedAddOnUpgrades {
+ final selectedUpgrades = state.addOnUpgrades.where((upgrade) => upgrade.isAddedToCart).toList();
+ return selectedUpgrades;
+ }
+
+ @override
+ Future<void> close() {
+ addressTextController.dispose();
+ postalCodeTextController.dispose();
+ cityTextController.dispose();
+ pageController.dispose();
+ firstNameTextController.dispose();
+ lastNameTextController.dispose();
+ emailTextController.dispose();
+ phoneNumberTextController.dispose();
+ documentNumberTextController.dispose();
+ return super.close();
+ }
+
+ bool get isAddressValid => addressTextController.text.isNotEmpty;
+
+ bool get isPostalCodeValid => postalCodeTextController.text.isNotEmpty;
+
+ bool get isCityValid => cityTextController.text.isNotEmpty;
+
+ bool get isDocumentNumberValid => documentNumberTextController.text.isNotEmpty;
+
+ bool get isPhoneNumberValid =>
+ phoneNumberTextController.text.length >= 7 && phoneNumberTextController.text.length < 16;
+
+ bool get isFirstNameValid => firstNameTextController.text.isNotEmpty;
+
+ bool get isLastNameValid => lastNameTextController.text.isNotEmpty;
+
+ bool get canContinue {
+ int page = pageController.page?.ceil() ?? 0;
+
+ final preregPage = PreregistrationPage.fromIndex(page);
+
+ switch (preregPage) {
+ case PreregistrationPage.profile:
+ return isFirstNameValid && isLastNameValid && isPhoneNumberValid;
+ case PreregistrationPage.address:
+ return isAddressValid && isPostalCodeValid && isCityValid;
+ case PreregistrationPage.upSales:
+ return true;
+ case PreregistrationPage.confirmation:
+ return true;
+ }
+ }
+
+ String buttonText(BuildContext context) {
+ int page = pageController.page?.ceil() ?? 0;
+ final preregPage = PreregistrationPage.fromIndex(page);
+ switch (preregPage) {
+ case PreregistrationPage.profile:
+ return context.strings.generic_continue;
+ case PreregistrationPage.address:
+ return context.strings.generic_continue;
+ case PreregistrationPage.upSales:
+ if (selectedAddOnUpgrades.isEmpty && state.selectedRoomUpgrade.isEmpty) {
+ return context.strings.continue_without_up_sales;
+ }
+ return context.strings.generic_continue;
+ case PreregistrationPage.confirmation:
+ return context.strings.generic_confirm;
+ }
+ }
+
+ void onTermsAndConditionsToggled(bool toggle) {
+ emit(state.copyWith(termsAndConditionsAccepted: toggle));
+ }
+
+ void toggleSelectedUpgrade(Upgrade upgrade) {
+ if (upgrade is RoomUpgrade) {
+ if (state.selectedRoomUpgrade == upgrade.id) {
+ emit(state.copyWith(selectedRoomUpgrade: ''));
+ } else {
+ emit(state.copyWith(selectedRoomUpgrade: upgrade.id));
+ }
+ } else if (upgrade is AddOnUpgrade) {
+ final updatedUpgrade = upgrade.copyWith(isSelected: !upgrade.isSelected, quantity: 1);
+ final updatedAddOnUpgrades = state.addOnUpgrades.toList();
+ final index = updatedAddOnUpgrades.indexWhere((e) => e.id == updatedUpgrade.id);
+ updatedAddOnUpgrades[index] = updatedUpgrade;
+ emit(state.copyWith(addOnUpgrades: updatedAddOnUpgrades));
+ }
+ }
+
+ void onContinue() {
+ emit(state.copyWith(selected: false));
+ }
+
+ void updateAddonUpgradeQuantity(AddOnUpgrade upgrade, int quantity) {
+ final updatedUpgrade = upgrade.copyWith(quantity: quantity);
+ final updatedAddOnUpgrades = state.addOnUpgrades.toList();
+ final index = updatedAddOnUpgrades.indexWhere((e) => e.id == updatedUpgrade.id);
+ updatedAddOnUpgrades[index] = updatedUpgrade;
+ emit(state.copyWith(addOnUpgrades: updatedAddOnUpgrades));
+ }
+
+ String get paymentMethodImage {
+ switch (state.selectedPaymentMethod?.brand) {
+ case 'mastercard':
+ return 'assets/images/master.svg';
+ case 'visa':
+ return 'assets/images/visa.svg';
+ case 'maestro':
+ return 'assets/images/maestro.svg';
+ default:
+ return 'assets/images/visa.png';
+ }
+ }
+}
diff --git a/comwell_key_app/lib/presentation/screens/pregistration/cubit/preregistration_state.dart b/comwell_key_app/lib/presentation/screens/pregistration/cubit/preregistration_state.dart
new file mode 100644
index 00000000..f93acc0c
--- /dev/null
+++ b/comwell_key_app/lib/presentation/screens/pregistration/cubit/preregistration_state.dart
@@ -0,0 +1,38 @@
+import 'package:comwell_key_app/domain/models/app_error.dart';
+import 'package:comwell_key_app/up_sales/models/addon_upgrade.dart';
+import 'package:comwell_key_app/up_sales/models/room_upgrade.dart';
+import 'package:country_code_picker/country_code_picker.dart';
+import 'package:freezed_annotation/freezed_annotation.dart';
+import 'package:payment_plugin/domain/models/stored_payment_method.dart';
+
+import '../../../../profile_settings/model/user.dart';
+
+part '../../../../.generated/presentation/screens/pregistration/cubit/preregistration_state.freezed.dart';
+
+@freezed
+abstract class PreregistrationState with _$PreregistrationState {
+ const factory PreregistrationState({
+ @Default(false) bool isLoading,
+ @Default(false) bool selected,
+ @Default([]) List<AddOnUpgrade> addOnUpgrades,
+ @Default([]) List<RoomUpgrade> availableRoomUpgrades,
+ @Default('') String selectedRoomUpgrade,
+ @Default(false) bool missingInformation,
+ @Default(0) int extrasTotalPrice,
+ @Default(false) bool termsAndConditionsAccepted,
+ @Default(false) bool forceUpdate,
+ @Default(null) User? user,
+ @Default(null) CountryCode? countryCode,
+ @Default('') String selectedCountry,
+ @Default(null) String? phoneNumber,
+ @Default(false) bool isPhoneNumberValid,
+ @Default(false) bool isFirstNameValid,
+ @Default(false) bool isLastNameValid,
+ @Default(false) bool isAddressValid,
+ @Default(false) bool isPostalCodeValid,
+ @Default(false) bool isCityValid,
+ @Default('') String selectedDocumentType,
+ @Default(null) StoredPaymentMethod? selectedPaymentMethod,
+ @Default(AppError.none) AppError error,
+ }) = _PreregistrationState;
+}
diff --git a/comwell_key_app/lib/presentation/screens/pregistration/pages/prereg_address_page.dart b/comwell_key_app/lib/presentation/screens/pregistration/pages/prereg_address_page.dart
new file mode 100644
index 00000000..399e176c
--- /dev/null
+++ b/comwell_key_app/lib/presentation/screens/pregistration/pages/prereg_address_page.dart
@@ -0,0 +1,152 @@
+import 'package:comwell_key_app/common/components/comwell_text_field.dart';
+import 'package:comwell_key_app/presentation/screens/pregistration/cubit/preregistration_cubit.dart';
+import 'package:comwell_key_app/presentation/screens/pregistration/cubit/preregistration_state.dart';
+import 'package:comwell_key_app/themes/light_theme.dart';
+import 'package:comwell_key_app/utils/l10n_utils.dart';
+import 'package:country_code_picker/country_code_picker.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter_bloc/flutter_bloc.dart';
+import 'package:comwell_key_app/common/components/shimmer_loader/prereg_address_shimmer_loader.dart';
+
+class PreregAddressPage extends StatelessWidget {
+ const PreregAddressPage({super.key});
+
+ @override
+ Widget build(BuildContext context) {
+ return BlocBuilder<PreregistrationCubit, PreregistrationState>(
+ builder: (context, state) {
+ final cubit = context.read<PreregistrationCubit>();
+
+ if (state.isLoading) {
+ return const Center(child: PreregAddressShimmerLoader());
+ }
+
+ final isFavoriteCountry = cubit.favoriteCountries.contains(state.selectedCountry);
+
+ final addressErrorMessage = !cubit.isAddressValid && state.missingInformation
+ ? context.strings.generic_information_required
+ : null;
+ final postalCodeErrorMessage = !cubit.isPostalCodeValid && state.missingInformation
+ ? context.strings.generic_information_required
+ : null;
+ final cityErrorMessage = !cubit.isCityValid && state.missingInformation
+ ? context.strings.generic_information_required
+ : null;
+
+ final documentNumberErrorMessage = !cubit.isDocumentNumberValid && state.missingInformation
+ ? context.strings.generic_information_required
+ : null;
+
+ return ListView(
+ padding: const EdgeInsets.symmetric(horizontal: 12.0),
+ key: const PageStorageKey("information_form"),
+ children: [
+ const SizedBox(height: 40),
+ Text(
+ context.strings.preregistration_address_title,
+ style: Theme.of(context).textTheme.headlineLarge,
+ ),
+ const SizedBox(height: 18),
+ Text(
+ context.strings.preregistration_address_subtitle,
+ style: Theme.of(context).textTheme.bodySmall,
+ ),
+ const SizedBox(height: 40),
+ ComwellTextField(
+ key: const Key("address"),
+ fieldName: context.strings.preregistration_address_label_address,
+ initialValue: "",
+ readOnly: false,
+ errorMessage: addressErrorMessage,
+ controller: cubit.addressTextController,
+ ),
+ const SizedBox(height: 12),
+ ComwellTextField(
+ fieldName: context.strings.preregistration_address_label_postal_code,
+ initialValue: "",
+ textInputType: TextInputType.number,
+ errorMessage: postalCodeErrorMessage,
+ readOnly: false,
+ controller: cubit.postalCodeTextController,
+ ),
+ const SizedBox(height: 12),
+ ComwellTextField(
+ fieldName: context.strings.preregistration_address_label_city,
+ initialValue: "",
+ readOnly: false,
+ errorMessage: cityErrorMessage,
+ controller: cubit.cityTextController,
+ ),
+ const SizedBox(height: 12),
+ Container(
+ height: 62,
+ width: double.infinity,
+ decoration: BoxDecoration(
+ borderRadius: BorderRadius.circular(8),
+ border: Border.all(color: colorDivider),
+ ),
+ child: CountryCodePicker(
+ alignLeft: true,
+ textOverflow: TextOverflow.visible,
+ initialSelection: cubit.countryCode?.name,
+ showFlag: true,
+ favorite: cubit.favoriteCountries,
+ showDropDownButton: true,
+ textStyle: Theme.of(context).textTheme.headlineSmall,
+ showCountryOnly: true,
+ showOnlyCountryWhenClosed: true,
+ onChanged: (CountryCode countryCode) {
+ cubit.onCountryCodeSelected(countryCode);
+ },
+ ),
+ ),
+ const SizedBox(height: 12),
+ if (!isFavoriteCountry) ...[
+ const Divider(color: colorDivider),
+ const SizedBox(height: 12),
+ Container(
+ height: 62,
+ width: double.infinity,
+ decoration: BoxDecoration(
+ borderRadius: BorderRadius.circular(8),
+ border: Border.all(color: colorDivider),
+ ),
+ child: Padding(
+ padding: const EdgeInsets.symmetric(vertical: 10, horizontal: 12),
+ child: DropdownButtonFormField<String>(
+ hint: Text(context.strings.document_type),
+ initialValue: state.selectedDocumentType.isNotEmpty
+ ? state.selectedDocumentType
+ : null,
+ style: Theme.of(context).textTheme.headlineSmall?.copyWith(color: Colors.black),
+ items: cubit.documentTypes
+ .map(
+ (documentType) =>
+ DropdownMenuItem(value: documentType, child: Text(documentType)),
+ )
+ .toList(),
+ onChanged: (value) {
+ if (value != null) {
+ cubit.onDocumentTypeSelected(value);
+ }
+ },
+ ),
+ ),
+ ),
+ const SizedBox(height: 12),
+ ComwellTextField(
+ key: const Key("document_number"),
+ fieldName: context.strings.document_number,
+ textInputType: TextInputType.number,
+ initialValue: "",
+ readOnly: false,
+ errorMessage: documentNumberErrorMessage,
+ controller: cubit.documentNumberTextController,
+ ),
+ ],
+ ],
+ );
+ },
+ );
+ }
+}
diff --git a/comwell_key_app/lib/presentation/screens/pregistration/pages/prereg_confirmation_page.dart b/comwell_key_app/lib/presentation/screens/pregistration/pages/prereg_confirmation_page.dart
new file mode 100644
index 00000000..b031fc63
--- /dev/null
+++ b/comwell_key_app/lib/presentation/screens/pregistration/pages/prereg_confirmation_page.dart
@@ -0,0 +1,123 @@
+import 'package:comwell_key_app/presentation/screens/pregistration/cubit/preregistration_cubit.dart';
+import 'package:comwell_key_app/presentation/screens/pregistration/components/information_card.dart';
+import 'package:comwell_key_app/themes/light_theme.dart';
+import 'package:comwell_key_app/utils/l10n_utils.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter_bloc/flutter_bloc.dart';
+import 'package:payment_plugin/presentation/app/bloc/payment_cards_cubit.dart';
+import 'package:payment_plugin/presentation/app/bloc/payment_cards_state.dart';
+
+class PreregConfirmationPage extends StatelessWidget {
+ const PreregConfirmationPage({super.key});
+
+ @override
+ Widget build(BuildContext context) {
+ return BlocBuilder<PaymentCardsCubit, PaymentCardsState>(
+ builder: (context, state) {
+ final cubit = context.read<PreregistrationCubit>();
+
+ final state = cubit.state;
+ final user = state.user!;
+ final theme = Theme.of(context);
+ final singularExtra =
+ cubit.numOfExtras == 1 && cubit.state.selectedRoomUpgrade.isEmpty ||
+ cubit.numOfExtras == 0 && cubit.state.selectedRoomUpgrade.isNotEmpty;
+ String extrasTitleText;
+
+ if (singularExtra) {
+ extrasTitleText = context.strings.preregistration_confirmation_extras_card_title_singular;
+ } else {
+ extrasTitleText = context.strings.preregistration_confirmation_extras_card_title_plural(
+ cubit.numOfExtras.toString(),
+ );
+ }
+
+ return SafeArea(
+ child: ListView(
+ padding: const EdgeInsets.symmetric(horizontal: 12.0),
+ children: [
+ const SizedBox(height: 16),
+ Text(
+ context.strings.preregistration_confirmation_title,
+ style: Theme.of(context).textTheme.headlineLarge,
+ ),
+ const SizedBox(height: 16),
+ InformationCard(
+ title: context.strings.preregistration_confirmation_profile_card_title,
+ titleStyle: theme.textTheme.titleMedium?.copyWith(
+ fontWeight: FontWeight.w500,
+ color: colorHeadlineText,
+ ),
+ onEditClick: cubit.onEditProfileClicked,
+ child: Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ Text(
+ "${state.user!.firstName} ${state.user!.lastName}",
+ style: Theme.of(context).textTheme.bodyMedium,
+ ),
+ Text(
+ user.email,
+ style: Theme.of(context).textTheme.bodyMedium,
+ ),
+ Text(
+ state.user!.phoneNumber,
+ style: Theme.of(context).textTheme.bodyMedium,
+ ),
+ ],
+ ),
+ ),
+ const SizedBox(height: 12),
+ InformationCard(
+ title: context.strings.preregistration_confirmation_address_card_title,
+ titleStyle: theme.textTheme.titleMedium?.copyWith(
+ fontWeight: FontWeight.w500,
+ color: colorHeadlineText,
+ ),
+ onEditClick: cubit.onEditAddressClicked,
+ child: Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ Text(
+ cubit.state.user!.address.street,
+ style: theme.textTheme.bodyMedium,
+ ),
+ Text(
+ "${state.user!.address.zipCode}, ${state.user!.address.city}${state.user!.address.country.isNotEmpty ? ', ${state.user!.address.country}' : ''}",
+ style: theme.textTheme.bodyMedium,
+ ),
+ ],
+ ),
+ ),
+ const SizedBox(height: 12),
+ InformationCard(
+ title: extrasTitleText,
+ titleStyle: theme.textTheme.titleMedium?.copyWith(
+ fontWeight: FontWeight.w500,
+ color: colorHeadlineText,
+ ),
+ onEditClick: cubit.onEditExtrasClicked,
+ child: Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ Text(
+ context.strings.total_charge_value(cubit.extrasTotalPrice.toString()),
+ style: theme.textTheme.bodyMedium,
+ ),
+ Text(
+ context.strings.preregistration_confirmation_extras_card_subtitle,
+ style: theme.textTheme.bodySmall?.copyWith(
+ color: colorHeadlineText,
+ ),
+ ),
+ ],
+ ),
+ ),
+ const SizedBox(height: 40),
+ ],
+ ),
+ );
+ },
+ );
+ }
+}
diff --git a/comwell_key_app/lib/presentation/screens/pregistration/pages/prereg_profile_page.dart b/comwell_key_app/lib/presentation/screens/pregistration/pages/prereg_profile_page.dart
new file mode 100644
index 00000000..8b9eb8f3
--- /dev/null
+++ b/comwell_key_app/lib/presentation/screens/pregistration/pages/prereg_profile_page.dart
@@ -0,0 +1,116 @@
+import 'package:comwell_key_app/common/components/comwell_error_widget.dart';
+import 'package:comwell_key_app/common/components/comwell_text_field.dart';
+import 'package:comwell_key_app/profile_settings/components/intl_phone_field.dart';
+import 'package:comwell_key_app/presentation/screens/pregistration/cubit/preregistration_cubit.dart';
+import 'package:comwell_key_app/presentation/screens/pregistration/cubit/preregistration_state.dart';
+import 'package:comwell_key_app/utils/l10n_utils.dart';
+import 'package:country_code_picker/country_code_picker.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter_bloc/flutter_bloc.dart';
+import 'package:comwell_key_app/common/components/shimmer_loader/prereg_profile_shimmer_loader.dart';
+
+class PreregProfilePage extends StatelessWidget {
+ const PreregProfilePage({super.key});
+
+ @override
+ Widget build(BuildContext context) {
+ final theme = Theme.of(context);
+ return BlocBuilder<PreregistrationCubit, PreregistrationState>(
+ builder: (context, state) {
+ if (state.isLoading) {
+ return const Center(child: PreregProfileShimmerLoader());
+ }
+
+ if (state.user != null) {
+ return _buildProfilePage(theme, state, context);
+ }
+
+ return Center(
+ child: ComwellErrorWidget(
+ title: context.strings.generic_error_title,
+ subtitle: context.strings.generic_error,
+ border: true,
+ ),
+ );
+ },
+ );
+ }
+
+ Widget _buildProfilePage(ThemeData theme, PreregistrationState state, BuildContext context) {
+ final cubit = context.read<PreregistrationCubit>();
+
+ final firstNameErrorMessage = !cubit.isFirstNameValid && state.missingInformation
+ ? context.strings.generic_information_required
+ : null;
+ final lastNameErrorMessage = !cubit.isLastNameValid && state.missingInformation
+ ? context.strings.generic_information_required
+ : null;
+ final phoneNumberErrorMessage = !cubit.isPhoneNumberValid && state.missingInformation
+ ? context.strings.generic_information_required
+ : null;
+
+ return ListView(
+ children: [
+ Padding(
+ padding: const EdgeInsets.symmetric(horizontal: 12.0),
+ child: Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ const SizedBox(height: 36),
+ ComwellTextField(
+ key: const Key("firstName"),
+ fieldName: context.strings.profile_settings_firstname,
+ initialValue: state.user!.firstName,
+ readOnly: false,
+ controller: cubit.firstNameTextController,
+ errorMessage: firstNameErrorMessage,
+ onChanged: (value) {
+ cubit.firstNameTextController.text = value;
+ },
+ ),
+ const SizedBox(height: 8),
+ ComwellTextField(
+ key: const Key("lastName"),
+ fieldName: context.strings.profile_settings_lastname,
+ initialValue: state.user!.lastName,
+ readOnly: false,
+ controller: cubit.lastNameTextController,
+ errorMessage: lastNameErrorMessage,
+ onChanged: (value) {
+ cubit.lastNameTextController.text = value;
+ },
+ ),
+ const SizedBox(height: 8),
+ ComwellTextField(
+ key: const Key("email"),
+ fieldName: context.strings.profile_settings_email,
+ initialValue: state.user!.email,
+ readOnly: true,
+ controller: cubit.emailTextController,
+ ),
+ const SizedBox(height: 8),
+ IntlPhoneField(
+ key: const Key("phone"),
+ title: context.strings.profile_settings_phone,
+ phoneNumber: cubit.phoneNumber!,
+ countryCode: cubit.countryCode!,
+ controller: cubit.phoneNumberTextController,
+ readOnly: false,
+ errorMessage: phoneNumberErrorMessage,
+ onCountryCodeSelected: (CountryCode countryCode) {
+ cubit.onCountryCodeSelected(countryCode);
+ },
+ onPhoneNumberChanged: (String phoneNumber) {
+ cubit.onPhoneNumberChanged(phoneNumber);
+ },
+ onSubmitted: (_) {
+ // NO OP
+ },
+ ),
+ ],
+ ),
+ ),
+ ],
+ );
+ }
+}
diff --git a/comwell_key_app/lib/presentation/screens/pregistration/pages/prereg_up_sales_catalog_page.dart b/comwell_key_app/lib/presentation/screens/pregistration/pages/prereg_up_sales_catalog_page.dart
new file mode 100644
index 00000000..c7fb67a6
--- /dev/null
+++ b/comwell_key_app/lib/presentation/screens/pregistration/pages/prereg_up_sales_catalog_page.dart
@@ -0,0 +1,125 @@
+import 'package:comwell_key_app/common/components/comwell_app_bar.dart';
+import 'package:comwell_key_app/common/components/comwell_error_widget.dart';
+import 'package:comwell_key_app/common/components/shimmer_loader/up_sales_catalog_shimmer_loader.dart';
+import 'package:comwell_key_app/up_sales/components/catalog/addon_upgrade_catalog.dart';
+import 'package:comwell_key_app/up_sales/components/catalog/room_upgrade_catalog.dart';
+import 'package:comwell_key_app/up_sales/components/catalog/service_catalog.dart';
+import 'package:comwell_key_app/presentation/screens/pregistration/cubit/preregistration_cubit.dart';
+import 'package:comwell_key_app/presentation/screens/pregistration/cubit/preregistration_state.dart';
+import 'package:comwell_key_app/utils/l10n_utils.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter_bloc/flutter_bloc.dart';
+
+class PreregUpSalesCatalogPage extends StatelessWidget {
+ const PreregUpSalesCatalogPage({super.key});
+
+ @override
+ Widget build(BuildContext context) {
+ final theme = Theme.of(context);
+ return BlocBuilder<PreregistrationCubit, PreregistrationState>(
+ builder: (context, state) {
+ final cubit = context.read<PreregistrationCubit>();
+
+ if (state.isLoading) {
+ return Scaffold(
+ appBar: const ComwellAppBar(),
+ backgroundColor: Theme.of(context).colorScheme.surface,
+ body: const UpSalesCatalogShimmerLoader(),
+ );
+ }
+
+ final serviceUpgrades = cubit.state.addOnUpgrades
+ .where((upgrade) => upgrade.isService)
+ .toList();
+ final addonUpgrades = cubit.state.addOnUpgrades
+ .where((upgrade) => upgrade.isService == false)
+ .toList();
+ final selectedRoomUpgrade = cubit.state.selectedRoomUpgrade.isEmpty
+ ? null
+ : cubit.state.availableRoomUpgrades
+ .firstWhere((e) => e.id == cubit.state.selectedRoomUpgrade);
+
+ return SingleChildScrollView(
+ child: Padding(
+ padding: const EdgeInsets.only(
+ top: 24,
+ bottom: 100,
+ ),
+ child: Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ Padding(
+ padding: const EdgeInsets.symmetric(horizontal: 16),
+ child: Text(context.strings.up_sales_catalog_title,
+ style: theme.textTheme.headlineLarge),
+ ),
+ const SizedBox(height: 40),
+ if (serviceUpgrades.isEmpty && addonUpgrades.isEmpty && cubit.state.availableRoomUpgrades.isEmpty) ...[
+ ComwellErrorWidget(
+ title: context.strings.up_sales_catalog_no_up_sales_title,
+ subtitle: context.strings.up_sales_catalog_no_up_sales_subtitle,
+ border: true)
+ ],
+ if (serviceUpgrades.isNotEmpty) ...[
+ Padding(
+ padding: const EdgeInsets.symmetric(horizontal: 16),
+ child: Text(context.strings.services,
+ style: theme.textTheme.headlineMedium),
+ ),
+ const SizedBox(height: 8),
+ ServiceCatalog(
+ booking: cubit.booking,
+ upSales: serviceUpgrades,
+ onServiceSelected: (upgrade, isSelected) {
+ cubit.toggleSelectedUpgrade(upgrade);
+ },
+ onTap: (upgrade) {
+ cubit.toggleSelectedUpgrade(upgrade);
+ },
+ ),
+ ],
+ if (cubit.state.availableRoomUpgrades.isNotEmpty) ...[
+ const SizedBox(height: 24),
+ Padding(
+ padding: const EdgeInsets.symmetric(horizontal: 16),
+ child: Text(context.strings.room_upgrades,
+ style: theme.textTheme.headlineMedium),
+ ),
+ const SizedBox(height: 8),
+ RoomUpgradeCatalog(
+ booking: cubit.booking,
+ availableRoomUpgrades: cubit.state.availableRoomUpgrades,
+ selectedRoomUpgrade: cubit.state.selectedRoomUpgrade,
+ onRoomUpgradeSelected: (upgrade, isSelected) {
+ cubit.toggleSelectedUpgrade(upgrade);
+ },
+ onTap: (upgrade) {
+ cubit.toggleSelectedUpgrade(upgrade);
+ },
+ ),
+ ],
+ if (addonUpgrades.isNotEmpty) ...[
+ const SizedBox(height: 24),
+ Padding(
+ padding: const EdgeInsets.symmetric(horizontal: 16),
+ child: Text(context.strings.other_up_sales,
+ style: theme.textTheme.headlineMedium),
+ ),
+ const SizedBox(height: 8),
+ AddOnUpgradeCatalog(
+ addOnUpgrades: cubit.otherUpgrades,
+ extrasTotalPrice: cubit.extrasTotalPrice,
+ selectedRoomUpgrade: selectedRoomUpgrade?.id ?? '',
+ onAddOnUpgradeSelected: (upgrade, quantity) {
+ cubit.updateAddonUpgradeQuantity(upgrade, quantity);
+ },
+ ),
+ ],
+ const SizedBox(height: 24),
+ ],
+ ),
+ ),
+ );
+ });
+ }
+}
diff --git a/comwell_key_app/lib/presentation/screens/pregistration/prereg_request_model.dart b/comwell_key_app/lib/presentation/screens/pregistration/prereg_request_model.dart
new file mode 100644
index 00000000..087b01a3
--- /dev/null
+++ b/comwell_key_app/lib/presentation/screens/pregistration/prereg_request_model.dart
@@ -0,0 +1,50 @@
+class PreregRequestDto {
+ final String firstName;
+ final String lastName;
+ final String email;
+ final String phoneNumber;
+ final String birthDay;
+ final String address;
+ final String zipCode;
+ final String city;
+ final String country;
+ final String confirmationNumber;
+
+ final String hotelCode;
+ final bool comwellClubTermsOfUseConsentChoice;
+ final bool comwellClubMarketingConsentChoice;
+
+ PreregRequestDto({
+ required this.firstName,
+ required this.lastName,
+ required this.email,
+ required this.phoneNumber,
+ required this.birthDay,
+ required this.address,
+ required this.zipCode,
+ required this.city,
+ required this.country,
+ required this.confirmationNumber,
+ required this.hotelCode,
+ required this.comwellClubTermsOfUseConsentChoice,
+ required this.comwellClubMarketingConsentChoice,
+ });
+
+ Map<String, dynamic> toJson() {
+ return {
+ 'firstName': firstName,
+ 'lastName': lastName,
+ 'email': email,
+ 'phoneNumber': phoneNumber,
+ 'birthDay': birthDay,
+ 'address': address,
+ 'zipCode': zipCode,
+ 'city': city,
+ 'country': country,
+ 'confirmationNumber': confirmationNumber,
+ 'hotelCode': hotelCode,
+ 'comwellClubTermsOfUseConsentChoice': comwellClubTermsOfUseConsentChoice,
+ 'comwellClubMarketingConsentChoice': comwellClubMarketingConsentChoice,
+ };
+ }
+}
diff --git a/comwell_key_app/lib/presentation/screens/pregistration/preregistration_flow.dart b/comwell_key_app/lib/presentation/screens/pregistration/preregistration_flow.dart
new file mode 100644
index 00000000..b0bdd98b
--- /dev/null
+++ b/comwell_key_app/lib/presentation/screens/pregistration/preregistration_flow.dart
@@ -0,0 +1,113 @@
+import 'package:comwell_key_app/common/components/comwell_app_bar.dart';
+
+import 'package:comwell_key_app/presentation/screens/pregistration/cubit/preregistration_state.dart';
+import 'package:comwell_key_app/presentation/screens/pregistration/cubit/preregistration_cubit.dart';
+import 'package:comwell_key_app/presentation/screens/pregistration/utils/utils.dart';
+import 'package:comwell_key_app/themes/light_theme.dart';
+import 'package:comwell_key_app/utils/locator.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter_bloc/flutter_bloc.dart';
+import 'package:go_router/go_router.dart';
+import 'package:payment_plugin/domain/repositories/adyen_repository.dart';
+import 'package:payment_plugin/presentation/app/bloc/payment_cards_cubit.dart';
+import 'package:payment_plugin/presentation/app/bloc/payment_cards_state.dart';
+import 'package:comwell_key_app/common/components/shimmer_loader/prereg_flow_shimmer_loader.dart';
+
+class PreregistrationFlow extends StatefulWidget {
+ const PreregistrationFlow({super.key});
+
+ @override
+ State<PreregistrationFlow> createState() => _PreregistrationFlowState();
+}
+
+class _PreregistrationFlowState extends State<PreregistrationFlow> {
+ @override
+ Widget build(BuildContext context) {
+ return BlocProvider<PaymentCardsCubit>(
+ create: (context) => PaymentCardsCubit(
+ adyenRepository: locator<AdyenRepository>(),
+ onPaymentMethodSelected: (paymentMethod) {
+ context.read<PreregistrationCubit>().onPaymentMethodSelected(paymentMethod);
+ },
+ onPaymentMethodValidationError: () {
+ context.read<PreregistrationCubit>().onPaymentMethodValidationError();
+ },
+ initialSelectedPaymentMethod: context
+ .read<PreregistrationCubit>()
+ .state
+ .selectedPaymentMethod,
+ ),
+ child: BlocBuilder<PaymentCardsCubit, PaymentCardsState>(
+ builder: (context, state) {
+ return BlocBuilder<PreregistrationCubit, PreregistrationState>(
+ builder: (context, state) {
+ final cubit = context.read<PreregistrationCubit>();
+ return Scaffold(
+ backgroundColor: Theme.of(context).colorScheme.surface,
+ appBar: ComwellAppBar(
+ shouldShowProfileButton: false,
+ shouldShowBackButton: true,
+ onBackPressed: () {
+ if (cubit.currentPage == PreregistrationPage.profile) {
+ context.pop();
+ } else {
+ cubit.onBackClicked();
+ }
+ },
+ ),
+ body: Builder(
+ builder: (context) {
+ if (state.isLoading) {
+ return const Center(child: PreregFlowShimmerLoader());
+ }
+
+ return PageView(
+ key: const PageStorageKey("prereg_flow"),
+ physics: const NeverScrollableScrollPhysics(),
+ controller: cubit.pageController,
+ children: PreregistrationPage.getPages(ValueKey(state)).toList(),
+ );
+ },
+ ),
+ bottomNavigationBar: Builder(
+ builder: (context) {
+ if (state.isLoading) return const SizedBox();
+ return Column(
+ // BOTTOM NAVIGATION
+ mainAxisSize: MainAxisSize.min,
+ children: [
+ const Divider(
+ color: Colors.black12,
+ height: 0,
+ ),
+ Row(
+ children: [
+ Expanded(
+ child: Padding(
+ padding: const EdgeInsets.fromLTRB(16.0, 16.0, 16.0, 40.0),
+ child: ElevatedButton(
+ onPressed: () {
+ cubit.onContinueClicked(context);
+ },
+ style: ElevatedButton.styleFrom(foregroundColor: colorBackground),
+ child: Padding(
+ padding: const EdgeInsets.symmetric(vertical: 16.0),
+ child: Text(cubit.buttonText(context)),
+ ),
+ ),
+ ),
+ ),
+ ],
+ ),
+ ],
+ );
+ },
+ ),
+ );
+ },
+ );
+ },
+ ),
+ );
+ }
+}
diff --git a/comwell_key_app/lib/presentation/screens/pregistration/preregistration_route.dart b/comwell_key_app/lib/presentation/screens/pregistration/preregistration_route.dart
new file mode 100644
index 00000000..54b5e38c
--- /dev/null
+++ b/comwell_key_app/lib/presentation/screens/pregistration/preregistration_route.dart
@@ -0,0 +1,18 @@
+import 'package:comwell_key_app/overview/models/booking.dart';
+import 'package:comwell_key_app/presentation/screens/pregistration/cubit/preregistration_cubit.dart';
+import 'package:comwell_key_app/presentation/screens/pregistration/preregistration_flow.dart';
+import 'package:comwell_key_app/routing/app_routes.dart';
+import 'package:flutter_bloc/flutter_bloc.dart';
+import 'package:go_router/go_router.dart';
+
+final preregistrationRoute = GoRoute(
+ path: AppRoutes.preregistration,
+ builder: (context, state) {
+ final extras = state.extra as List<dynamic>;
+ final booking = extras[0] as Booking;
+ return BlocProvider(
+ create: (context) => PreregistrationCubit(booking: booking),
+ child: const PreregistrationFlow(),
+ );
+ },
+);
diff --git a/comwell_key_app/lib/presentation/screens/pregistration/utils/utils.dart b/comwell_key_app/lib/presentation/screens/pregistration/utils/utils.dart
new file mode 100644
index 00000000..738383a0
--- /dev/null
+++ b/comwell_key_app/lib/presentation/screens/pregistration/utils/utils.dart
@@ -0,0 +1,34 @@
+import 'package:comwell_key_app/presentation/screens/pregistration/pages/prereg_address_page.dart';
+import 'package:comwell_key_app/presentation/screens/pregistration/pages/prereg_confirmation_page.dart';
+import 'package:comwell_key_app/presentation/screens/pregistration/pages/prereg_profile_page.dart';
+import 'package:comwell_key_app/presentation/screens/pregistration/pages/prereg_up_sales_catalog_page.dart';
+import 'package:flutter/material.dart';
+
+enum PreregistrationPage {
+ profile,
+ address,
+ //payment,
+ upSales,
+ confirmation;
+
+ static PreregistrationPage fromIndex(int index) {
+ return PreregistrationPage.values[index];
+ }
+
+ static Iterable<Widget> getPages(Key key) {
+ return PreregistrationPage.values.map((page) {
+ switch (page) {
+ case PreregistrationPage.profile:
+ return PreregProfilePage(key: key);
+ case PreregistrationPage.address:
+ return PreregAddressPage(key: key);
+ /* case PreregistrationPage.payment:
+ return const PaymentCardsPage(); */
+ case PreregistrationPage.upSales:
+ return const PreregUpSalesCatalogPage();
+ case PreregistrationPage.confirmation:
+ return PreregConfirmationPage(key: key);
+ }
+ });
+ }
+}
diff --git a/comwell_key_app/lib/routing/app_router.dart b/comwell_key_app/lib/routing/app_router.dart
index 1103c25c..83862395 100644
--- a/comwell_key_app/lib/routing/app_router.dart
+++ b/comwell_key_app/lib/routing/app_router.dart
@@ -6,7 +6,7 @@ import 'package:comwell_key_app/hotel_information/hotel_information_route.dart';
import 'package:comwell_key_app/housekeeping/house_keeping_route.dart';
import 'package:comwell_key_app/my_booking/my_booking_route.dart';
import 'package:comwell_key_app/notifications/notifications_route.dart';
-import 'package:comwell_key_app/pregistration/preregistration_route.dart';
+import 'package:comwell_key_app/presentation/screens/pregistration/preregistration_route.dart';
import 'package:comwell_key_app/presentation/screens/booking_details/booking_details_route.dart';
import 'package:comwell_key_app/presentation/screens/change_password/change_password_route.dart';
import 'package:comwell_key_app/presentation/screens/concierge/concierge_route.dart';
diff --git a/comwell_key_app/lib/services/api.dart b/comwell_key_app/lib/services/api.dart
index 2f55c4be..daba8e5a 100644
--- a/comwell_key_app/lib/services/api.dart
+++ b/comwell_key_app/lib/services/api.dart
@@ -3,7 +3,7 @@ import 'dart:io';
import 'package:comwell_key_app/hotel_information/models/hotel.dart';
import 'package:comwell_key_app/housekeeping/models/housekeeping.dart';
import 'package:comwell_key_app/notifications/models/notification_permission.dart';
-import 'package:comwell_key_app/pregistration/prereg_request_model.dart';
+import 'package:comwell_key_app/presentation/screens/pregistration/prereg_request_model.dart';
import 'package:comwell_key_app/services/http_client.dart';
import 'package:comwell_key_app/services/models/booking_dto.dart';
import 'package:comwell_key_app/services/models/simple_user_dto.dart';
@@ -29,7 +29,13 @@ class Api {
// Get current locale globally
Locale get _currentLocale {
final navigatorKey = locator<GlobalKey<NavigatorState>>();
- return Locale(navigatorKey.currentContext!.strings.localeName);
+ final languageCode = navigatorKey.currentContext!.strings.localeName;
+ final countryCode = switch (languageCode) {
+ 'en' => 'US',
+ 'da' => 'DK',
+ _ => 'DK',
+ };
+ return Locale(languageCode, countryCode);
}
Future<Response<dynamic>> logout() async {
diff --git a/comwell_key_app/lib/utils/locator.dart b/comwell_key_app/lib/utils/locator.dart
index a88bff99..c3a43fe5 100644
--- a/comwell_key_app/lib/utils/locator.dart
+++ b/comwell_key_app/lib/utils/locator.dart
@@ -14,7 +14,7 @@ import 'package:comwell_key_app/key/repository/key_repository.dart';
import 'package:comwell_key_app/my_booking/my_booking_repository.dart';
import 'package:comwell_key_app/notifications/notifications_repository.dart';
import 'package:comwell_key_app/overview/repository/overview_repository.dart';
-import 'package:comwell_key_app/pregistration/pregistration_repository.dart';
+import 'package:comwell_key_app/domain/repositories/pregistration_repository.dart';
import 'package:comwell_key_app/profile/profile_repository.dart';
import 'package:comwell_key_app/profile_settings/repostiory/profile_settings_repository.dart';
import 'package:comwell_key_app/services/api.dart';
diff --git a/payment_plugin/lib/_generated/data/remote/api/api_client.g.dart b/payment_plugin/lib/_generated/data/remote/api/api_client.g.dart
index fbce2f27..c18c6685 100644
--- a/payment_plugin/lib/_generated/data/remote/api/api_client.g.dart
+++ b/payment_plugin/lib/_generated/data/remote/api/api_client.g.dart
@@ -49,9 +49,9 @@ class _ApiClient implements ApiClient {
@override
Future<dynamic> createAdyenSession(String data) async {
final _extra = <String, dynamic>{};
- final queryParameters = <String, dynamic>{r'data': data};
+ final queryParameters = <String, dynamic>{};
final _headers = <String, dynamic>{};
- const Map<String, dynamic>? _data = null;
+ final _data = data;
final _options = _setStreamType<dynamic>(
Options(method: 'POST', headers: _headers, extra: _extra)
.compose(
diff --git a/payment_plugin/lib/data/remote/api/api_client.dart b/payment_plugin/lib/data/remote/api/api_client.dart
index 2c835e4e..fff19858 100644
--- a/payment_plugin/lib/data/remote/api/api_client.dart
+++ b/payment_plugin/lib/data/remote/api/api_client.dart
@@ -16,7 +16,7 @@ abstract class ApiClient {
@POST("/Payment/v1/CreateAdyenSessionForBooking")
Future<dynamic> createAdyenSession(
- @Query("data") String data,
+ @Body() String data,
);
@POST("/Payment/v1/CreatePaymentSessionForAddingCards")
diff --git a/payment_plugin/lib/presentation/app/bloc/payment_cubit.dart b/payment_plugin/lib/presentation/app/bloc/payment_cubit.dart
index f2e96b82..d9ef70fa 100644
--- a/payment_plugin/lib/presentation/app/bloc/payment_cubit.dart
+++ b/payment_plugin/lib/presentation/app/bloc/payment_cubit.dart
@@ -13,7 +13,6 @@ class PaymentCubit extends Cubit<PaymentProcessingState> {
Future<void> createSession(int price, String confirmationId,
bool applyClubPoints, String hotelCode) async {
try {
-
emit(PaymentProcessingStateProcessing());
final paymentConfigurations = await adyenRepository
diff --git a/payment_plugin/lib/presentation/screens/payment_processing_page.dart b/payment_plugin/lib/presentation/screens/payment_processing_page.dart
index 04fb5dc6..99656f4f 100644
--- a/payment_plugin/lib/presentation/screens/payment_processing_page.dart
+++ b/payment_plugin/lib/presentation/screens/payment_processing_page.dart
@@ -45,11 +45,7 @@ class _PaymentProcessingPageState extends State<PaymentProcessingPage>
}
void playError() async {
- loadingComposition?.playBetween(
- animationController,
- "error",
- repeat: true,
- );
+ loadingComposition?.playBetween(animationController, "error", repeat: true);
await Future<void>.delayed(const Duration(seconds: 1));
if (mounted) Navigator.of(context).pop();
}
@@ -99,25 +95,25 @@ class _PaymentProcessingPageState extends State<PaymentProcessingPage>
showAdyenModal(context);
}
},
- child: Lottie.asset(
- 'assets/animations/load_animation.json',
- controller: animationController,
- onLoaded: (composition) {
- if (loadingComposition == null) {
- loadingComposition = composition;
- animationController.duration = composition.duration;
- switch (cubit.state) {
- case PaymentProcessingStateConfirmed _:
- playSuccess();
- case PaymentProcessingStateError _:
- playError();
- default:
- playLoading();
+ child: Lottie.asset(
+ 'assets/animations/load_animation.json',
+ controller: animationController,
+ onLoaded: (composition) {
+ if (loadingComposition == null) {
+ loadingComposition = composition;
+ animationController.duration = composition.duration;
+ switch (cubit.state) {
+ case PaymentProcessingStateConfirmed _:
+ playSuccess();
+ case PaymentProcessingStateError _:
+ playError();
+ default:
+ playLoading();
+ }
}
- }
- },
- fit: BoxFit.cover,
- width: 64,
+ },
+ fit: BoxFit.cover,
+ width: 64,
height: 64,
),
),