6177214e-ce7c-49e3-99de-ff9721b26f63 — Commit 7103981d
Changed files
comwell_key_app/assets/translations/da-DK.json | 4 +- comwell_key_app/assets/translations/en-US.json | 7 +- .../adyen/stored_payment_methods_response.g.dart | 6 +- .../.generated/services/models/bookings_dto.g.dart | 6 +- .../booking_details_repository.dart | 1 + .../lib/common/components/comwell_text_field.dart | 3 + .../components/get_a_phone_call_section.dart | 5 +- .../payment_cards/bloc/payment_cards_cubit.dart | 7 +- .../payment_cards/bloc/payment_cards_state.dart | 5 + .../lib/payment_cards/payment_cards_page.dart | 16 +- .../payment_cards/payment_cards_repository.dart | 2 +- .../pregistration/bloc/preregistration_cubit.dart | 97 +++++++++--- .../pregistration/components/information_card.dart | 7 +- .../pregistration/pages/prereg_address_page.dart | 108 +++++++++++++ .../pages/prereg_confirmation_page.dart | 169 +++++++++++++-------- .../pages/prereg_information_page.dart | 82 ---------- .../pregistration/pages/prereg_profile_page.dart | 88 +++++++++++ .../lib/pregistration/preregistration_flow.dart | 28 ++-- .../profile/components/profile_page_widget.dart | 28 ++-- .../components/intl_phone_field.dart | 11 +- .../profile_settings/profile_settings_page.dart | 6 +- .../adyen/stored_payment_methods_response.dart | 2 +- comwell_key_app/lib/services/api.dart | 3 +- comwell_key_app/lib/utils/phone_utils.dart | 13 ++ 24 files changed, 483 insertions(+), 221 deletions(-)
Diff
diff --git a/comwell_key_app/assets/translations/da-DK.json b/comwell_key_app/assets/translations/da-DK.json
index 37224147..368c5de4 100644
--- a/comwell_key_app/assets/translations/da-DK.json
+++ b/comwell_key_app/assets/translations/da-DK.json
@@ -245,5 +245,7 @@
"profile_error_name": "Fejl ved indlæsning af profiloplysninger",
"error": "Fejl",
"error_logout": "Der skete en fejl",
- "error_logout_subtitle": "Du har været logget ud. Log venligst ind igen."
+ "error_logout_subtitle": "Du har været logget ud. Log venligst ind igen.",
+ "edit": "Rediger",
+ "error_cards": "Fejl ved indlæsning af kort, prøv igen senere."
}
\ No newline at end of file
diff --git a/comwell_key_app/assets/translations/en-US.json b/comwell_key_app/assets/translations/en-US.json
index 64fa7100..a43eda3c 100644
--- a/comwell_key_app/assets/translations/en-US.json
+++ b/comwell_key_app/assets/translations/en-US.json
@@ -237,12 +237,15 @@
"share_booking": "Share booking",
"total_charge": "Total charge",
"early_checkin": "Early check-in",
- "payed": "PAYED",,
+ "payed": "PAYED",
"room_prefix": "Room {}",
"total_charge_value": "{} kr.",
"generic_error_profile_page": "An error occurred. Please try again later. Or logout and try again.",
"profile_error_name": "Failed to load profile information",
"error": "Error",
"error_logout": "There has been an error",
- "error_logout_subtitle": "Please log in again"
+ "error_logout_subtitle": "Please log in again",
+ "edit": "Edit",
+ "error_cards": "Failed to load cards, try again later"
+
}
diff --git a/comwell_key_app/lib/.generated/services/adyen/stored_payment_methods_response.g.dart b/comwell_key_app/lib/.generated/services/adyen/stored_payment_methods_response.g.dart
index 8fbae914..899c42ef 100644
--- a/comwell_key_app/lib/.generated/services/adyen/stored_payment_methods_response.g.dart
+++ b/comwell_key_app/lib/.generated/services/adyen/stored_payment_methods_response.g.dart
@@ -10,8 +10,8 @@ StoredPaymentsResponse _$StoredPaymentsResponseFromJson(Map json) =>
StoredPaymentsResponse(
merchantAccount: json['merchantAccount'] as String,
shopperReference: json['shopperReference'] as String,
- storedPaymentMethods: (json['storedPaymentMethods'] as List<dynamic>).map(
- (e) => StoredPaymentMethod.fromJson(
+ storedPaymentMethods: (json['storedPaymentMethods'] as List<dynamic>?)
+ ?.map((e) => StoredPaymentMethod.fromJson(
Map<String, dynamic>.from(e as Map))),
);
@@ -21,5 +21,5 @@ Map<String, dynamic> _$StoredPaymentsResponseToJson(
'merchantAccount': instance.merchantAccount,
'shopperReference': instance.shopperReference,
'storedPaymentMethods':
- instance.storedPaymentMethods.map((e) => e.toJson()).toList(),
+ instance.storedPaymentMethods?.map((e) => e.toJson()).toList(),
};
diff --git a/comwell_key_app/lib/.generated/services/models/bookings_dto.g.dart b/comwell_key_app/lib/.generated/services/models/bookings_dto.g.dart
index f0a66fd5..68206099 100644
--- a/comwell_key_app/lib/.generated/services/models/bookings_dto.g.dart
+++ b/comwell_key_app/lib/.generated/services/models/bookings_dto.g.dart
@@ -8,11 +8,11 @@ part of '../../../services/models/bookings_dto.dart';
BookingsDTO _$BookingsDTOFromJson(Map json) => BookingsDTO(
current: (json['current'] as List<dynamic>)
- .map((e) => BookingDTO.fromJson(Json.from(e as Map))),
+ .map((e) => BookingDTO.fromJson(Map<String, dynamic>.from(e as Map))),
past: (json['past'] as List<dynamic>)
- .map((e) => BookingDTO.fromJson(Json.from(e as Map))),
+ .map((e) => BookingDTO.fromJson(Map<String, dynamic>.from(e as Map))),
cancelled: (json['cancelled'] as List<dynamic>)
- .map((e) => BookingDTO.fromJson(Json.from(e as Map))),
+ .map((e) => BookingDTO.fromJson(Map<String, dynamic>.from(e as Map))),
);
Map<String, dynamic> _$BookingsDTOToJson(BookingsDTO instance) =>
diff --git a/comwell_key_app/lib/booking_details/booking_details_repository.dart b/comwell_key_app/lib/booking_details/booking_details_repository.dart
index 146ad959..9e4d148c 100644
--- a/comwell_key_app/lib/booking_details/booking_details_repository.dart
+++ b/comwell_key_app/lib/booking_details/booking_details_repository.dart
@@ -31,6 +31,7 @@ class BookingDetailsRepository {
return false;
}
+
Future<String?> doesInvitationCodeExist(String key) async {
return await secureStorage.read(key);
}
diff --git a/comwell_key_app/lib/common/components/comwell_text_field.dart b/comwell_key_app/lib/common/components/comwell_text_field.dart
index be2a94fe..7a560304 100644
--- a/comwell_key_app/lib/common/components/comwell_text_field.dart
+++ b/comwell_key_app/lib/common/components/comwell_text_field.dart
@@ -8,6 +8,7 @@ class ComwellTextField extends StatefulWidget {
final TextInputType? textInputType;
final TextEditingController controller;
final String? errorMessage;
+ final void Function(String)? onChanged;
const ComwellTextField({
super.key,
@@ -17,6 +18,7 @@ class ComwellTextField extends StatefulWidget {
required this.controller,
this.errorMessage,
this.textInputType,
+ this.onChanged,
});
@override
@@ -57,6 +59,7 @@ class ComwellTextFieldState extends State<ComwellTextField> {
controller: widget.controller,
focusNode: _focusNode,
keyboardType: widget.textInputType,
+ onChanged: widget.onChanged,
decoration: InputDecoration(
errorText: errorMessage,
errorStyle: Theme.of(context)
diff --git a/comwell_key_app/lib/contact/components/get_a_phone_call_section.dart b/comwell_key_app/lib/contact/components/get_a_phone_call_section.dart
index c3969c10..2618a80b 100644
--- a/comwell_key_app/lib/contact/components/get_a_phone_call_section.dart
+++ b/comwell_key_app/lib/contact/components/get_a_phone_call_section.dart
@@ -1,5 +1,6 @@
import 'package:comwell_key_app/profile_settings/components/intl_phone_field.dart';
import 'package:comwell_key_app/themes/light_theme.dart';
+import 'package:comwell_key_app/utils/phone_utils.dart';
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
@@ -13,6 +14,7 @@ class GetAPhoneCallSection extends StatelessWidget {
@override
Widget build(BuildContext context) {
final theme = Theme.of(context);
+ final (countryCode, phoneNumber) = getCountryCodeFromPhoneNumber('+4528960099');
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
@@ -27,7 +29,8 @@ class GetAPhoneCallSection extends StatelessWidget {
IntlPhoneField(
readOnly: true,
title: 'Telefonnummer',
- phoneNumber: '28960099',
+ phoneNumber: phoneNumber,
+ countryCode: countryCode,
controller: TextEditingController(),
),
const SizedBox(height: 16),
diff --git a/comwell_key_app/lib/payment_cards/bloc/payment_cards_cubit.dart b/comwell_key_app/lib/payment_cards/bloc/payment_cards_cubit.dart
index 362fc6f1..463c9fd5 100644
--- a/comwell_key_app/lib/payment_cards/bloc/payment_cards_cubit.dart
+++ b/comwell_key_app/lib/payment_cards/bloc/payment_cards_cubit.dart
@@ -32,7 +32,12 @@ class PaymentCardsCubit extends Cubit<PaymentCardsState> {
try {
final cards = await _paymentCardsRepository.getCards();
paymentConfigurations = await fetchPaymentConfiguration();
- emit(state.cardsFetched(cards));
+
+ if (cards.isEmpty) {
+ emit(state.cardsFetchedEmpty());
+ } else {
+ emit(state.cardsFetched(cards));
+ }
} catch (e) {
emit(state.cardsFetchedError());
}
diff --git a/comwell_key_app/lib/payment_cards/bloc/payment_cards_state.dart b/comwell_key_app/lib/payment_cards/bloc/payment_cards_state.dart
index ded62dd1..0958ec6d 100644
--- a/comwell_key_app/lib/payment_cards/bloc/payment_cards_state.dart
+++ b/comwell_key_app/lib/payment_cards/bloc/payment_cards_state.dart
@@ -21,6 +21,10 @@ class PaymentCardsState extends Equatable {
return _copyWith(cards: cards, isLoading: false);
}
+ PaymentCardsState cardsFetchedEmpty() {
+ return _copyWith(cards: [], isLoading: false, hasCards: false);
+ }
+
PaymentCardsState cardsFetchedError() =>
_copyWith(isLoading: false, hasError: true);
@@ -28,6 +32,7 @@ class PaymentCardsState extends Equatable {
Iterable<StoredPaymentMethod>? cards,
bool? isLoading,
bool? hasError,
+ bool? hasCards,
}) {
return PaymentCardsState._(
cards: cards ?? this.cards,
diff --git a/comwell_key_app/lib/payment_cards/payment_cards_page.dart b/comwell_key_app/lib/payment_cards/payment_cards_page.dart
index 818187e1..3f3c2130 100644
--- a/comwell_key_app/lib/payment_cards/payment_cards_page.dart
+++ b/comwell_key_app/lib/payment_cards/payment_cards_page.dart
@@ -23,12 +23,13 @@ class PaymentCardsPage extends StatelessWidget {
return const Center(child: CircularProgressIndicator());
}
if (cubit.state.hasError) {
- return const Center(child: Text('Error fetching cards'));
+ return Center(child: Text('error_cards'.tr(), style: Theme.of(context).textTheme.bodyMedium,));
}
- return Center(
- child: Padding(
- padding: const EdgeInsets.symmetric(horizontal: 16.0),
- child: Column(
+ return ListView(
+ children: [
+ Padding(
+ padding: const EdgeInsets.symmetric(horizontal: 16.0),
+ child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const SizedBox(height: 40),
@@ -69,9 +70,10 @@ class PaymentCardsPage extends StatelessWidget {
),
const SizedBox(height: 12),
const AddCard()
- ],
+ ],
+ ),
),
- ),
+ ],
);
});
}
diff --git a/comwell_key_app/lib/payment_cards/payment_cards_repository.dart b/comwell_key_app/lib/payment_cards/payment_cards_repository.dart
index 747d649b..28b07444 100644
--- a/comwell_key_app/lib/payment_cards/payment_cards_repository.dart
+++ b/comwell_key_app/lib/payment_cards/payment_cards_repository.dart
@@ -6,7 +6,7 @@ class PaymentCardsRepository {
Future<Iterable<StoredPaymentMethod>> getCards() async {
final cards = await _api.getPaymentMethods();
- return cards.storedPaymentMethods;
+ return cards?.storedPaymentMethods ?? [];
}
Future<void> removeCard(StoredPaymentMethod card) async {
diff --git a/comwell_key_app/lib/pregistration/bloc/preregistration_cubit.dart b/comwell_key_app/lib/pregistration/bloc/preregistration_cubit.dart
index cbb39b78..6fe41fa1 100644
--- a/comwell_key_app/lib/pregistration/bloc/preregistration_cubit.dart
+++ b/comwell_key_app/lib/pregistration/bloc/preregistration_cubit.dart
@@ -5,6 +5,8 @@ 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/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/utils/locator.dart';
@@ -13,6 +15,7 @@ import 'package:flutter/cupertino.dart';
class PreregistrationCubit extends Cubit<PreregistrationState> {
final _profileRepository = locator<ProfileRepository>();
+ final _profileSettingsRepository = locator<ProfileSettingsRepository>();
final _tracking = locator<ComwellTracking>();
final _preregistrationRepository = locator<PreregistrationRepository>();
// final _bookingDetailsBloc = locator<BookingDetailsBloc>();
@@ -22,7 +25,11 @@ class PreregistrationCubit extends Cubit<PreregistrationState> {
final addressTextController = TextEditingController();
final postalCodeTextController = TextEditingController();
final cityTextController = TextEditingController();
- final countryTextController = TextEditingController();
+ final firstNameTextController = TextEditingController();
+ final lastNameTextController = TextEditingController();
+ final emailTextController = TextEditingController();
+ final phoneNumberTextController = TextEditingController();
+ String selectedCountry = '';
PreregistrationPage get currentPage =>
PreregistrationPage.fromIndex(pageController.page?.toInt() ?? 0);
@@ -43,30 +50,66 @@ class PreregistrationCubit extends Cubit<PreregistrationState> {
addressTextController.text = user.address.street;
postalCodeTextController.text = user.address.zipCode;
cityTextController.text = user.address.city;
- countryTextController.text = user.address.country;
+ selectedCountry = user.address.country;
+ phoneNumberTextController.text = user.phoneNumber;
+
+ firstNameTextController.text = user.firstName;
+ lastNameTextController.text = user.lastName;
+ emailTextController.text = user.email;
+ phoneNumberTextController.text = user.phoneNumber;
+
+
+
emit(state.copyWith(loading: false, error: null, user: user));
} on Exception catch (e) {
emit(state.copyWith(error: e));
}
}
- void onInformationContinueClicked() {
- if (isAddressValid && isCityValid && isCountryValid) {
+ void onAddressContinueClicked() {
+
+ if (isAddressValid && isCityValid) {
+
+ final updatedUser = state.user!.copyWith(
+ address: Address(
+ street: addressTextController.text,
+ zipCode: postalCodeTextController.text,
+ city: cityTextController.text,
+ country: selectedCountry,
+ ));
+
+ emit(state.copyWith(user: updatedUser));
_navigateNextPage();
} else {
emit(state.copyWith(missingInformation: true));
}
}
+ void onProfileContinueClicked() {
+ final updatedUser = state.user!.copyWith(
+ firstName: firstNameTextController.text,
+ lastName: lastNameTextController.text,
+ phoneNumber: phoneNumberTextController.text);
+ emit(state.copyWith(user: updatedUser));
+ _navigateNextPage();
+ }
+
+ void onPaymentContinueClicked() {
+ _navigateNextPage();
+ }
+
void onContinueClicked() {
if (_isAnimating) return;
switch (currentPage) {
- case PreregistrationPage.information:
- onInformationContinueClicked();
+ case PreregistrationPage.profile:
+ onProfileContinueClicked();
+ break;
+ case PreregistrationPage.address:
+ onAddressContinueClicked();
+ break;
+ case PreregistrationPage.payment:
+ onPaymentContinueClicked();
break;
- // case PreregistrationPage.payment:
- // _onConfirmPressed();
- // break;
case PreregistrationPage.confirmation:
_onConfirmPressed();
break;
@@ -116,6 +159,7 @@ class PreregistrationCubit extends Cubit<PreregistrationState> {
final confirmationId = booking.confirmationId;
print("confirmationId=$confirmationId");
+ await _profileSettingsRepository.updateUser(state.user!);
final response =
await _preregistrationRepository.createPreregistration(confirmationId);
print("response=$response");
@@ -126,11 +170,15 @@ class PreregistrationCubit extends Cubit<PreregistrationState> {
}
void onEditProfileClicked() {
- // Not implemented
+ _navigateTo(PreregistrationPage.profile);
}
void onEditAddressClicked() {
- _navigateTo(PreregistrationPage.information);
+ _navigateTo(PreregistrationPage.address);
+ }
+
+ void onEditPaymentMethodCLickked() {
+ _navigateTo(PreregistrationPage.payment);
}
void onEditExtrasClicked() {
@@ -182,30 +230,31 @@ class PreregistrationCubit extends Cubit<PreregistrationState> {
addressTextController.dispose();
postalCodeTextController.dispose();
cityTextController.dispose();
- countryTextController.dispose();
pageController.dispose();
return super.close();
}
+
bool get isAddressValid => addressTextController.text.isNotEmpty;
- bool get isPostalCodeValid =>
- postalCodeTextController.text.isNotEmpty;
+ bool get isPostalCodeValid => postalCodeTextController.text.isNotEmpty;
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.profile:
+ return true;
+ case PreregistrationPage.address:
+ return isAddressValid ||
+ isPostalCodeValid ||
+ isCityValid;
+ case PreregistrationPage.payment:
+ return true;
case PreregistrationPage.confirmation:
return true;
- // case PreregistrationPage.payment:
- // return true;
}
}
@@ -213,12 +262,14 @@ class PreregistrationCubit extends Cubit<PreregistrationState> {
int page = pageController.page?.ceil() ?? 0;
final preregPage = PreregistrationPage.fromIndex(page);
switch (preregPage) {
- case PreregistrationPage.information:
+ case PreregistrationPage.profile:
+ return "generic_continue".tr();
+ case PreregistrationPage.address:
+ return "generic_continue".tr();
+ case PreregistrationPage.payment:
return "generic_continue".tr();
case PreregistrationPage.confirmation:
return "generic_confirm".tr();
- // case PreregistrationPage.payment:
- // return "generic_confirm".tr();
}
}
diff --git a/comwell_key_app/lib/pregistration/components/information_card.dart b/comwell_key_app/lib/pregistration/components/information_card.dart
index 3cfbde80..1b5a90eb 100644
--- a/comwell_key_app/lib/pregistration/components/information_card.dart
+++ b/comwell_key_app/lib/pregistration/components/information_card.dart
@@ -1,16 +1,19 @@
import 'package:comwell_key_app/themes/dark_theme.dart';
+import 'package:easy_localization/easy_localization.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
@@ -26,8 +29,8 @@ class InformationCard extends StatelessWidget {
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
- Text(title),
- TextButton(onPressed: onEditClick, child: const Text("Rediger"))
+ Text(title, style: titleStyle),
+ TextButton(onPressed: onEditClick, child: Text("edit".tr(), style: const TextStyle(decoration: TextDecoration.underline),))
],
),
const SizedBox(height: 40),
diff --git a/comwell_key_app/lib/pregistration/pages/prereg_address_page.dart b/comwell_key_app/lib/pregistration/pages/prereg_address_page.dart
new file mode 100644
index 00000000..9b7cc1f8
--- /dev/null
+++ b/comwell_key_app/lib/pregistration/pages/prereg_address_page.dart
@@ -0,0 +1,108 @@
+import 'package:comwell_key_app/common/components/comwell_text_field.dart';
+import 'package:comwell_key_app/pregistration/bloc/preregistration_cubit.dart';
+import 'package:comwell_key_app/pregistration/bloc/preregistration_state.dart';
+import 'package:comwell_key_app/themes/light_theme.dart';
+import 'package:country_code_picker/country_code_picker.dart';
+import 'package:easy_localization/easy_localization.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter_bloc/flutter_bloc.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>();
+ final state = cubit.state;
+ if (state.loading) {
+ return const Center(child: CircularProgressIndicator());
+ }
+ if (state.error != null) {
+ return const Center(child: Text("Error"));
+ }
+ final addressErrorMessage =
+ !cubit.isAddressValid && state.missingInformation
+ ? "generic_information_required".tr()
+ : null;
+ final postalCodeErrorMessage =
+ !cubit.isPostalCodeValid && state.missingInformation
+ ? "generic_information_required".tr()
+ : null;
+ final cityErrorMessage = !cubit.isCityValid && state.missingInformation
+ ? "generic_information_required".tr()
+ : null;
+ return ListView(
+ key: const PageStorageKey("information_form"),
+ children: [
+ const SizedBox(height: 40),
+ Text("preregistration_address_title".tr(),
+ style: Theme.of(context).textTheme.headlineLarge),
+ const SizedBox(height: 18),
+ Text("preregistration_address_subtitle".tr(),
+ style: Theme.of(context).textTheme.bodySmall),
+ const SizedBox(height: 40),
+ ComwellTextField(
+ key: const Key("address"),
+ fieldName: "preregistration_address_label_address".tr(),
+ initialValue: "",
+ readOnly: false,
+ errorMessage: addressErrorMessage,
+ controller: cubit.addressTextController,
+ onChanged: (value) {
+ cubit.addressTextController.text = value;
+ }),
+ const SizedBox(height: 12),
+ ComwellTextField(
+ fieldName: "preregistration_address_label_postal_code".tr(),
+ initialValue: "",
+ textInputType: TextInputType.number,
+ errorMessage: postalCodeErrorMessage,
+ readOnly: false,
+ controller: cubit.postalCodeTextController,
+ onChanged: (value) {
+ cubit.postalCodeTextController.text = value;
+
+ }),
+ const SizedBox(height: 12),
+ ComwellTextField(
+ fieldName: "preregistration_address_label_city".tr(),
+ initialValue: "",
+ readOnly: false,
+ errorMessage: cityErrorMessage,
+ controller: cubit.cityTextController,
+ onChanged: (value) {
+ cubit.cityTextController.text = value;
+
+ }),
+ 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: state.user?.address.country,
+ showFlag: true,
+ favorite: const ['DK', 'SE', 'NO', 'DE'],
+ showDropDownButton: true,
+ padding: const EdgeInsets.symmetric(horizontal: 16),
+ textStyle: Theme.of(context).textTheme.headlineSmall,
+ showCountryOnly: true,
+ showOnlyCountryWhenClosed: true,
+ onChanged: (CountryCode countryCode) {
+ cubit.selectedCountry = countryCode.name ?? '';
+ },
+ ),
+ ),
+ const SizedBox(height: 100),
+ ],
+ );
+ });
+ }
+}
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 7128a205..440f4808 100644
--- a/comwell_key_app/lib/pregistration/pages/prereg_confirmation_page.dart
+++ b/comwell_key_app/lib/pregistration/pages/prereg_confirmation_page.dart
@@ -1,5 +1,6 @@
import 'package:comwell_key_app/pregistration/bloc/preregistration_cubit.dart';
import 'package:comwell_key_app/pregistration/components/information_card.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';
@@ -12,6 +13,7 @@ class PreregConfirmationPage extends StatelessWidget {
final cubit = context.read<PreregistrationCubit>();
final state = cubit.state;
final user = state.user!;
+ final theme = Theme.of(context);
String extrasTitleText;
if (state.numOfExtras == 1) {
@@ -22,71 +24,114 @@ class PreregConfirmationPage extends StatelessWidget {
.tr(args: [state.numOfExtras.toString()]);
}
- return ListView(
- children: [
- const SizedBox(height: 40),
- Text("preregistration_confirmation_title".tr(),
- style: Theme.of(context).textTheme.headlineLarge),
- const SizedBox(height: 40),
- InformationCard(
- title: "preregistration_confirmation_profile_card_title".tr(),
- onEditClick: cubit.onEditProfileClicked,
- child: Column(
- crossAxisAlignment: CrossAxisAlignment.start,
- children: [
- Text(
- "${user.firstName} ${user.lastName}",
- style: Theme.of(context).textTheme.bodyMedium,
- ),
- Text(
- user.email,
- style: Theme.of(context).textTheme.bodyMedium,
- ),
- Text(
- "${user.addressCountry} ${user.phoneNumber}",
- style: Theme.of(context).textTheme.bodyMedium,
- ),
- ],
+ return SafeArea(
+ child: ListView(
+ children: [
+ const SizedBox(height: 16),
+ Text("preregistration_confirmation_title".tr(),
+ style: Theme.of(context).textTheme.headlineLarge),
+ const SizedBox(height: 16),
+ InformationCard(
+ title: "preregistration_confirmation_profile_card_title".tr(),
+ titleStyle: theme.textTheme.titleMedium,
+ 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!.address.country} ${state.user!.phoneNumber}",
+ style: Theme.of(context).textTheme.bodyMedium,
+ ),
+ ],
+ ),
),
- ),
- const SizedBox(height: 12),
- InformationCard(
- title: "preregistration_confirmation_address_card_title".tr(),
- onEditClick: cubit.onEditAddressClicked,
- child: Column(
- crossAxisAlignment: CrossAxisAlignment.start,
- children: [
- Text(
- user.address.street,
- style: Theme.of(context).textTheme.bodyMedium,
- ),
- Text(
- "${user.address.zipCode}, ${user.address.city}, ${user.address.country}",
- style: Theme.of(context).textTheme.bodyMedium,
- ),
- ],
+ const SizedBox(height: 12),
+ InformationCard(
+ title: "preregistration_confirmation_address_card_title".tr(),
+ titleStyle: theme.textTheme.titleMedium?.copyWith(
+ fontWeight: FontWeight.w500,
+ ),
+ onEditClick: cubit.onEditAddressClicked,
+ child: Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ Text(
+ state.user!.address.street,
+ style: theme.textTheme.bodyMedium,
+ ),
+ Text(
+ "${state.user!.address.zipCode}, ${state.user!.address.city}, ${state.user!.address.country}",
+ style: theme.textTheme.bodyMedium,
+ ),
+ ],
+ ),
),
- ),
- const SizedBox(height: 12),
- InformationCard(
- title: extrasTitleText,
- onEditClick: cubit.onEditExtrasClicked,
- child: Column(
- crossAxisAlignment: CrossAxisAlignment.start,
- children: [
- Text(
- "${state.extrasTotalPrice} kr.",
- style: Theme.of(context).textTheme.bodySmall,
- ),
- Text(
- "preregistration_confirmation_extras_card_subtitle".tr(),
- style: Theme.of(context).textTheme.bodyMedium,
- ),
- ],
+ const SizedBox(height: 12),
+ InformationCard(
+ title: "payment_card_profile_menu".tr(),
+ titleStyle: theme.textTheme.titleMedium?.copyWith(
+ fontWeight: FontWeight.w500,
+ ),
+ onEditClick: cubit.onPaymentContinueClicked,
+ child: Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ Row(
+ mainAxisAlignment: MainAxisAlignment.start,
+ children: [
+ Image.asset('assets/images/master.png',
+ width: 48, height: 48),
+ const SizedBox(width: 12),
+ Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ Text("${user.firstName} ${user.lastName}",
+ style: theme.textTheme.bodyMedium),
+ Text('•••• •••• •••• 1234',
+ style: theme.textTheme.bodyMedium),
+ const SizedBox(width: 8),
+ ],
+ ),
+ ],
+ ),
+ ],
+ ),
),
- ),
- const SizedBox(height: 40),
- ],
+ const SizedBox(height: 12),
+ InformationCard(
+ title: extrasTitleText,
+ titleStyle: theme.textTheme.titleMedium?.copyWith(
+ fontWeight: FontWeight.w500,
+ ),
+ onEditClick: cubit.onEditExtrasClicked,
+ child: Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ Text(
+ "${state.extrasTotalPrice} kr.",
+ style: theme.textTheme.titleLarge?.copyWith(
+ fontWeight: FontWeight.bold,
+ ),
+ ),
+ Text(
+ "preregistration_confirmation_extras_card_subtitle".tr(),
+ style: theme.textTheme.bodyMedium!
+ .copyWith(fontWeight: FontWeight.w400),
+ )
+ ],
+ ),
+ ),
+ const SizedBox(height: 40),
+ ],
+ ),
);
}
}
diff --git a/comwell_key_app/lib/pregistration/pages/prereg_information_page.dart b/comwell_key_app/lib/pregistration/pages/prereg_information_page.dart
deleted file mode 100644
index 6564dfbe..00000000
--- a/comwell_key_app/lib/pregistration/pages/prereg_information_page.dart
+++ /dev/null
@@ -1,82 +0,0 @@
-import 'package:comwell_key_app/common/components/comwell_text_field.dart';
-import 'package:comwell_key_app/pregistration/bloc/preregistration_cubit.dart';
-import 'package:comwell_key_app/pregistration/bloc/preregistration_state.dart';
-import 'package:easy_localization/easy_localization.dart';
-import 'package:flutter/material.dart';
-import 'package:flutter_bloc/flutter_bloc.dart';
-
-class PreregInformationPage extends StatelessWidget {
- const PreregInformationPage({super.key});
-
- @override
- Widget build(BuildContext context) {
- return BlocBuilder<PreregistrationCubit, PreregistrationState>(
- builder: (context, state) {
- final cubit = context.read<PreregistrationCubit>();
- final state = cubit.state;
- if (state.loading) {
- return const Center(child: CircularProgressIndicator());
- }
- if (state.error != null) {
- return const Center(child: Text("Error"));
- }
- final addressErrorMessage =
- !cubit.isAddressValid && state.missingInformation
- ? "generic_information_required".tr()
- : null;
- final postalCodeErrorMessage =
- !cubit.isPostalCodeValid && state.missingInformation
- ? "generic_information_required".tr()
- : null;
- final cityErrorMessage = !cubit.isCityValid && state.missingInformation
- ? "generic_information_required".tr()
- : null;
- final countryErrorMessage =
- !cubit.isCountryValid && state.missingInformation
- ? "generic_information_required".tr()
- : null;
- return ListView(
- key: const PageStorageKey("information_form"),
- children: [
- const SizedBox(height: 40),
- Text("preregistration_address_title".tr(),
- style: Theme.of(context).textTheme.headlineLarge),
- const SizedBox(height: 18),
- Text("preregistration_address_subtitle".tr(),
- style: Theme.of(context).textTheme.bodySmall),
- const SizedBox(height: 40),
- ComwellTextField(
- key: const Key("address"),
- fieldName: "preregistration_address_label_address".tr(),
- initialValue: "",
- readOnly: false,
- errorMessage: addressErrorMessage,
- controller: cubit.addressTextController),
- const SizedBox(height: 12),
- ComwellTextField(
- fieldName: "preregistration_address_label_postal_code".tr(),
- initialValue: "",
- textInputType: TextInputType.number,
- errorMessage: postalCodeErrorMessage,
- readOnly: false,
- controller: cubit.postalCodeTextController),
- const SizedBox(height: 12),
- ComwellTextField(
- fieldName: "preregistration_address_label_city".tr(),
- initialValue: "",
- readOnly: false,
- errorMessage: cityErrorMessage,
- controller: cubit.cityTextController),
- const SizedBox(height: 12),
- ComwellTextField(
- fieldName: "preregistration_address_label_country".tr(),
- initialValue: "",
- errorMessage: countryErrorMessage,
- readOnly: false,
- controller: cubit.countryTextController),
- const SizedBox(height: 100),
- ],
- );
- });
- }
-}
diff --git a/comwell_key_app/lib/pregistration/pages/prereg_profile_page.dart b/comwell_key_app/lib/pregistration/pages/prereg_profile_page.dart
new file mode 100644
index 00000000..2c7fb8cd
--- /dev/null
+++ b/comwell_key_app/lib/pregistration/pages/prereg_profile_page.dart
@@ -0,0 +1,88 @@
+import 'package:comwell_key_app/common/components/comwell_app_bar.dart';
+import 'package:comwell_key_app/profile_settings/components/comwell_text_field.dart';
+import 'package:comwell_key_app/profile_settings/components/intl_phone_field.dart';
+import 'package:comwell_key_app/pregistration/bloc/preregistration_cubit.dart';
+import 'package:comwell_key_app/pregistration/bloc/preregistration_state.dart';
+import 'package:comwell_key_app/themes/light_theme.dart';
+import 'package:comwell_key_app/utils/phone_utils.dart';
+import 'package:easy_localization/easy_localization.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter_bloc/flutter_bloc.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.loading) {
+ return const Center(child: CircularProgressIndicator());
+ } else if (state.user != null) {
+ return _buildProfilePage(theme, state, context);
+ } else {
+ return Center(
+ child: Text(
+ "generic_error".tr(),
+ style: theme.textTheme.headlineLarge,
+ ),
+ );
+ }
+ },
+ );
+ }
+
+ Widget _buildProfilePage(
+ ThemeData theme, PreregistrationState state, BuildContext context) {
+ final cubit = context.read<PreregistrationCubit>();
+ final (countryCode, phoneNumber) =
+ getCountryCodeFromPhoneNumber(state.user!.phoneNumber);
+
+ print("phoneNumber: $phoneNumber");
+
+ return ListView(children: [
+ Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ const SizedBox(height: 36),
+ Text(
+ "profile_settings".tr(),
+ style: theme.textTheme.headlineLarge,
+ textAlign: TextAlign.start,
+ ),
+ const SizedBox(height: 36),
+ ComwellTextField(
+ fieldName: "profile_settings_firstname".tr(),
+ initialValue: state.user!.firstName,
+ readOnly: false,
+ controller: cubit.firstNameTextController,
+ ),
+ const SizedBox(height: 8),
+ ComwellTextField(
+ fieldName: "profile_settings_lastname".tr(),
+ initialValue: state.user!.lastName,
+ readOnly: false,
+ controller: cubit.lastNameTextController,
+ ),
+ const SizedBox(height: 8),
+ ComwellTextField(
+ fieldName: "profile_settings_email".tr(),
+ initialValue: state.user!.email,
+ readOnly: true,
+ controller: cubit.emailTextController,
+ ),
+ const SizedBox(height: 8),
+ IntlPhoneField(
+ title: "profile_settings_phone".tr(),
+ phoneNumber: phoneNumber,
+ countryCode: countryCode,
+ controller: cubit.phoneNumberTextController,
+ readOnly: false,
+ onSubmitted: (_) {},
+ ),
+ ],
+ ),
+ ]);
+ }
+}
diff --git a/comwell_key_app/lib/pregistration/preregistration_flow.dart b/comwell_key_app/lib/pregistration/preregistration_flow.dart
index 5a9ed24a..aa77b857 100644
--- a/comwell_key_app/lib/pregistration/preregistration_flow.dart
+++ b/comwell_key_app/lib/pregistration/preregistration_flow.dart
@@ -5,15 +5,17 @@ import 'package:comwell_key_app/payment_cards/payment_cards_page.dart';
import 'package:comwell_key_app/pregistration/bloc/preregistration_state.dart';
import 'package:comwell_key_app/pregistration/bloc/preregistration_cubit.dart';
import 'package:comwell_key_app/pregistration/pages/prereg_confirmation_page.dart';
-import 'package:comwell_key_app/pregistration/pages/prereg_information_page.dart';
+import 'package:comwell_key_app/pregistration/pages/prereg_address_page.dart';
+import 'package:comwell_key_app/pregistration/pages/prereg_profile_page.dart';
import 'package:comwell_key_app/themes/dark_theme.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:go_router/go_router.dart';
enum PreregistrationPage {
- information,
- // payment,
+ profile,
+ address,
+ payment,
confirmation;
static PreregistrationPage fromIndex(int index) {
@@ -23,12 +25,14 @@ enum PreregistrationPage {
static Iterable<Widget> getPages(Key key) {
return PreregistrationPage.values.map((page) {
switch (page) {
- case PreregistrationPage.information:
- return PreregInformationPage(key: key);
- // case PreregistrationPage.payment:
- // return BlocProvider(
- // create: (context) => PaymentCardsCubit(),
- // child: const PaymentCardsPage());
+ case PreregistrationPage.profile:
+ return PreregProfilePage(key: key);
+ case PreregistrationPage.address:
+ return PreregAddressPage(key: key);
+ case PreregistrationPage.payment:
+ return BlocProvider(
+ create: (context) => PaymentCardsCubit(),
+ child: const PaymentCardsPage());
case PreregistrationPage.confirmation:
return PreregConfirmationPage(key: key);
}
@@ -48,15 +52,15 @@ class _PreregistrationFlowState extends State<PreregistrationFlow> {
@override
Widget build(BuildContext context) {
return BlocProvider(
- create: (context) => PreregistrationCubit(booking: widget.booking)..init(),
+ create: (context) =>
+ PreregistrationCubit(booking: widget.booking)..init(),
child: BlocConsumer<PreregistrationCubit, PreregistrationState>(
listener: (context, state) {},
builder: (context, state) {
final cubit = context.read<PreregistrationCubit>();
return Scaffold(
backgroundColor: Colors.white,
- appBar: const ComwellAppBar(
- ),
+ appBar: const ComwellAppBar(),
bottomNavigationBar: Builder(builder: (context) {
if (state.loading) return const SizedBox();
return Column(
diff --git a/comwell_key_app/lib/profile/components/profile_page_widget.dart b/comwell_key_app/lib/profile/components/profile_page_widget.dart
index 53810713..63d5ff98 100644
--- a/comwell_key_app/lib/profile/components/profile_page_widget.dart
+++ b/comwell_key_app/lib/profile/components/profile_page_widget.dart
@@ -43,7 +43,8 @@ class ProfilePageWidget extends StatelessWidget {
child: Column(
children: [
ComwellCard(
- content: CardContentWidget(cubit: cubit, isActive: isActive),
+ content:
+ CardContentWidget(cubit: cubit, isActive: isActive),
backgroundColor: isActive ? sandColor : sandColor[10]!),
],
),
@@ -190,19 +191,18 @@ class ProfilePageWidget extends StatelessWidget {
),
),
),
- const SizedBox(height: 16),
- FutureBuilder<String>(
- future: context.read<ProfileCubit>().getVersion(),
- builder: (context, snapshot) {
- if (snapshot.hasData) {
- return Text(snapshot.data!,
- style: TextStyle(color: Colors.grey[500]));
- }
- return const SizedBox.shrink();
- },
+ Expanded(
+ child: FutureBuilder<String>(
+ future: context.read<ProfileCubit>().getVersion(),
+ builder: (context, snapshot) {
+ if (snapshot.hasData) {
+ return Text(snapshot.data!,
+ style: TextStyle(color: Colors.grey[500]));
+ }
+ return const SizedBox.shrink();
+ },
+ ),
),
- const SizedBox(height: 20),
- const Spacer(),
],
),
),
@@ -211,6 +211,4 @@ class ProfilePageWidget extends StatelessWidget {
),
);
}
-
-
}
diff --git a/comwell_key_app/lib/profile_settings/components/intl_phone_field.dart b/comwell_key_app/lib/profile_settings/components/intl_phone_field.dart
index 8cf0226d..8f5ec5ad 100644
--- a/comwell_key_app/lib/profile_settings/components/intl_phone_field.dart
+++ b/comwell_key_app/lib/profile_settings/components/intl_phone_field.dart
@@ -6,6 +6,7 @@ import 'package:flutter/services.dart';
class IntlPhoneField extends StatefulWidget {
final String title;
final String phoneNumber;
+ final CountryCode countryCode;
final TextEditingController controller;
final bool readOnly;
final void Function(String)? onSubmitted;
@@ -13,6 +14,7 @@ class IntlPhoneField extends StatefulWidget {
const IntlPhoneField({
required this.title,
required this.phoneNumber,
+ required this.countryCode,
required this.controller,
this.readOnly = false,
this.onSubmitted,
@@ -44,6 +46,10 @@ class IntlPhoneFieldState extends State<IntlPhoneField> {
@override
Widget build(BuildContext context) {
final theme = Theme.of(context);
+ final countryCode = widget.countryCode.code;
+
+ print("countryCode: $countryCode");
+
return Form(
key: formKey,
child: Container(
@@ -56,7 +62,7 @@ class IntlPhoneFieldState extends State<IntlPhoneField> {
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
CountryCodePicker(
- initialSelection: "DK",
+ initialSelection: widget.countryCode.toString(),
showFlag: false,
favorite: const [
'SE',
@@ -84,7 +90,8 @@ class IntlPhoneFieldState extends State<IntlPhoneField> {
readOnly: widget.readOnly,
style: theme.textTheme.headlineSmall,
onSubmitted: widget.onSubmitted,
- keyboardType:const TextInputType.numberWithOptions(signed: true),
+ keyboardType:
+ const TextInputType.numberWithOptions(signed: true),
inputFormatters: [
FilteringTextInputFormatter.digitsOnly,
],
diff --git a/comwell_key_app/lib/profile_settings/profile_settings_page.dart b/comwell_key_app/lib/profile_settings/profile_settings_page.dart
index 97ed4044..5ca2d351 100644
--- a/comwell_key_app/lib/profile_settings/profile_settings_page.dart
+++ b/comwell_key_app/lib/profile_settings/profile_settings_page.dart
@@ -12,6 +12,7 @@ import 'package:comwell_key_app/profile_settings/model/address.dart';
import 'package:comwell_key_app/profile_settings/model/user.dart';
import 'package:comwell_key_app/themes/light_theme.dart';
import 'package:comwell_key_app/utils/locator.dart';
+import 'package:comwell_key_app/utils/phone_utils.dart';
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
@@ -56,7 +57,7 @@ class ProfileSettingsPage extends StatelessWidget {
Widget _buildProfileSettingsPage(
ThemeData theme, ProfileSettingsState state, BuildContext context) {
final cubit = context.read<ProfileSettingsCubit>();
-
+ final (countryCode, phoneNumber) = getCountryCodeFromPhoneNumber(state.user!.phoneNumber);
return Scaffold(
resizeToAvoidBottomInset: false,
backgroundColor: Colors.white,
@@ -102,7 +103,8 @@ class ProfileSettingsPage extends StatelessWidget {
const SizedBox(height: 8),
IntlPhoneField(
title: "profile_settings_phone".tr(),
- phoneNumber: state.user!.phoneNumber,
+ phoneNumber: phoneNumber,
+ countryCode: countryCode,
controller: cubit.phoneNumberController,
readOnly: false,
onSubmitted: (value) {
diff --git a/comwell_key_app/lib/services/adyen/stored_payment_methods_response.dart b/comwell_key_app/lib/services/adyen/stored_payment_methods_response.dart
index a53e2a07..399035fa 100644
--- a/comwell_key_app/lib/services/adyen/stored_payment_methods_response.dart
+++ b/comwell_key_app/lib/services/adyen/stored_payment_methods_response.dart
@@ -8,7 +8,7 @@ part '../../.generated/services/adyen/stored_payment_methods_response.g.dart';
class StoredPaymentsResponse {
final String merchantAccount;
final String shopperReference;
- final Iterable<StoredPaymentMethod> storedPaymentMethods;
+ final Iterable<StoredPaymentMethod>? storedPaymentMethods;
StoredPaymentsResponse({required this.merchantAccount, required this.shopperReference, required this.storedPaymentMethods});
diff --git a/comwell_key_app/lib/services/api.dart b/comwell_key_app/lib/services/api.dart
index 9acee15d..ce983fb4 100644
--- a/comwell_key_app/lib/services/api.dart
+++ b/comwell_key_app/lib/services/api.dart
@@ -34,8 +34,9 @@ class Api {
return BookingsDTO.fromJson(response.data!);
}
- Future<StoredPaymentsResponse> getPaymentMethods() async {
+ Future<StoredPaymentsResponse?> getPaymentMethods() async {
final response = await dio.get<Json>(ApiEndpoints.storedPaymentMethods);
+ print("response=$response");
return StoredPaymentsResponse.fromJson(response.data!);
}
diff --git a/comwell_key_app/lib/utils/phone_utils.dart b/comwell_key_app/lib/utils/phone_utils.dart
new file mode 100644
index 00000000..b365a998
--- /dev/null
+++ b/comwell_key_app/lib/utils/phone_utils.dart
@@ -0,0 +1,13 @@
+
+import 'package:country_code_picker/country_code_picker.dart';
+
+(CountryCode, String) getCountryCodeFromPhoneNumber(String phoneNumber) {
+ final countryCode = phoneNumber.length == 13
+ ? CountryCode.fromDialCode(phoneNumber.substring(0, 4))
+ : CountryCode.fromDialCode(phoneNumber.substring(0, 3));
+
+ final cleanedPhoneNumber = phoneNumber.substring(countryCode.dialCode!.length);
+
+ print("cleanedPhoneNumber: $cleanedPhoneNumber");
+ return (countryCode, cleanedPhoneNumber);
+}