6177214e-ce7c-49e3-99de-ff9721b26f63 — Commit 7a53e0d5
Changed files
comwell_key_app/.fvmrc | 3 + comwell_key_app/.gitignore | 5 +- comwell_key_app/build.yaml | 7 ++ .../.generated/services/adyen/adyen_amount.g.dart | 18 ++++ .../services/adyen/adyen_line_item.g.dart | 33 +++++++ .../services/adyen/payment_method.g.dart | 19 ++++ .../services/adyen/payment_methods.g.dart | 21 +++++ .../services/adyen/payment_request_data.g.dart | 61 ++++++++++++ .../services/adyen/stored_payment_method.g.dart | 40 ++++++++ .../lib/common/components/payment_card_image.dart | 22 +++++ comwell_key_app/lib/common/const.dart | 7 +- .../lib/overview/models/payment_details.dart | 25 ++--- .../past_cancelled_booking_detail_page.dart | 17 +--- .../pregistration/bloc/preregistration_cubit.dart | 94 ++++++++++++++++-- .../pregistration/bloc/preregistration_state.dart | 52 +++++----- .../lib/pregistration/components/add_card.dart | 86 +++++++++++++++++ .../lib/pregistration/components/card_item.dart | 55 +++++++++++ .../pregistration/components/information_card.dart | 38 ++++++++ .../pages/prereg_confirmation_page.dart | 7 +- .../pregistration/pages/prereg_payment_page.dart | 43 +++++++-- .../pregistration/pregistration_repository.dart | 83 ++++++++++++++++ .../lib/pregistration/preregistration_flow.dart | 30 +++--- .../lib/pregistration/widgets/add_card.dart | 40 -------- .../lib/pregistration/widgets/card_item.dart | 39 -------- .../pregistration/widgets/information_card.dart | 38 -------- .../lib/profile_settings/model/user.dart | 6 ++ .../lib/services/adyen/adyen_amount.dart | 18 ++++ .../lib/services/adyen/adyen_line_item.dart | 33 +++++++ comwell_key_app/lib/services/adyen/extensions.dart | 55 +++++++++++ .../lib/services/adyen/payment_event_handler.dart | 80 ++++++++++++++++ .../lib/services/adyen/payment_method.dart | 16 ++++ .../lib/services/adyen/payment_methods.dart | 15 +++ .../lib/services/adyen/payment_request_data.dart | 48 ++++++++++ .../lib/services/adyen/stored_payment_method.dart | 36 +++++++ comwell_key_app/lib/services/api.dart | 14 +++ comwell_key_app/lib/utils/json.dart | 1 + comwell_key_app/lib/utils/locator.dart | 22 +++-- comwell_key_app/lib/utils/payment_utils.dart | 25 +++++ comwell_key_app/pubspec.yaml | 24 +---- .../test/home_test/home_bloc_test.mocks.dart | 105 +++++++++++++++++++-- .../profile_settings_cubit_test.dart | 1 + .../android/.gradle/config.properties | 2 + .../libs/mobilekeys-android-sdk-debug-8.1.0.aar | Bin 4333160 -> 0 bytes .../libs/mobilekeys-android-sdk-debug-8.1.2.aar | Bin 0 -> 4188961 bytes .../libs/mobilekeys-android-sdk-release-8.1.0.aar | Bin 4394625 -> 0 bytes .../libs/mobilekeys-android-sdk-release-8.1.2.aar | Bin 0 -> 5456329 bytes mobilekeys_sdk_plugin/android/local.properties | 8 ++ 47 files changed, 1161 insertions(+), 231 deletions(-)
Diff
diff --git a/comwell_key_app/.fvmrc b/comwell_key_app/.fvmrc
new file mode 100644
index 00000000..ff263c64
--- /dev/null
+++ b/comwell_key_app/.fvmrc
@@ -0,0 +1,3 @@
+{
+ "flutter": "3.24.4"
+}
\ No newline at end of file
diff --git a/comwell_key_app/.gitignore b/comwell_key_app/.gitignore
index 375cc606..71127197 100644
--- a/comwell_key_app/.gitignore
+++ b/comwell_key_app/.gitignore
@@ -45,4 +45,7 @@ app.*.map.json
/android/app/release
# Project related
-pubspec.lock
\ No newline at end of file
+pubspec.lock
+
+# FVM Version Cache
+.fvm/
\ No newline at end of file
diff --git a/comwell_key_app/build.yaml b/comwell_key_app/build.yaml
new file mode 100644
index 00000000..b79ba129
--- /dev/null
+++ b/comwell_key_app/build.yaml
@@ -0,0 +1,7 @@
+targets:
+ $default:
+ builders:
+ source_gen:combining_builder:
+ options:
+ build_extensions:
+ '^lib/{{}}.dart': 'lib/.generated/{{}}.g.dart'
\ No newline at end of file
diff --git a/comwell_key_app/lib/.generated/services/adyen/adyen_amount.g.dart b/comwell_key_app/lib/.generated/services/adyen/adyen_amount.g.dart
new file mode 100644
index 00000000..f69bab35
--- /dev/null
+++ b/comwell_key_app/lib/.generated/services/adyen/adyen_amount.g.dart
@@ -0,0 +1,18 @@
+// GENERATED CODE - DO NOT MODIFY BY HAND
+
+part of '../../../services/adyen/adyen_amount.dart';
+
+// **************************************************************************
+// JsonSerializableGenerator
+// **************************************************************************
+
+AdyenAmount _$AdyenAmountFromJson(Map<String, dynamic> json) => AdyenAmount(
+ json['currency'] as String,
+ (json['value'] as num).toInt(),
+ );
+
+Map<String, dynamic> _$AdyenAmountToJson(AdyenAmount instance) =>
+ <String, dynamic>{
+ 'currency': instance.currency,
+ 'value': instance.value,
+ };
diff --git a/comwell_key_app/lib/.generated/services/adyen/adyen_line_item.g.dart b/comwell_key_app/lib/.generated/services/adyen/adyen_line_item.g.dart
new file mode 100644
index 00000000..594dc84c
--- /dev/null
+++ b/comwell_key_app/lib/.generated/services/adyen/adyen_line_item.g.dart
@@ -0,0 +1,33 @@
+// GENERATED CODE - DO NOT MODIFY BY HAND
+
+part of '../../../services/adyen/adyen_line_item.dart';
+
+// **************************************************************************
+// JsonSerializableGenerator
+// **************************************************************************
+
+AdyenLineItem _$AdyenLineItemFromJson(Map<String, dynamic> json) =>
+ AdyenLineItem(
+ quantity: (json['quantity'] as num?)?.toInt(),
+ amountExcludingTax: (json['amountExcludingTax'] as num?)?.toInt(),
+ taxPercentage: (json['taxPercentage'] as num?)?.toInt(),
+ description: json['description'] as String?,
+ id: json['id'] as String?,
+ taxAmount: (json['taxAmount'] as num?)?.toInt(),
+ amountIncludingTax: (json['amountIncludingTax'] as num?)?.toInt(),
+ productUrl: json['productUrl'] as String?,
+ imageUrl: json['imageUrl'] as String?,
+ );
+
+Map<String, dynamic> _$AdyenLineItemToJson(AdyenLineItem instance) =>
+ <String, dynamic>{
+ 'quantity': instance.quantity,
+ 'amountExcludingTax': instance.amountExcludingTax,
+ 'taxPercentage': instance.taxPercentage,
+ 'description': instance.description,
+ 'id': instance.id,
+ 'taxAmount': instance.taxAmount,
+ 'amountIncludingTax': instance.amountIncludingTax,
+ 'productUrl': instance.productUrl,
+ 'imageUrl': instance.imageUrl,
+ };
diff --git a/comwell_key_app/lib/.generated/services/adyen/payment_method.g.dart b/comwell_key_app/lib/.generated/services/adyen/payment_method.g.dart
new file mode 100644
index 00000000..e7037891
--- /dev/null
+++ b/comwell_key_app/lib/.generated/services/adyen/payment_method.g.dart
@@ -0,0 +1,19 @@
+// GENERATED CODE - DO NOT MODIFY BY HAND
+
+part of '../../../services/adyen/payment_method.dart';
+
+// **************************************************************************
+// JsonSerializableGenerator
+// **************************************************************************
+
+PaymentMethod _$PaymentMethodFromJson(Map<String, dynamic> json) =>
+ PaymentMethod(
+ json['name'] as String,
+ json['type'] as String,
+ );
+
+Map<String, dynamic> _$PaymentMethodToJson(PaymentMethod instance) =>
+ <String, dynamic>{
+ 'name': instance.name,
+ 'type': instance.type,
+ };
diff --git a/comwell_key_app/lib/.generated/services/adyen/payment_methods.g.dart b/comwell_key_app/lib/.generated/services/adyen/payment_methods.g.dart
new file mode 100644
index 00000000..bb18e944
--- /dev/null
+++ b/comwell_key_app/lib/.generated/services/adyen/payment_methods.g.dart
@@ -0,0 +1,21 @@
+// GENERATED CODE - DO NOT MODIFY BY HAND
+
+part of '../../../services/adyen/payment_methods.dart';
+
+// **************************************************************************
+// JsonSerializableGenerator
+// **************************************************************************
+
+PaymentMethods _$PaymentMethodsFromJson(Map<String, dynamic> json) =>
+ PaymentMethods(
+ (json['paymentMethods'] as List<dynamic>)
+ .map((e) => PaymentMethod.fromJson(e as Map<String, dynamic>)),
+ (json['storedPaymentMethods'] as List<dynamic>)
+ .map((e) => StoredPaymentMethod.fromJson(e as Map<String, dynamic>)),
+ );
+
+Map<String, dynamic> _$PaymentMethodsToJson(PaymentMethods instance) =>
+ <String, dynamic>{
+ 'paymentMethods': instance.paymentMethods.toList(),
+ 'storedPaymentMethods': instance.storedPaymentMethods.toList(),
+ };
diff --git a/comwell_key_app/lib/.generated/services/adyen/payment_request_data.g.dart b/comwell_key_app/lib/.generated/services/adyen/payment_request_data.g.dart
new file mode 100644
index 00000000..e1f060d5
--- /dev/null
+++ b/comwell_key_app/lib/.generated/services/adyen/payment_request_data.g.dart
@@ -0,0 +1,61 @@
+// GENERATED CODE - DO NOT MODIFY BY HAND
+
+part of '../../../services/adyen/payment_request_data.dart';
+
+// **************************************************************************
+// JsonSerializableGenerator
+// **************************************************************************
+
+PaymentsRequestData _$PaymentsRequestDataFromJson(Map<String, dynamic> json) =>
+ PaymentsRequestData(
+ merchantAccount: json['merchantAccount'] as String,
+ amount: AdyenAmount.fromJson(json['amount'] as Map<String, dynamic>),
+ reference: json['reference'] as String,
+ shopperReference: json['shopperReference'] as String?,
+ countryCode: json['countryCode'] as String?,
+ returnUrl: json['returnUrl'] as String?,
+ additionalData: json['additionalData'] as Map<String, dynamic>?,
+ shopperIP: json['shopperIP'] as String?,
+ channel: json['channel'] as String?,
+ lineItems: (json['lineItems'] as List<dynamic>?)
+ ?.map((e) => AdyenLineItem.fromJson(e as Map<String, dynamic>))
+ .toList(),
+ shopperEmail: json['shopperEmail'] as String?,
+ threeDS2RequestData: json['threeDS2RequestData'] as Map<String, dynamic>?,
+ recurringProcessingModel: $enumDecodeNullable(
+ _$RecurringProcessingModelEnumMap, json['recurringProcessingModel']),
+ shopperInteraction: json['shopperInteraction'] as String?,
+ authenticationData: json['authenticationData'] as Map<String, dynamic>?,
+ );
+
+Map<String, dynamic> _$PaymentsRequestDataToJson(
+ PaymentsRequestData instance) =>
+ <String, dynamic>{
+ 'merchantAccount': instance.merchantAccount,
+ 'amount': instance.amount,
+ 'reference': instance.reference,
+ if (instance.shopperReference case final value?)
+ 'shopperReference': value,
+ if (instance.countryCode case final value?) 'countryCode': value,
+ if (instance.returnUrl case final value?) 'returnUrl': value,
+ if (instance.additionalData case final value?) 'additionalData': value,
+ if (instance.shopperIP case final value?) 'shopperIP': value,
+ if (instance.channel case final value?) 'channel': value,
+ if (instance.lineItems case final value?) 'lineItems': value,
+ if (instance.shopperEmail case final value?) 'shopperEmail': value,
+ if (instance.threeDS2RequestData case final value?)
+ 'threeDS2RequestData': value,
+ if (_$RecurringProcessingModelEnumMap[instance.recurringProcessingModel]
+ case final value?)
+ 'recurringProcessingModel': value,
+ if (instance.shopperInteraction case final value?)
+ 'shopperInteraction': value,
+ if (instance.authenticationData case final value?)
+ 'authenticationData': value,
+ };
+
+const _$RecurringProcessingModelEnumMap = {
+ RecurringProcessingModel.subscription: 'subscription',
+ RecurringProcessingModel.cardOnFile: 'cardOnFile',
+ RecurringProcessingModel.unscheduledCardOnFile: 'unscheduledCardOnFile',
+};
diff --git a/comwell_key_app/lib/.generated/services/adyen/stored_payment_method.g.dart b/comwell_key_app/lib/.generated/services/adyen/stored_payment_method.g.dart
new file mode 100644
index 00000000..254bb574
--- /dev/null
+++ b/comwell_key_app/lib/.generated/services/adyen/stored_payment_method.g.dart
@@ -0,0 +1,40 @@
+// GENERATED CODE - DO NOT MODIFY BY HAND
+
+part of '../../../services/adyen/stored_payment_method.dart';
+
+// **************************************************************************
+// JsonSerializableGenerator
+// **************************************************************************
+
+StoredPaymentMethod _$StoredPaymentMethodFromJson(Map<String, dynamic> json) =>
+ StoredPaymentMethod(
+ brand: json['brand'] as String,
+ expiryMonth: json['expiryMonth'] as String,
+ expiryYear: json['expiryYear'] as String,
+ holderName: json['holderName'] as String,
+ id: json['id'] as String,
+ lastFour: json['lastFour'] as String,
+ name: json['name'] as String,
+ shopperEmail: json['shopperEmail'] as String,
+ supportedRecurringProcessingModels:
+ (json['supportedRecurringProcessingModels'] as List<dynamic>)
+ .map((e) => e as String)
+ .toList(),
+ type: json['type'] as String,
+ );
+
+Map<String, dynamic> _$StoredPaymentMethodToJson(
+ StoredPaymentMethod instance) =>
+ <String, dynamic>{
+ 'brand': instance.brand,
+ 'expiryMonth': instance.expiryMonth,
+ 'expiryYear': instance.expiryYear,
+ 'holderName': instance.holderName,
+ 'id': instance.id,
+ 'lastFour': instance.lastFour,
+ 'name': instance.name,
+ 'shopperEmail': instance.shopperEmail,
+ 'supportedRecurringProcessingModels':
+ instance.supportedRecurringProcessingModels,
+ 'type': instance.type,
+ };
diff --git a/comwell_key_app/lib/common/components/payment_card_image.dart b/comwell_key_app/lib/common/components/payment_card_image.dart
new file mode 100644
index 00000000..537c67ce
--- /dev/null
+++ b/comwell_key_app/lib/common/components/payment_card_image.dart
@@ -0,0 +1,22 @@
+import 'package:flutter/material.dart';
+import 'package:flutter_svg/svg.dart';
+
+import '../../overview/models/payment_details.dart';
+
+class PaymentCardImage extends StatelessWidget {
+ final CardType cardType;
+
+ const PaymentCardImage({super.key, required this.cardType});
+
+ @override
+ Widget build(BuildContext context) {
+ switch (cardType) {
+ case CardType.visa:
+ return SvgPicture.asset('assets/icons/visa.svg');
+ case CardType.mastercard:
+ return SvgPicture.asset('assets/icons/mastercard.svg');
+ case CardType.maestro:
+ return SvgPicture.asset('assets/icons/maestro.svg');
+ }
+ }
+}
diff --git a/comwell_key_app/lib/common/const.dart b/comwell_key_app/lib/common/const.dart
index 800dde18..5f1fb949 100644
--- a/comwell_key_app/lib/common/const.dart
+++ b/comwell_key_app/lib/common/const.dart
@@ -1,4 +1,9 @@
const accessToken = 'access_token';
const refreshToken = 'refresh_token';
const isEndpointSetup = 'isEndpointSetup';
-const hasKey = 'hasKey';
\ No newline at end of file
+const hasKey = 'hasKey';
+
+// Adyen
+class AdyenConstants {
+ static const merchantAccount = "ComwellHotelsECOM";
+}
diff --git a/comwell_key_app/lib/overview/models/payment_details.dart b/comwell_key_app/lib/overview/models/payment_details.dart
index bcdad785..7bcdc92a 100644
--- a/comwell_key_app/lib/overview/models/payment_details.dart
+++ b/comwell_key_app/lib/overview/models/payment_details.dart
@@ -23,7 +23,7 @@ class PaymentDetails extends Equatable {
cardHolder: json['cardHolder'] as String,
expiryDate: json['expiryDate'] as String,
cvc: json['cvc'] as String,
- cardType: _parseCardType(json['cardType'] as String),
+ cardType: CardType.fromString(json['cardType'] as String),
cardName: json['cardName'] as String,
);
}
@@ -38,8 +38,18 @@ class PaymentDetails extends Equatable {
};
}
- static CardType _parseCardType(String type) {
- switch (type) {
+
+ @override
+ List<Object?> get props => [cardNumber, cardHolder, expiryDate, cvc, cardType, cardName];
+}
+
+enum CardType {
+ visa,
+ mastercard,
+ maestro;
+
+ static CardType fromString(String type) {
+ switch (type.toLowerCase()) {
case 'visa':
return CardType.visa;
case 'mastercard':
@@ -50,13 +60,4 @@ class PaymentDetails extends Equatable {
throw Exception('Unknown card type: $type');
}
}
-
- @override
- List<Object?> get props => [cardNumber, cardHolder, expiryDate, cvc, cardType, cardName];
-}
-
-enum CardType {
- visa,
- mastercard,
- maestro,
}
diff --git a/comwell_key_app/lib/overview/past_cancelled_booking_detail_page.dart b/comwell_key_app/lib/overview/past_cancelled_booking_detail_page.dart
index 49774fbf..a0f8079c 100644
--- a/comwell_key_app/lib/overview/past_cancelled_booking_detail_page.dart
+++ b/comwell_key_app/lib/overview/past_cancelled_booking_detail_page.dart
@@ -1,4 +1,5 @@
import 'package:comwell_key_app/common/components/comwell_app_bar.dart';
+import 'package:comwell_key_app/common/components/payment_card_image.dart';
import 'package:comwell_key_app/overview/models/booking.dart';
import 'package:comwell_key_app/overview/models/payment_details.dart';
import 'package:comwell_key_app/themes/light_theme.dart';
@@ -142,7 +143,8 @@ class PastCancelledBookingDetailPage extends StatelessWidget {
? Text('booking_annulled'.tr(),
style: theme.textTheme.headlineSmall
?.copyWith(color: Colors.red))
- : bookingCardImage(booking.paymentDetails.cardType),
+ : PaymentCardImage(
+ cardType: booking.paymentDetails.cardType),
],
)
],
@@ -175,17 +177,4 @@ class PastCancelledBookingDetailPage extends StatelessWidget {
),
);
}
-
- Widget bookingCardImage(CardType cardType) {
- switch (cardType) {
- case CardType.visa:
- return SvgPicture.asset('assets/icons/visa.svg');
- case CardType.mastercard:
- return SvgPicture.asset('assets/icons/mastercard.svg');
- case CardType.maestro:
- return SvgPicture.asset('assets/icons/maestro.svg');
- default:
- return SvgPicture.asset('assets/icons/visa.svg');
- }
- }
}
diff --git a/comwell_key_app/lib/pregistration/bloc/preregistration_cubit.dart b/comwell_key_app/lib/pregistration/bloc/preregistration_cubit.dart
index 8b4d8591..4f80baf7 100644
--- a/comwell_key_app/lib/pregistration/bloc/preregistration_cubit.dart
+++ b/comwell_key_app/lib/pregistration/bloc/preregistration_cubit.dart
@@ -1,6 +1,9 @@
+import 'package:adyen_checkout/adyen_checkout.dart';
import 'package:bloc/bloc.dart';
import 'package:comwell_key_app/pregistration/bloc/preregistration_state.dart';
+import 'package:comwell_key_app/pregistration/pregistration_repository.dart';
import 'package:comwell_key_app/pregistration/preregistration_flow.dart';
+import 'package:comwell_key_app/services/adyen/stored_payment_method.dart';
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/cupertino.dart';
@@ -9,6 +12,8 @@ import '../../utils/locator.dart';
class PreregistrationCubit extends Cubit<PreregistrationState> {
final _profileSettingsRepository = locator<ProfileSettingsRepository>();
+ final _preregistrationRepository = locator<PreregistrationRepository>();
+
final pageController = PageController();
final addressTextController = TextEditingController();
final postalCodeTextController = TextEditingController();
@@ -19,18 +24,21 @@ class PreregistrationCubit extends Cubit<PreregistrationState> {
PreregistrationPage.fromIndex(pageController.page?.toInt() ?? 0);
bool _isAnimating = false;
- PreregistrationCubit() : super(const PreregistrationState.initial());
+ PreregistrationCubit() : super(const PreregistrationState(loading: false));
void init() async {
emit(state.copyWith(loading: true, error: null));
try {
final user = await _profileSettingsRepository.fetchProfileSettings();
+ final paymentMethods =
+ await _preregistrationRepository.getPaymentMethods();
if (user != null) {
addressTextController.text = user.address.street;
postalCodeTextController.text = user.address.zipCode;
cityTextController.text = user.address.city;
countryTextController.text = user.address.country;
- emit(state.copyWith(loading: false, user: user));
+ emit(state.copyWith(
+ loading: false, user: user, storedPaymentMethods: paymentMethods));
} else {
emit(state.copyWith(
loading: false, error: Exception("Der skete en fejl")));
@@ -40,6 +48,8 @@ class PreregistrationCubit extends Cubit<PreregistrationState> {
}
}
+ void onAddCardClicked() {}
+
void onInformationContinueClicked() {
if (isAddressValid && isPostalCodeValid && isCityValid && isCountryValid) {
_navigateNextPage();
@@ -50,22 +60,20 @@ class PreregistrationCubit extends Cubit<PreregistrationState> {
void onContinueClicked() {
if (_isAnimating) return;
- String textStringId = "generic_continue";
switch (currentPage) {
case PreregistrationPage.information:
onInformationContinueClicked();
+ break;
case PreregistrationPage.paymentMethod:
- textStringId = "generic_confirm";
onPaymentMethodsContinueClicked();
+ break;
case PreregistrationPage.confirmation:
_onConfirmPressed();
break;
}
- emit(state.copyWith(buttonTextStringId: textStringId));
}
void onPaymentMethodsContinueClicked() {
- // TODO: Check if payment method is selected and valid
_navigateNextPage();
}
@@ -92,6 +100,10 @@ class PreregistrationCubit extends Cubit<PreregistrationState> {
// Not implemented
}
+ void onSelectCard(StoredPaymentMethod paymentMethod) {
+ emit(state.copyWith(selectedPaymentMethod: paymentMethod));
+ }
+
void onBackClicked() {
if (_isAnimating) return;
final hasPage = pageController.page != null;
@@ -106,6 +118,7 @@ class PreregistrationCubit extends Cubit<PreregistrationState> {
await pageController.animateToPage(page.index,
duration: const Duration(milliseconds: 500),
curve: Curves.fastOutSlowIn);
+ emit(state.copyWith(forceUpdate: true));
_isAnimating = false;
}
@@ -115,6 +128,7 @@ class PreregistrationCubit extends Cubit<PreregistrationState> {
await pageController.nextPage(
duration: const Duration(milliseconds: 500),
curve: Curves.fastOutSlowIn);
+ emit(state.copyWith(forceUpdate: true));
_isAnimating = false;
}
@@ -124,6 +138,7 @@ class PreregistrationCubit extends Cubit<PreregistrationState> {
await pageController.previousPage(
duration: const Duration(milliseconds: 500),
curve: Curves.fastOutSlowIn);
+ emit(state.copyWith(forceUpdate: true));
_isAnimating = false;
}
@@ -146,4 +161,71 @@ class PreregistrationCubit extends Cubit<PreregistrationState> {
bool get isCityValid => cityTextController.text.isNotEmpty;
bool get isCountryValid => countryTextController.text.isNotEmpty;
+
+ bool get canContinue {
+ int page = pageController.page?.ceil() ?? 0;
+ final preregPage = PreregistrationPage.fromIndex(page);
+ switch (preregPage) {
+ case PreregistrationPage.information:
+ return isAddressValid &&
+ isPostalCodeValid &&
+ isCityValid &&
+ isCityValid;
+ case PreregistrationPage.paymentMethod:
+ return state.termsAndConditionsAccepted &&
+ state.selectedPaymentMethod != null;
+ case PreregistrationPage.confirmation:
+ return true;
+ }
+ }
+
+ String get buttonText {
+ int page = pageController.page?.ceil() ?? 0;
+ final preregPage = PreregistrationPage.fromIndex(page);
+ switch (preregPage) {
+ case PreregistrationPage.information:
+ case PreregistrationPage.paymentMethod:
+ return "generic_continue".tr();
+ case PreregistrationPage.confirmation:
+ return "generic_confirm".tr();
+ }
+ }
+
+ void onTermsAndConditionsToggled(bool toggle) {
+ emit(state.copyWith(termsAndConditionsAccepted: toggle));
+ }
+
+ Checkout advancedCheckout() {
+ return AdvancedCheckout(
+ onSubmit: _preregistrationRepository.onSubmit,
+ onAdditionalDetails: _preregistrationRepository.onAdditionalDetails,
+ );
+ }
+
+ Future<void> onPaymentResult(PaymentResult result) async {
+ switch (result) {
+ case PaymentAdvancedFinished():
+ print("Payment advanced finished");
+ break;
+ case PaymentSessionFinished():
+ print("Payment session finished");
+ break;
+ case PaymentCancelledByUser():
+ print("Session cancelled");
+ break;
+ case PaymentError():
+ print("Session error ${result.reason}");
+ break;
+ }
+ }
+
+ void fetchPaymentMethods() async {
+ emit(state.copyWith(loading: true, error: null));
+ try {
+ final paymentMethods = await _preregistrationRepository.getPaymentMethods();
+ emit(state.copyWith(loading: false, storedPaymentMethods: paymentMethods));
+ } on Exception catch (e) {
+ emit(state.copyWith(error: e));
+ }
+ }
}
diff --git a/comwell_key_app/lib/pregistration/bloc/preregistration_state.dart b/comwell_key_app/lib/pregistration/bloc/preregistration_state.dart
index 3b372bfb..f2fd1b1a 100644
--- a/comwell_key_app/lib/pregistration/bloc/preregistration_state.dart
+++ b/comwell_key_app/lib/pregistration/bloc/preregistration_state.dart
@@ -1,32 +1,32 @@
-import 'package:easy_localization/easy_localization.dart';
+import 'package:comwell_key_app/services/adyen/payment_method.dart';
+import 'package:comwell_key_app/services/adyen/stored_payment_method.dart';
import 'package:equatable/equatable.dart';
import '../../profile_settings/model/user.dart';
class PreregistrationState extends Equatable {
+ final bool forceUpdate;
final bool loading;
final User? user;
final Exception? error;
final bool missingInformation;
- final String buttonTextStringId;
final int numOfExtras;
final int extrasTotalPrice;
- final String paymentMethodName;
- final String paymentMethodLastFourDigits;
-
- String get buttonTextLocalized => buttonTextStringId.tr();
-
- const PreregistrationState.initial()
- : this(loading: true, missingInformation: false);
+ final Iterable<StoredPaymentMethod> storedPaymentMethods;
+ final Iterable<PaymentMethod> availablePaymentMethods;
+ final StoredPaymentMethod? selectedPaymentMethod;
+ final bool termsAndConditionsAccepted;
const PreregistrationState({
required this.loading,
- required this.missingInformation,
- this.buttonTextStringId = "generic_continue",
+ this.missingInformation = false,
this.numOfExtras = 0,
this.extrasTotalPrice = 0,
- this.paymentMethodName = "Name Name",
- this.paymentMethodLastFourDigits = "1234",
+ this.storedPaymentMethods = const [],
+ this.selectedPaymentMethod,
+ this.termsAndConditionsAccepted = false,
+ this.availablePaymentMethods = const [],
+ this.forceUpdate = false,
this.user,
this.error,
});
@@ -37,11 +37,13 @@ class PreregistrationState extends Equatable {
user,
error,
missingInformation,
- buttonTextStringId,
numOfExtras,
extrasTotalPrice,
- paymentMethodName,
- paymentMethodLastFourDigits
+ selectedPaymentMethod,
+ storedPaymentMethods,
+ termsAndConditionsAccepted,
+ forceUpdate,
+ availablePaymentMethods
];
PreregistrationState copyWith({
@@ -54,18 +56,26 @@ class PreregistrationState extends Equatable {
String? paymentMethodName,
String? paymentMethodLastFourDigits,
String? buttonTextStringId,
+ bool? termsAndConditionsAccepted,
+ Iterable<PaymentMethod>? availablePaymentMethods,
+ Iterable<StoredPaymentMethod>? storedPaymentMethods,
+ StoredPaymentMethod? selectedPaymentMethod,
+ bool forceUpdate = false,
}) {
return PreregistrationState(
+ forceUpdate: forceUpdate ? !this.forceUpdate : this.forceUpdate,
loading: loading ?? this.loading,
missingInformation: missingInformation ?? this.missingInformation,
user: user ?? this.user,
- buttonTextStringId: buttonTextStringId ?? this.buttonTextStringId,
numOfExtras: numOfExtras ?? this.numOfExtras,
+ storedPaymentMethods: storedPaymentMethods ?? this.storedPaymentMethods,
+ availablePaymentMethods:
+ availablePaymentMethods ?? this.availablePaymentMethods,
+ termsAndConditionsAccepted:
+ termsAndConditionsAccepted ?? this.termsAndConditionsAccepted,
+ selectedPaymentMethod:
+ selectedPaymentMethod ?? this.selectedPaymentMethod,
extrasTotalPrice: extrasTotalPrice ?? this.extrasTotalPrice,
- paymentMethodName:
- paymentMethodName ?? this.paymentMethodLastFourDigits,
- paymentMethodLastFourDigits:
- paymentMethodLastFourDigits ?? this.paymentMethodLastFourDigits,
error: error);
}
}
diff --git a/comwell_key_app/lib/pregistration/components/add_card.dart b/comwell_key_app/lib/pregistration/components/add_card.dart
new file mode 100644
index 00000000..64b8e873
--- /dev/null
+++ b/comwell_key_app/lib/pregistration/components/add_card.dart
@@ -0,0 +1,86 @@
+import 'package:adyen_checkout/adyen_checkout.dart';
+import 'package:comwell_key_app/pregistration/bloc/preregistration_cubit.dart';
+import 'package:comwell_key_app/themes/light_theme.dart';
+import 'package:easy_localization/easy_localization.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter_bloc/flutter_bloc.dart';
+import 'package:flutter_svg/flutter_svg.dart';
+
+import '../../services/adyen/payment_method.dart';
+
+class AddCard extends StatelessWidget {
+ final VoidCallback onClick;
+
+ const AddCard({super.key, required this.onClick});
+
+ @override
+ Widget build(BuildContext context) {
+ final cubit = context.read<PreregistrationCubit>();
+ final paymentMethod =
+ _extractPaymentMethod(cubit.state.availablePaymentMethods);
+ final config = CardComponentConfiguration(
+ environment: Environment.test,
+ clientKey: "ComwellHotelsECOM",
+ countryCode: "DK",
+ shopperLocale: "da-DK",
+ cardConfiguration:
+ const CardConfiguration(showStorePaymentField: true));
+
+ return InkWell(
+ onTap: () async {
+ try {
+ await showModalBottomSheet(
+ isDismissible: false,
+ isScrollControlled: true,
+ context: context,
+ builder: (BuildContext context) {
+ return SafeArea(
+ child: Padding(
+ padding: MediaQuery.of(context).viewInsets,
+ child: AdyenCardComponent(
+ configuration: config,
+ paymentMethod: paymentMethod?.toJson() ?? {},
+ checkout: cubit.advancedCheckout(),
+ onPaymentResult: cubit.onPaymentResult,
+ ),
+ ));
+ },
+ );
+ cubit.fetchPaymentMethods();
+ } catch (e) {
+ cubit.fetchPaymentMethods();
+ }
+ },
+ child: Container(
+ decoration: BoxDecoration(
+ border: Border.all(color: colorDivider),
+ ),
+ padding: const EdgeInsets.all(12),
+ child: Row(
+ crossAxisAlignment: CrossAxisAlignment.center,
+ children: [
+ Text(
+ "preregistration_payment_add_card".tr(),
+ style: Theme.of(context).textTheme.bodyMedium,
+ ),
+ const SizedBox(width: 12),
+ SvgPicture.asset("assets/icons/visa.svg"),
+ const SizedBox(width: 4),
+ SvgPicture.asset("assets/icons/mastercard.svg"),
+ const SizedBox(width: 4),
+ SvgPicture.asset("assets/icons/maestro.svg"),
+ const Expanded(child: SizedBox()),
+ SvgPicture.asset("assets/icons/ic_plus.svg"),
+ ],
+ ),
+ ),
+ );
+ }
+
+ PaymentMethod? _extractPaymentMethod(Iterable<PaymentMethod> paymentMethods) {
+ for (var paymentMethod in paymentMethods) {
+ if (paymentMethod.type == "scheme") return paymentMethod;
+ }
+ return null;
+ }
+}
diff --git a/comwell_key_app/lib/pregistration/components/card_item.dart b/comwell_key_app/lib/pregistration/components/card_item.dart
new file mode 100644
index 00000000..a5bb8cdc
--- /dev/null
+++ b/comwell_key_app/lib/pregistration/components/card_item.dart
@@ -0,0 +1,55 @@
+import 'package:comwell_key_app/common/components/payment_card_image.dart';
+import 'package:comwell_key_app/overview/models/payment_details.dart';
+import 'package:comwell_key_app/pregistration/bloc/preregistration_cubit.dart';
+import 'package:comwell_key_app/services/adyen/stored_payment_method.dart';
+import 'package:comwell_key_app/themes/light_theme.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter_bloc/flutter_bloc.dart';
+import 'package:flutter_svg/flutter_svg.dart';
+
+class CardItem extends StatelessWidget {
+ final StoredPaymentMethod paymentMethod;
+ final bool isSelected;
+
+ const CardItem({
+ super.key,
+ required this.paymentMethod,
+ required this.isSelected,
+ });
+
+ @override
+ Widget build(BuildContext context) {
+ final cubit = context.read<PreregistrationCubit>();
+ return InkWell(
+ onTap: () => cubit.onSelectCard(paymentMethod),
+ child: Container(
+ decoration: BoxDecoration(
+ border: Border.all(color: colorDivider),
+ ),
+ padding: const EdgeInsets.all(12),
+ child: Row(
+ crossAxisAlignment: CrossAxisAlignment.center,
+ children: [
+ PaymentCardImage(cardType: CardType.fromString(paymentMethod.type)),
+ const SizedBox(width: 12),
+ Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ Text(
+ paymentMethod.name,
+ style: Theme.of(context).textTheme.bodySmall,
+ ),
+ Text(
+ "**** **** **** ${paymentMethod.lastFour}",
+ style: Theme.of(context).textTheme.bodyMedium,
+ ),
+ ],
+ ),
+ const Expanded(child: SizedBox()),
+ if (isSelected) SvgPicture.asset("assets/icons/ic_checkmark.svg")
+ ],
+ ),
+ ),
+ );
+ }
+}
diff --git a/comwell_key_app/lib/pregistration/components/information_card.dart b/comwell_key_app/lib/pregistration/components/information_card.dart
new file mode 100644
index 00000000..cfbccf08
--- /dev/null
+++ b/comwell_key_app/lib/pregistration/components/information_card.dart
@@ -0,0 +1,38 @@
+import 'package:flutter/material.dart';
+
+class InformationCard extends StatelessWidget {
+ final String title;
+ final VoidCallback onEditClick;
+ final Widget child;
+
+ const InformationCard({
+ super.key,
+ required this.title,
+ required this.onEditClick,
+ required this.child,
+ });
+
+ @override
+ Widget build(BuildContext context) {
+ return Container(
+ padding: const EdgeInsets.all(12),
+ decoration: const BoxDecoration(
+ color: Color(0xFFF9F6F2),
+ borderRadius: BorderRadius.all(Radius.circular(10))),
+ child: Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ Row(
+ mainAxisAlignment: MainAxisAlignment.spaceBetween,
+ children: [
+ Text(title),
+ TextButton(onPressed: onEditClick, child: const Text("Rediger"))
+ ],
+ ),
+ const SizedBox(height: 40),
+ child
+ ],
+ ),
+ );
+ }
+}
diff --git a/comwell_key_app/lib/pregistration/pages/prereg_confirmation_page.dart b/comwell_key_app/lib/pregistration/pages/prereg_confirmation_page.dart
index 076f4505..f454a9d3 100644
--- a/comwell_key_app/lib/pregistration/pages/prereg_confirmation_page.dart
+++ b/comwell_key_app/lib/pregistration/pages/prereg_confirmation_page.dart
@@ -1,10 +1,11 @@
import 'package:comwell_key_app/pregistration/bloc/preregistration_cubit.dart';
-import 'package:comwell_key_app/pregistration/widgets/information_card.dart';
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_svg/svg.dart';
+import '../components/information_card.dart';
+
class PreregConfirmationPage extends StatelessWidget {
const PreregConfirmationPage({super.key});
@@ -101,14 +102,14 @@ class PreregConfirmationPage extends StatelessWidget {
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
- state.paymentMethodName,
+ "${state.selectedPaymentMethod?.name}",
style: Theme
.of(context)
.textTheme
.bodySmall,
),
Text(
- "**** **** **** ${state.paymentMethodLastFourDigits}",
+ "**** **** **** ${state.selectedPaymentMethod?.lastFour}",
style: Theme
.of(context)
.textTheme
diff --git a/comwell_key_app/lib/pregistration/pages/prereg_payment_page.dart b/comwell_key_app/lib/pregistration/pages/prereg_payment_page.dart
index 8a3c07fe..76840e22 100644
--- a/comwell_key_app/lib/pregistration/pages/prereg_payment_page.dart
+++ b/comwell_key_app/lib/pregistration/pages/prereg_payment_page.dart
@@ -1,13 +1,23 @@
-import 'package:comwell_key_app/pregistration/widgets/add_card.dart';
-import 'package:comwell_key_app/pregistration/widgets/card_item.dart';
+import 'package:comwell_key_app/pregistration/bloc/preregistration_cubit.dart';
+import 'package:comwell_key_app/services/adyen/adyen_amount.dart';
+import 'package:comwell_key_app/services/adyen/payment_method.dart';
+import 'package:comwell_key_app/services/adyen/stored_payment_method.dart';
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
+import 'package:flutter_bloc/flutter_bloc.dart';
+
+import '../components/add_card.dart';
+import '../components/card_item.dart';
class PreregPaymentPage extends StatelessWidget {
const PreregPaymentPage({super.key});
@override
Widget build(BuildContext context) {
+ final cubit = context.read<PreregistrationCubit>();
+ final isTermsAndConditionsAccepted = cubit.state.termsAndConditionsAccepted;
+ final paymentMethods = cubit.state.storedPaymentMethods;
+ final selectedPaymentMethod = cubit.state.selectedPaymentMethod;
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
@@ -18,13 +28,28 @@ class PreregPaymentPage extends StatelessWidget {
Text("preregistration_payment_subtitle".tr(),
style: Theme.of(context).textTheme.bodySmall),
const SizedBox(height: 40),
- const CardItem(),
- const SizedBox(height: 12),
- const CardItem(),
- const SizedBox(height: 12),
- const CardItem(),
- const SizedBox(height: 12),
- AddCard(onClick: () {})
+ ...paymentMethods.map((pm) => Padding(
+ padding: const EdgeInsets.only(bottom: 12.0),
+ child: CardItem(
+ paymentMethod: pm,
+ isSelected: pm.id == selectedPaymentMethod?.id,
+ ),
+ )),
+ AddCard(onClick: () {}),
+ Row(
+ children: [
+ Checkbox(
+ value: isTermsAndConditionsAccepted,
+ activeColor: const Color(0xffAA8D65),
+ shape: RoundedRectangleBorder(
+ borderRadius: BorderRadius.circular(4),
+ ),
+ onChanged: (toggle) {
+ cubit.onTermsAndConditionsToggled(toggle ?? false);
+ }),
+ const Text("Jeg acceptere betingelserne")
+ ],
+ )
],
);
}
diff --git a/comwell_key_app/lib/pregistration/pregistration_repository.dart b/comwell_key_app/lib/pregistration/pregistration_repository.dart
new file mode 100644
index 00000000..713e8ffe
--- /dev/null
+++ b/comwell_key_app/lib/pregistration/pregistration_repository.dart
@@ -0,0 +1,83 @@
+import 'package:adyen_checkout/adyen_checkout.dart';
+import 'package:comwell_key_app/common/const.dart';
+import 'package:comwell_key_app/profile_settings/repostiory/profile_settings_repository.dart';
+import 'package:comwell_key_app/services/adyen/extensions.dart';
+import 'package:comwell_key_app/services/adyen/payment_event_handler.dart';
+import 'package:comwell_key_app/services/adyen/stored_payment_method.dart';
+import 'package:comwell_key_app/services/api.dart';
+
+import '../services/adyen/adyen_amount.dart';
+import '../services/adyen/payment_request_data.dart';
+import '../utils/locator.dart';
+import '../utils/payment_utils.dart';
+
+class PreregistrationRepository {
+ final Api api = Api();
+ final ProfileSettingsRepository profileSettingsRepository =
+ locator<ProfileSettingsRepository>();
+
+ PreregistrationRepository();
+
+ Future<Iterable<StoredPaymentMethod>> getPaymentMethods() async {
+ final user = await profileSettingsRepository.fetchProfileSettings();
+ if (user == null) throw Exception("User not logged in");
+ final response = await api.getPaymentMethods(user.shopperReference);
+ return response.data!.storedPaymentMethods;
+ }
+
+ Future<PaymentEvent> onSubmit(
+ Map<String, dynamic> data, [
+ Map<String, dynamic>? extra,
+ ]) async {
+ final user = await profileSettingsRepository.fetchProfileSettings();
+ if (user == null) throw Exception("User not logged in");
+ String returnUrl = await determineBaseReturnUrl();
+ returnUrl += "/adyenPayment";
+ final paymentsRequestData = PaymentsRequestData(
+ merchantAccount: AdyenConstants.merchantAccount,
+ shopperReference: user.shopperReference,
+ reference: "booking_${DateTime.now().millisecondsSinceEpoch}",
+ returnUrl: returnUrl,
+ amount: AdyenAmount.named(
+ value: 0,
+ currency: "DKK",
+ ),
+ countryCode: "da-DK",
+ channel: determineChannel(),
+ recurringProcessingModel: RecurringProcessingModel.cardOnFile,
+ shopperInteraction:
+ ShopperInteractionModel.ecommerce.shopperInteractionModelString,
+ authenticationData: {
+ "threeDSRequestData": {
+ "nativeThreeDS": "preferred",
+ },
+ },
+ );
+ final Map<String, dynamic> mergedJson = <String, dynamic>{};
+ mergedJson.addAll(data);
+ mergedJson.addAll(paymentsRequestData.toJson());
+ final response = await api.postPaymentsDetails(mergedJson);
+ return PaymentEventHandler().handleResponse(jsonResponse: response);
+ }
+
+ Future<PaymentEvent> onAdditionalDetails(
+ Map<String, dynamic> additionalDetails) async {
+ final response = await api.postPaymentsDetails(additionalDetails);
+ return PaymentEventHandler().handleResponse(jsonResponse: response);
+ }
+
+ static final Iterable<StoredPaymentMethod> _mockData = [1, 2, 3, 4].map((i) =>
+ StoredPaymentMethod(
+ brand: "brand",
+ expiryMonth: "expiryMonth",
+ expiryYear: "expiryYear",
+ holderName: "holderName",
+ id: "id $i",
+ lastFour: "$i$i$i$i",
+ name: "name $i",
+ shopperEmail: "shopperEmail",
+ supportedRecurringProcessingModels: const [
+ "supportedRecurringProcessingModels"
+ ],
+ type: "visa"));
+}
diff --git a/comwell_key_app/lib/pregistration/preregistration_flow.dart b/comwell_key_app/lib/pregistration/preregistration_flow.dart
index a56f0bdc..ade74604 100644
--- a/comwell_key_app/lib/pregistration/preregistration_flow.dart
+++ b/comwell_key_app/lib/pregistration/preregistration_flow.dart
@@ -16,15 +16,15 @@ enum PreregistrationPage {
return PreregistrationPage.values[index];
}
- static Iterable<Widget> getPages() {
+ static Iterable<Widget> getPages(Key key) {
return PreregistrationPage.values.map((page) {
switch (page) {
case PreregistrationPage.information:
- return const PreregInformationPage();
+ return PreregInformationPage(key: key);
case PreregistrationPage.paymentMethod:
- return const PreregPaymentPage();
+ return PreregPaymentPage(key: key);
case PreregistrationPage.confirmation:
- return const PreregConfirmationPage();
+ return PreregConfirmationPage(key: key);
}
});
}
@@ -77,18 +77,23 @@ class _PreregistrationFlowState extends State<PreregistrationFlow> {
child: Padding(
padding: const EdgeInsets.all(16.0),
child: ElevatedButton(
- onPressed: () {
- cubit.onContinueClicked();
- },
- style: const ButtonStyle(
+ onPressed: cubit.canContinue
+ ? cubit.onContinueClicked
+ : null,
+ style: ButtonStyle(
backgroundColor:
- WidgetStatePropertyAll(Color(0xffAA8D65)),
+ WidgetStateProperty.resolveWith((states) {
+ if (states.contains(WidgetState.disabled)) {
+ return Colors.grey;
+ }
+ return const Color(0xffAA8D65);
+ }),
foregroundColor:
- WidgetStatePropertyAll(Colors.white)),
+ const WidgetStatePropertyAll(Colors.white)),
child: Padding(
padding:
const EdgeInsets.symmetric(vertical: 16.0),
- child: Text(state.buttonTextLocalized),
+ child: Text(cubit.buttonText),
),
),
),
@@ -109,7 +114,8 @@ class _PreregistrationFlowState extends State<PreregistrationFlow> {
return PageView(
physics: const NeverScrollableScrollPhysics(),
controller: cubit.pageController,
- children: PreregistrationPage.getPages().toList(),
+ children: PreregistrationPage.getPages(ValueKey(state))
+ .toList(),
);
},
),
diff --git a/comwell_key_app/lib/pregistration/widgets/add_card.dart b/comwell_key_app/lib/pregistration/widgets/add_card.dart
deleted file mode 100644
index 7613ba74..00000000
--- a/comwell_key_app/lib/pregistration/widgets/add_card.dart
+++ /dev/null
@@ -1,40 +0,0 @@
-import 'package:comwell_key_app/themes/light_theme.dart';
-import 'package:easy_localization/easy_localization.dart';
-import 'package:flutter/material.dart';
-import 'package:flutter_svg/flutter_svg.dart';
-
-class AddCard extends StatelessWidget {
- final VoidCallback onClick;
-
- const AddCard({super.key, required this.onClick});
-
- @override
- Widget build(BuildContext context) {
- return InkWell(
- onTap: onClick,
- child: Container(
- decoration: BoxDecoration(
- border: Border.all(color: colorDivider),
- ),
- padding: const EdgeInsets.all(12),
- child: Row(
- crossAxisAlignment: CrossAxisAlignment.center,
- children: [
- Text(
- "preregistration_payment_add_card".tr(),
- style: Theme.of(context).textTheme.bodyMedium,
- ),
- const SizedBox(width: 12),
- SvgPicture.asset("assets/icons/visa.svg"),
- const SizedBox(width: 4),
- SvgPicture.asset("assets/icons/mastercard.svg"),
- const SizedBox(width: 4),
- SvgPicture.asset("assets/icons/maestro.svg"),
- const Expanded(child: SizedBox()),
- SvgPicture.asset("assets/icons/ic_plus.svg"),
- ],
- ),
- ),
- );
- }
-}
diff --git a/comwell_key_app/lib/pregistration/widgets/card_item.dart b/comwell_key_app/lib/pregistration/widgets/card_item.dart
deleted file mode 100644
index 0d6aea8e..00000000
--- a/comwell_key_app/lib/pregistration/widgets/card_item.dart
+++ /dev/null
@@ -1,39 +0,0 @@
-import 'package:comwell_key_app/themes/light_theme.dart';
-import 'package:flutter/material.dart';
-import 'package:flutter_svg/flutter_svg.dart';
-
-class CardItem extends StatelessWidget {
- const CardItem({super.key});
-
- @override
- Widget build(BuildContext context) {
- return Container(
- decoration: BoxDecoration(
- border: Border.all(color: colorDivider),
- ),
- padding: const EdgeInsets.all(12),
- child: Row(
- crossAxisAlignment: CrossAxisAlignment.center,
- children: [
- SvgPicture.asset("assets/icons/maestro.svg"),
- const SizedBox(width: 12),
- Column(
- crossAxisAlignment: CrossAxisAlignment.start,
- children: [
- Text(
- "Name",
- style: Theme.of(context).textTheme.bodySmall,
- ),
- Text(
- "**** **** **** 1234",
- style: Theme.of(context).textTheme.bodyMedium,
- ),
- ],
- ),
- const Expanded(child: SizedBox()),
- SvgPicture.asset("assets/icons/ic_checkmark.svg"),
- ],
- ),
- );
- }
-}
diff --git a/comwell_key_app/lib/pregistration/widgets/information_card.dart b/comwell_key_app/lib/pregistration/widgets/information_card.dart
deleted file mode 100644
index cfbccf08..00000000
--- a/comwell_key_app/lib/pregistration/widgets/information_card.dart
+++ /dev/null
@@ -1,38 +0,0 @@
-import 'package:flutter/material.dart';
-
-class InformationCard extends StatelessWidget {
- final String title;
- final VoidCallback onEditClick;
- final Widget child;
-
- const InformationCard({
- super.key,
- required this.title,
- required this.onEditClick,
- required this.child,
- });
-
- @override
- Widget build(BuildContext context) {
- return Container(
- padding: const EdgeInsets.all(12),
- decoration: const BoxDecoration(
- color: Color(0xFFF9F6F2),
- borderRadius: BorderRadius.all(Radius.circular(10))),
- child: Column(
- crossAxisAlignment: CrossAxisAlignment.start,
- children: [
- Row(
- mainAxisAlignment: MainAxisAlignment.spaceBetween,
- children: [
- Text(title),
- TextButton(onPressed: onEditClick, child: const Text("Rediger"))
- ],
- ),
- const SizedBox(height: 40),
- child
- ],
- ),
- );
- }
-}
diff --git a/comwell_key_app/lib/profile_settings/model/user.dart b/comwell_key_app/lib/profile_settings/model/user.dart
index 44e5383c..f505cc8b 100644
--- a/comwell_key_app/lib/profile_settings/model/user.dart
+++ b/comwell_key_app/lib/profile_settings/model/user.dart
@@ -9,9 +9,11 @@ class User {
final String email;
final Address address;
final DateTime birthday;
+ final String shopperReference;
User({
required this.id,
+ required this.shopperReference,
required this.firstName,
required this.lastName,
required this.countryCode,
@@ -27,6 +29,7 @@ class User {
firstName: json['firstName'] as String,
lastName: json['lastName'] as String,
countryCode: json['countryCode'] as String,
+ shopperReference: json["shopperReference"] as String? ?? "",
phone: json['phone'] as String,
email: json['email'] as String,
address: Address.fromJson(json['address'] as Map<String, dynamic>),
@@ -41,6 +44,7 @@ class User {
'lastName': lastName,
'phone': phone,
'email': email,
+ 'shopperReference': shopperReference,
'address': address.toJson(),
'birthday': birthday.toIso8601String(),
};
@@ -54,6 +58,7 @@ class User {
String? phone,
String? email,
Address? address,
+ String? shopperReference,
DateTime? birthday,
}) {
return User(
@@ -61,6 +66,7 @@ class User {
firstName: firstName ?? this.firstName,
lastName: lastName ?? this.lastName,
countryCode: countryCode ?? this.countryCode,
+ shopperReference: shopperReference ?? this.shopperReference,
phone: phone ?? this.phone,
email: email ?? this.email,
address: address ?? this.address,
diff --git a/comwell_key_app/lib/services/adyen/adyen_amount.dart b/comwell_key_app/lib/services/adyen/adyen_amount.dart
new file mode 100644
index 00000000..54b31cb8
--- /dev/null
+++ b/comwell_key_app/lib/services/adyen/adyen_amount.dart
@@ -0,0 +1,18 @@
+import 'package:comwell_key_app/utils/json.dart';
+import 'package:json_annotation/json_annotation.dart';
+
+part '../../.generated/services/adyen/adyen_amount.g.dart';
+
+@JsonSerializable()
+class AdyenAmount {
+ final String currency;
+ final int value;
+
+ AdyenAmount.named({required this.currency, required this.value});
+
+ AdyenAmount(this.currency, this.value);
+
+ factory AdyenAmount.fromJson(Json json) => _$AdyenAmountFromJson(json);
+
+ Json toJson() => _$AdyenAmountToJson(this);
+}
diff --git a/comwell_key_app/lib/services/adyen/adyen_line_item.dart b/comwell_key_app/lib/services/adyen/adyen_line_item.dart
new file mode 100644
index 00000000..a5a899f5
--- /dev/null
+++ b/comwell_key_app/lib/services/adyen/adyen_line_item.dart
@@ -0,0 +1,33 @@
+import 'package:comwell_key_app/utils/json.dart';
+import 'package:json_annotation/json_annotation.dart';
+
+part '../../.generated/services/adyen/adyen_line_item.g.dart';
+
+@JsonSerializable()
+class AdyenLineItem {
+ int? quantity;
+ int? amountExcludingTax;
+ int? taxPercentage;
+ String? description;
+ String? id;
+ int? taxAmount;
+ int? amountIncludingTax;
+ String? productUrl;
+ String? imageUrl;
+
+ AdyenLineItem({
+ this.quantity,
+ this.amountExcludingTax,
+ this.taxPercentage,
+ this.description,
+ this.id,
+ this.taxAmount,
+ this.amountIncludingTax,
+ this.productUrl,
+ this.imageUrl,
+ });
+
+ factory AdyenLineItem.fromJson(Json json) => _$AdyenLineItemFromJson(json);
+
+ Json toJson() => _$AdyenLineItemToJson(this);
+}
diff --git a/comwell_key_app/lib/services/adyen/extensions.dart b/comwell_key_app/lib/services/adyen/extensions.dart
new file mode 100644
index 00000000..5f87fccb
--- /dev/null
+++ b/comwell_key_app/lib/services/adyen/extensions.dart
@@ -0,0 +1,55 @@
+
+enum StorePaymentMethodMode {
+ disabled,
+ askForConsent,
+ enabled,
+}
+
+enum RecurringProcessingModel {
+ subscription,
+ cardOnFile,
+ unscheduledCardOnFile
+}
+
+enum ShopperInteractionModel { ecommerce, contAuth, moto, pos }
+
+extension StorePaymentMethodModeExtension on StorePaymentMethodMode {
+ String get storePaymentMethodModeString {
+ switch (this) {
+ case StorePaymentMethodMode.disabled:
+ return "disabled";
+ case StorePaymentMethodMode.askForConsent:
+ return "askForConsent";
+ case StorePaymentMethodMode.enabled:
+ return "enabled";
+ }
+ }
+}
+
+extension RecurringProcessingModelExtension on RecurringProcessingModel {
+ String get recurringModelString {
+ switch (this) {
+ case RecurringProcessingModel.subscription:
+ return 'Subscription';
+ case RecurringProcessingModel.cardOnFile:
+ return 'CardOnFile';
+ case RecurringProcessingModel.unscheduledCardOnFile:
+ return 'UnscheduledCardOnFile';
+ }
+ }
+}
+
+extension ShopperInteractionModelExtension on ShopperInteractionModel {
+ String get shopperInteractionModelString {
+ switch (this) {
+ case ShopperInteractionModel.ecommerce:
+ return "Ecommerce";
+ case ShopperInteractionModel.contAuth:
+ return "ContAuth";
+ case ShopperInteractionModel.moto:
+ return "Moto";
+ case ShopperInteractionModel.pos:
+ return "POS";
+ }
+ }
+}
diff --git a/comwell_key_app/lib/services/adyen/payment_event_handler.dart b/comwell_key_app/lib/services/adyen/payment_event_handler.dart
new file mode 100644
index 00000000..e64a4d28
--- /dev/null
+++ b/comwell_key_app/lib/services/adyen/payment_event_handler.dart
@@ -0,0 +1,80 @@
+import 'package:adyen_checkout/adyen_checkout.dart';
+import 'package:comwell_key_app/utils/json.dart';
+
+class PaymentEventHandler {
+ //Response keys
+ static const errorCodeKey = "errorCode";
+ static const resultCodeKey = "resultCode";
+ static const actionKey = "action";
+ static const messageKey = "message";
+ static const refusalReasonKey = "refusalReason";
+
+ PaymentEvent handleResponse({
+ required Json jsonResponse,
+ Json updatedPaymentMethodsJson = const {},
+ }) {
+ if (_isError(jsonResponse)) {
+ return Error(
+ errorMessage: jsonResponse[messageKey] as String,
+ reason: (jsonResponse[messageKey] ?? jsonResponse[refusalReasonKey])
+ as String,
+ dismissDropIn: true,
+ );
+ }
+
+ if (_isRefusedInPartialPaymentFlow(jsonResponse)) {
+ return Error(
+ errorMessage: "Payment is refused",
+ reason: "Refused",
+ dismissDropIn: true,
+ );
+ }
+
+ if (_isAction(jsonResponse)) {
+ return Action(actionResponse: jsonResponse[actionKey] as Json);
+ }
+
+ if (_isNonFullyPaidOrder(jsonResponse) &&
+ updatedPaymentMethodsJson.isNotEmpty) {
+ return Update(
+ orderJson: jsonResponse["order"] as Json,
+ paymentMethodsJson: updatedPaymentMethodsJson,
+ );
+ }
+
+ if (jsonResponse.containsKey(resultCodeKey)) {
+ return Finished(resultCode: jsonResponse[resultCodeKey] as String);
+ }
+
+ return Finished(resultCode: "EMPTY");
+ }
+
+ bool _isError(Json jsonResponse) {
+ final hasErrorCodeKey = jsonResponse.containsKey(errorCodeKey);
+ final hasErrorResultCode = (jsonResponse[resultCodeKey] as String?)
+ ?.toUpperCase()
+ .contains(ResultCode.error.name.toUpperCase()) ??
+ false;
+ return hasErrorCodeKey || hasErrorResultCode;
+ }
+
+ bool _isRefusedInPartialPaymentFlow(Json jsonResponse) =>
+ _isRefused(jsonResponse) && _isNonFullyPaidOrder(jsonResponse);
+
+ bool _isRefused(Json jsonResponse) => jsonResponse[resultCodeKey]
+ .toString()
+ .toUpperCase()
+ .contains(ResultCode.refused.name.toUpperCase());
+
+ bool _isAction(Json jsonResponse) => jsonResponse.containsKey(actionKey);
+
+ bool _isNonFullyPaidOrder(Json jsonResponse) {
+ if (jsonResponse.containsKey("order")) {
+ final num remainingAmount =
+ jsonResponse["order"]["remainingAmount"]["value"] as num;
+ return remainingAmount > 0;
+ } else {
+ return false;
+ }
+ }
+}
diff --git a/comwell_key_app/lib/services/adyen/payment_method.dart b/comwell_key_app/lib/services/adyen/payment_method.dart
new file mode 100644
index 00000000..68b81f61
--- /dev/null
+++ b/comwell_key_app/lib/services/adyen/payment_method.dart
@@ -0,0 +1,16 @@
+import 'package:comwell_key_app/utils/json.dart';
+import 'package:json_annotation/json_annotation.dart';
+
+part '../../.generated/services/adyen/payment_method.g.dart';
+
+@JsonSerializable()
+class PaymentMethod {
+ final String name;
+ final String type;
+
+ PaymentMethod(this.name, this.type);
+
+ factory PaymentMethod.fromJson(Map<String, dynamic> json) => _$PaymentMethodFromJson(json);
+
+ Json toJson() => _$PaymentMethodToJson(this);
+}
\ No newline at end of file
diff --git a/comwell_key_app/lib/services/adyen/payment_methods.dart b/comwell_key_app/lib/services/adyen/payment_methods.dart
new file mode 100644
index 00000000..d9a9948f
--- /dev/null
+++ b/comwell_key_app/lib/services/adyen/payment_methods.dart
@@ -0,0 +1,15 @@
+import 'package:comwell_key_app/services/adyen/payment_method.dart';
+import 'package:comwell_key_app/services/adyen/stored_payment_method.dart';
+import 'package:json_annotation/json_annotation.dart';
+
+part '../../.generated/services/adyen/payment_methods.g.dart';
+
+@JsonSerializable()
+class PaymentMethods {
+ final Iterable<PaymentMethod> paymentMethods;
+ final Iterable<StoredPaymentMethod> storedPaymentMethods;
+
+ PaymentMethods(this.paymentMethods, this.storedPaymentMethods);
+
+ factory PaymentMethods.fromJson(Map<String, dynamic> json) => _$PaymentMethodsFromJson(json);
+}
\ No newline at end of file
diff --git a/comwell_key_app/lib/services/adyen/payment_request_data.dart b/comwell_key_app/lib/services/adyen/payment_request_data.dart
new file mode 100644
index 00000000..0a3f9dc6
--- /dev/null
+++ b/comwell_key_app/lib/services/adyen/payment_request_data.dart
@@ -0,0 +1,48 @@
+import 'package:comwell_key_app/services/adyen/adyen_amount.dart';
+import 'package:comwell_key_app/utils/json.dart';
+import 'package:json_annotation/json_annotation.dart';
+
+import 'adyen_line_item.dart';
+import 'extensions.dart';
+
+part '../../.generated/services/adyen/payment_request_data.g.dart';
+
+
+@JsonSerializable(includeIfNull: false)
+class PaymentsRequestData {
+ final String merchantAccount;
+ final AdyenAmount amount;
+ final String reference;
+ final String? shopperReference;
+ final String? countryCode;
+ final String? returnUrl;
+ final Map<String, dynamic>? additionalData;
+ final String? shopperIP;
+ final String? channel;
+ final List<AdyenLineItem>? lineItems;
+ final String? shopperEmail;
+ final Map<String, dynamic>? threeDS2RequestData;
+ final RecurringProcessingModel? recurringProcessingModel;
+ final String? shopperInteraction;
+ final Map<String, dynamic>? authenticationData;
+
+ PaymentsRequestData({
+ required this.merchantAccount,
+ required this.amount,
+ required this.reference,
+ this.shopperReference,
+ this.countryCode,
+ this.returnUrl,
+ this.additionalData,
+ this.shopperIP,
+ this.channel,
+ this.lineItems,
+ this.shopperEmail,
+ this.threeDS2RequestData,
+ this.recurringProcessingModel,
+ this.shopperInteraction,
+ this.authenticationData,
+ });
+
+ Json toJson() => _$PaymentsRequestDataToJson(this);
+}
diff --git a/comwell_key_app/lib/services/adyen/stored_payment_method.dart b/comwell_key_app/lib/services/adyen/stored_payment_method.dart
new file mode 100644
index 00000000..f5c1d14e
--- /dev/null
+++ b/comwell_key_app/lib/services/adyen/stored_payment_method.dart
@@ -0,0 +1,36 @@
+import 'package:equatable/equatable.dart';
+import 'package:json_annotation/json_annotation.dart';
+
+part '../../.generated/services/adyen/stored_payment_method.g.dart';
+
+@JsonSerializable()
+class StoredPaymentMethod extends Equatable {
+ String brand;
+ String expiryMonth;
+ String expiryYear;
+ String holderName;
+ String id;
+ String lastFour;
+ String name;
+ String shopperEmail;
+ List<String> supportedRecurringProcessingModels;
+ String type;
+
+ StoredPaymentMethod({
+ required this.brand,
+ required this.expiryMonth,
+ required this.expiryYear,
+ required this.holderName,
+ required this.id,
+ required this.lastFour,
+ required this.name,
+ required this.shopperEmail,
+ required this.supportedRecurringProcessingModels,
+ required this.type,
+ });
+
+ factory StoredPaymentMethod.fromJson(Map<String, dynamic> json) => _$StoredPaymentMethodFromJson(json);
+
+ @override
+ List<Object?> get props => [id];
+}
\ No newline at end of file
diff --git a/comwell_key_app/lib/services/api.dart b/comwell_key_app/lib/services/api.dart
index d844a605..f8bde9ae 100644
--- a/comwell_key_app/lib/services/api.dart
+++ b/comwell_key_app/lib/services/api.dart
@@ -1,8 +1,11 @@
+import 'dart:convert';
import 'package:comwell_key_app/profile_settings/model/user.dart';
import 'package:comwell_key_app/services/http_client.dart';
import 'package:dio/dio.dart';
+import 'adyen/payment_methods.dart';
+
class Api {
Dio? _dio;
@@ -23,6 +26,17 @@ class Api {
return await dio.get('/booking/v1/GetCurrentBookingsFunction/$userId');
}
+ Future<Response<PaymentMethods>> getPaymentMethods(
+ String shopperReference) async {
+ return await dio.get('/paymentMethods?shopperReference=$shopperReference');
+ }
+
+ Future<Map<String, dynamic>> postPaymentsDetails(
+ Map<String, dynamic> body) async {
+ final response = await dio.post("/payment/details", data: jsonEncode(body));
+ return response.data as Map<String, dynamic>;
+ }
+
Future<Response<dynamic>> createEndpointRegistration() async {
return await dio.post('/keys/v1/CreateEndpointRegistration');
}
diff --git a/comwell_key_app/lib/utils/json.dart b/comwell_key_app/lib/utils/json.dart
new file mode 100644
index 00000000..3e024144
--- /dev/null
+++ b/comwell_key_app/lib/utils/json.dart
@@ -0,0 +1 @@
+typedef Json = Map<String, dynamic>;
\ No newline at end of file
diff --git a/comwell_key_app/lib/utils/locator.dart b/comwell_key_app/lib/utils/locator.dart
index 8a5e78e3..b43caf86 100644
--- a/comwell_key_app/lib/utils/locator.dart
+++ b/comwell_key_app/lib/utils/locator.dart
@@ -2,6 +2,7 @@ import 'package:comwell_key_app/authentication/authentication_repository.dart';
import 'package:comwell_key_app/home/home_repository.dart';
import 'package:comwell_key_app/key/repository/key_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/profile/profile_repository.dart';
import 'package:comwell_key_app/profile_settings/repostiory/profile_settings_repository.dart';
import 'package:device_info_plus/device_info_plus.dart';
@@ -10,19 +11,22 @@ import 'package:get_it/get_it.dart';
import 'package:seos_mobile_keys_plugin/seos_mobile_keys_plugin.dart';
final locator = GetIt.I;
+
void setupLocator() {
locator.registerFactory<DeviceInfoPlugin>(() => DeviceInfoPlugin());
- if(!kIsWeb) {
+ if (!kIsWeb) {
locator.registerSingleton(SeosMobileKeysPlugin());
- locator.registerFactory<KeyRepository>(() => KeyRepository(deviceInfoPlugin: locator<DeviceInfoPlugin>(), seosMobileKeysPlugin: locator<SeosMobileKeysPlugin>()));
+ locator.registerFactory<KeyRepository>(() => KeyRepository(
+ deviceInfoPlugin: locator<DeviceInfoPlugin>(),
+ seosMobileKeysPlugin: locator<SeosMobileKeysPlugin>()));
locator.registerFactory<OverviewRepository>(() => OverviewRepository());
- locator.registerFactory<ProfileSettingsRepository>(() => ProfileSettingsRepository());
- locator.registerFactory<AuthenticationRepository>(() => AuthenticationRepository());
+ locator.registerFactory<ProfileSettingsRepository>(
+ () => ProfileSettingsRepository());
+ locator.registerFactory<AuthenticationRepository>(
+ () => AuthenticationRepository());
locator.registerFactory<HomeRepository>(() => HomeRepository());
locator.registerFactory<ProfileRepository>(() => ProfileRepository());
-
+ locator.registerFactory<PreregistrationRepository>(
+ () => PreregistrationRepository());
}
-
-
-
-}
\ No newline at end of file
+}
diff --git a/comwell_key_app/lib/utils/payment_utils.dart b/comwell_key_app/lib/utils/payment_utils.dart
new file mode 100644
index 00000000..85d55f39
--- /dev/null
+++ b/comwell_key_app/lib/utils/payment_utils.dart
@@ -0,0 +1,25 @@
+import 'dart:io';
+
+import 'package:adyen_checkout/adyen_checkout.dart';
+
+String determineChannel() {
+ if (Platform.isAndroid) {
+ return "Android";
+ }
+
+ if (Platform.isIOS) {
+ return "iOS";
+ }
+
+ throw Exception("Unsupported platform");
+}
+
+Future<String> determineBaseReturnUrl() async {
+ if (Platform.isAndroid) {
+ return await AdyenCheckout.instance.getReturnUrl();
+ } else if (Platform.isIOS) {
+ return "adyencheckout://com.adyen.adyen_checkout_example";
+ } else {
+ throw Exception("Unsupported platform");
+ }
+}
\ No newline at end of file
diff --git a/comwell_key_app/pubspec.yaml b/comwell_key_app/pubspec.yaml
index 80121c5c..dfc7947c 100644
--- a/comwell_key_app/pubspec.yaml
+++ b/comwell_key_app/pubspec.yaml
@@ -1,29 +1,16 @@
name: comwell_key_app
description: This app needs a description
-# The following line prevents the package from being accidentally published to
-# pub.dev using `flutter pub publish`. This is preferred for private packages.
publish_to: 'none' # Remove this line if you wish to publish to pub.dev
version: 0.0.1+8
environment:
sdk: '>=3.0.0 <3.25.0'
-
-# Dependencies specify other packages that your package needs in order to work.
-# To automatically upgrade your package dependencies to the latest versions
-# consider running `flutter pub upgrade --major-versions`. Alternatively,
-# dependencies can be manually updated by changing the version numbers below to
-# the latest version available on pub.dev. To see which dependencies have newer
-# versions available, run `flutter pub outdated`.
dependencies:
flutter:
sdk: flutter
-
seos_mobile_keys_plugin:
path: ../mobilekeys_sdk_plugin
-
- # The following adds the Cupertino Icons font to your application.
- # Use with the CupertinoIcons class for iOS style icons.
cupertino_icons: ^1.0.2
focus_detector: ^2.0.0
permission_handler: ^11.3.0
@@ -53,19 +40,16 @@ dependencies:
flutter_launcher_icons: ^0.14.1
slider_button: ^2.1.0
country_code_picker: ^3.1.0
+ adyen_checkout: ^1.2.0
+ json_annotation: ^4.9.0
dev_dependencies:
flutter_test:
sdk: flutter
-
- # The "flutter_lints" package below contains a set of recommended lints to
- # encourage good coding practices. The lint set provided by the package is
- # activated in the `analysis_options.yaml` file located at the root of your
- # package. See that file for information about deactivating specific lint
- # rules and activating additional ones.
flutter_lints: ^4.0.0
- build_runner: ^2.4.11
change_app_package_name: ^1.3.0
+ build_runner: ^2.4.13
+ json_serializable: ^6.9.0
# For information on the generic Dart part of this file, see the
# following page: https://dart.dev/tools/pub/pubspec
diff --git a/comwell_key_app/test/home_test/home_bloc_test.mocks.dart b/comwell_key_app/test/home_test/home_bloc_test.mocks.dart
index 84c7380d..97776b5d 100644
--- a/comwell_key_app/test/home_test/home_bloc_test.mocks.dart
+++ b/comwell_key_app/test/home_test/home_bloc_test.mocks.dart
@@ -3,9 +3,11 @@
// Do not manually edit this file.
// ignore_for_file: no_leading_underscores_for_library_prefixes
-import 'dart:async' as _i3;
+import 'dart:async' as _i5;
-import 'package:comwell_key_app/home/home_repository.dart' as _i2;
+import 'package:comwell_key_app/home/home_repository.dart' as _i4;
+import 'package:comwell_key_app/services/api.dart' as _i2;
+import 'package:comwell_key_app/utils/secure_storage.dart' as _i3;
import 'package:mockito/mockito.dart' as _i1;
// ignore_for_file: type=lint
@@ -21,22 +23,113 @@ import 'package:mockito/mockito.dart' as _i1;
// ignore_for_file: camel_case_types
// ignore_for_file: subtype_of_sealed_class
+class _FakeApi_0 extends _i1.SmartFake implements _i2.Api {
+ _FakeApi_0(
+ Object parent,
+ Invocation parentInvocation,
+ ) : super(
+ parent,
+ parentInvocation,
+ );
+}
+
+class _FakeSecureStorage_1 extends _i1.SmartFake implements _i3.SecureStorage {
+ _FakeSecureStorage_1(
+ Object parent,
+ Invocation parentInvocation,
+ ) : super(
+ parent,
+ parentInvocation,
+ );
+}
+
/// A class which mocks [HomeRepository].
///
/// See the documentation for Mockito's code generation for more information.
-class MockHomeRepository extends _i1.Mock implements _i2.HomeRepository {
+class MockHomeRepository extends _i1.Mock implements _i4.HomeRepository {
MockHomeRepository() {
_i1.throwOnMissingStub(this);
}
@override
- _i3.Future<bool> isEndpointSetup({bool? firstLaunch = true}) =>
+ _i2.Api get api => (super.noSuchMethod(
+ Invocation.getter(#api),
+ returnValue: _FakeApi_0(
+ this,
+ Invocation.getter(#api),
+ ),
+ ) as _i2.Api);
+
+ @override
+ _i3.SecureStorage get secureStorage => (super.noSuchMethod(
+ Invocation.getter(#secureStorage),
+ returnValue: _FakeSecureStorage_1(
+ this,
+ Invocation.getter(#secureStorage),
+ ),
+ ) as _i3.SecureStorage);
+
+ @override
+ _i5.Future<bool> isEndpointSetup({bool? firstLaunch = true}) =>
(super.noSuchMethod(
Invocation.method(
#isEndpointSetup,
[],
{#firstLaunch: firstLaunch},
),
- returnValue: _i3.Future<bool>.value(false),
- ) as _i3.Future<bool>);
+ returnValue: _i5.Future<bool>.value(false),
+ ) as _i5.Future<bool>);
+
+ @override
+ _i5.Future<bool> updateEndpoint() => (super.noSuchMethod(
+ Invocation.method(
+ #updateEndpoint,
+ [],
+ ),
+ returnValue: _i5.Future<bool>.value(false),
+ ) as _i5.Future<bool>);
+
+ @override
+ _i5.Future<void> setupEndpoint() => (super.noSuchMethod(
+ Invocation.method(
+ #setupEndpoint,
+ [],
+ ),
+ returnValue: _i5.Future<void>.value(),
+ returnValueForMissingStub: _i5.Future<void>.value(),
+ ) as _i5.Future<void>);
+
+ @override
+ _i5.Future<void> provisionKey(
+ String? bookingId, {
+ bool? forceProvision = false,
+ }) =>
+ (super.noSuchMethod(
+ Invocation.method(
+ #provisionKey,
+ [bookingId],
+ {#forceProvision: forceProvision},
+ ),
+ returnValue: _i5.Future<void>.value(),
+ returnValueForMissingStub: _i5.Future<void>.value(),
+ ) as _i5.Future<void>);
+
+ @override
+ _i5.Future<bool> startMobilePlugin() => (super.noSuchMethod(
+ Invocation.method(
+ #startMobilePlugin,
+ [],
+ ),
+ returnValue: _i5.Future<bool>.value(false),
+ ) as _i5.Future<bool>);
+
+ @override
+ _i5.Future<String?> doesInvitationCodeExist(String? key) =>
+ (super.noSuchMethod(
+ Invocation.method(
+ #doesInvitationCodeExist,
+ [key],
+ ),
+ returnValue: _i5.Future<String?>.value(),
+ ) as _i5.Future<String?>);
}
diff --git a/comwell_key_app/test/profile_settings_test/profile_settings_cubit_test.dart b/comwell_key_app/test/profile_settings_test/profile_settings_cubit_test.dart
index dcb3501e..9937d65d 100644
--- a/comwell_key_app/test/profile_settings_test/profile_settings_cubit_test.dart
+++ b/comwell_key_app/test/profile_settings_test/profile_settings_cubit_test.dart
@@ -31,6 +31,7 @@ void main() {
id: '1',
firstName: 'John',
lastName: 'Doe',
+ shopperReference: "",
email: 'john.doe@example.com',
phone: '1234567890',
address: Address(
diff --git a/mobilekeys_sdk_plugin/android/.gradle/config.properties b/mobilekeys_sdk_plugin/android/.gradle/config.properties
new file mode 100644
index 00000000..73a6ef72
--- /dev/null
+++ b/mobilekeys_sdk_plugin/android/.gradle/config.properties
@@ -0,0 +1,2 @@
+#Fri Jan 10 14:59:51 CET 2025
+java.home=/Applications/Android Studio.app/Contents/jbr/Contents/Home
diff --git a/mobilekeys_sdk_plugin/android/libs/mobilekeys-android-sdk-debug-8.1.0.aar b/mobilekeys_sdk_plugin/android/libs/mobilekeys-android-sdk-debug-8.1.0.aar
deleted file mode 100644
index 837d5a7f..00000000
Binary files a/mobilekeys_sdk_plugin/android/libs/mobilekeys-android-sdk-debug-8.1.0.aar and /dev/null differ
diff --git a/mobilekeys_sdk_plugin/android/libs/mobilekeys-android-sdk-debug-8.1.2.aar b/mobilekeys_sdk_plugin/android/libs/mobilekeys-android-sdk-debug-8.1.2.aar
new file mode 100644
index 00000000..f6cf99f0
Binary files /dev/null and b/mobilekeys_sdk_plugin/android/libs/mobilekeys-android-sdk-debug-8.1.2.aar differ
diff --git a/mobilekeys_sdk_plugin/android/libs/mobilekeys-android-sdk-release-8.1.0.aar b/mobilekeys_sdk_plugin/android/libs/mobilekeys-android-sdk-release-8.1.0.aar
deleted file mode 100644
index fa823585..00000000
Binary files a/mobilekeys_sdk_plugin/android/libs/mobilekeys-android-sdk-release-8.1.0.aar and /dev/null differ
diff --git a/mobilekeys_sdk_plugin/android/libs/mobilekeys-android-sdk-release-8.1.2.aar b/mobilekeys_sdk_plugin/android/libs/mobilekeys-android-sdk-release-8.1.2.aar
new file mode 100644
index 00000000..92f1c227
Binary files /dev/null and b/mobilekeys_sdk_plugin/android/libs/mobilekeys-android-sdk-release-8.1.2.aar differ
diff --git a/mobilekeys_sdk_plugin/android/local.properties b/mobilekeys_sdk_plugin/android/local.properties
new file mode 100644
index 00000000..bc14d75f
--- /dev/null
+++ b/mobilekeys_sdk_plugin/android/local.properties
@@ -0,0 +1,8 @@
+## This file must *NOT* be checked into Version Control Systems,
+# as it contains information specific to your local configuration.
+#
+# Location of the SDK. This is only used by Gradle.
+# For customization when using a Version Control System, please read the
+# header note.
+#Fri Jan 10 14:59:51 CET 2025
+sdk.dir=/Users/mth/Library/Android/sdk