6177214e-ce7c-49e3-99de-ff9721b26f63 — Commit 6ffc67ad

AuthorMikkel Thygesen<mikkelet@gmail.com>
Date2026-02-12 01:23:23 +0100
3770: improved auth

Changed files

.../authentication/authentication_repository.dart  |  11 +-
 .../booking_details/bloc/booking_details_bloc.dart | 125 +++++++-----
 .../bloc/booking_details_state.dart                |  78 ++++----
 .../booking_details/components/share_button.dart   | 181 ++++++++---------
 comwell_key_app/lib/comwell_app.dart               |  13 +-
 comwell_key_app/lib/data/remote/msal_service.dart  |  19 +-
 .../lib/my_booking/my_booking_page.dart            | 213 +++++++++++----------
 comwell_key_app/lib/overview/models/booking.dart   |  57 +++---
 comwell_key_app/lib/overview/overview_route.dart   |  39 +---
 .../lib/profile/cubit/profile_cubit.dart           |  50 +++--
 .../cubit/profile_settings_cubit.dart              |  39 ++--
 comwell_key_app/lib/services/http_client.dart      |   5 +-
 .../interceptors/response_handle_interceptor.dart  |  11 +-
 .../lib/services/mappers/booking_mapper.dart       |  77 ++++----
 .../booking_details_bloc_test.dart                 |  24 ++-
 .../profile_settings_cubit_test.dart               |  37 ++--
 16 files changed, 511 insertions(+), 468 deletions(-)

Diff

diff --git a/comwell_key_app/lib/authentication/authentication_repository.dart b/comwell_key_app/lib/authentication/authentication_repository.dart
index 3b6c9719..424d34d3 100644
--- a/comwell_key_app/lib/authentication/authentication_repository.dart
+++ b/comwell_key_app/lib/authentication/authentication_repository.dart
@@ -31,9 +31,12 @@ class AuthenticationRepository {
}
Future<bool> isLoggedIn() async {
- final token = await secureStorage.read(constants.accessToken);
- if (token == null) return false;
- return token.isNotEmpty;
+ try {
+ await _msalService.acquireTokenSilent();
+ return true;
+ } catch (_) {
+ return false;
+ }
}
Future<void> logOut() async {
@@ -55,6 +58,4 @@ class AuthenticationRepository {
value: 'true',
);
}
-
- Future<String?> get accessToken => _secureStorage.read(constants.accessToken);
}
diff --git a/comwell_key_app/lib/booking_details/bloc/booking_details_bloc.dart b/comwell_key_app/lib/booking_details/bloc/booking_details_bloc.dart
index ec48c5bd..1872bebf 100644
--- a/comwell_key_app/lib/booking_details/bloc/booking_details_bloc.dart
+++ b/comwell_key_app/lib/booking_details/bloc/booking_details_bloc.dart
@@ -16,32 +16,32 @@ import 'package:flutter/foundation.dart';
import 'package:seos_mobile_keys_plugin/app_usage_api.dart';
import '../../overview/models/booking.dart';
-import '../../utils/locator.dart';
import '../booking_details_repository.dart';
part 'booking_details_event.dart';
part 'booking_details_state.dart';
-class BookingDetailsBloc
- extends Bloc<BookingDetailsEvent, BookingDetailsState> {
+class BookingDetailsBloc extends Bloc<BookingDetailsEvent, BookingDetailsState> {
late Booking booking;
User? user;
Timer? _timer;
final BookingDetailsRepository bookingDetailsRepository;
final ProfileRepository profileRepository;
- final SeosRepository seosRepository = locator<SeosRepository>();
- Duration _remainingTime = Duration.zero;
+ final SeosRepository seosRepository;
final UpSalesRepository upSaleRepository;
final HouseKeepingRepository houseKeepingRepository;
- final ShareBookingRepository shareBookingRepository =
- locator<ShareBookingRepository>();
+ final ShareBookingRepository shareBookingRepository;
+ Duration _remainingTime = Duration.zero;
+
BookingDetailsBloc(
- this.booking, {
- required this.bookingDetailsRepository,
- required this.profileRepository,
- required this.upSaleRepository,
- required this.houseKeepingRepository,
+ this.bookingDetailsRepository,
+ this.profileRepository,
+ this.seosRepository,
+ this.upSaleRepository,
+ this.shareBookingRepository,
+ this.houseKeepingRepository, {
+ required this.booking,
}) : super(BookingDetailsState.initial(booking)) {
on<InitialEvent>((event, emit) async {
try {
@@ -63,16 +63,24 @@ class BookingDetailsBloc
on<PreregisterEvent>((event, emit) async {
emit(state.loading());
- await getBookingDetails(emit, booking.confirmationNumber,
- fetchRemote: true, hotelCode: booking.hotelCode);
+ await getBookingDetails(
+ emit,
+ booking.confirmationNumber,
+ fetchRemote: true,
+ hotelCode: booking.hotelCode,
+ );
await getUpSales(emit, fetchRemote: true);
emit(state.main());
});
on<CheckInEvent>((event, emit) async {
emit(state.loading());
- await getBookingDetails(emit, booking.confirmationNumber,
- fetchRemote: true, hotelCode: booking.hotelCode);
+ await getBookingDetails(
+ emit,
+ booking.confirmationNumber,
+ fetchRemote: true,
+ hotelCode: booking.hotelCode,
+ );
await checkMobileKeys(emit);
await getUpSales(emit, fetchRemote: true);
emit(state.main());
@@ -113,8 +121,12 @@ class BookingDetailsBloc
});
on<GetBookingDetailsEvent>((event, emit) async {
- await getBookingDetails(emit, event.hmsConfirmationNumber,
- hotelCode: booking.hotelCode, fetchRemote: event.fetchRemote);
+ await getBookingDetails(
+ emit,
+ event.hmsConfirmationNumber,
+ hotelCode: booking.hotelCode,
+ fetchRemote: event.fetchRemote,
+ );
});
on<GetUserEvent>((event, emit) async {
@@ -127,16 +139,19 @@ class BookingDetailsBloc
});
}
- Future<void> getUpSales(Emitter<BookingDetailsState> emit,
- {bool fetchRemote = false}) async {
+ Future<void> getUpSales(Emitter<BookingDetailsState> emit, {bool fetchRemote = false}) async {
try {
if (fetchRemote) {
final response = await upSaleRepository.getRemoteUpSales(
- booking.confirmationNumber, booking.hotelCode);
+ booking.confirmationNumber,
+ booking.hotelCode,
+ );
emit(state.getUpSales(response));
} else {
final response = await upSaleRepository.getUpSales(
- booking.confirmationNumber, booking.hotelCode);
+ booking.confirmationNumber,
+ booking.hotelCode,
+ );
emit(state.getUpSales(response));
}
} catch (e) {
@@ -146,19 +161,26 @@ class BookingDetailsBloc
}
Future<Booking> getBookingDetails(
- Emitter<BookingDetailsState> emit, String hmsConfirmationNumber,
- {bool fetchRemote = false, required String hotelCode}) async {
+ Emitter<BookingDetailsState> emit,
+ String hmsConfirmationNumber, {
+ bool fetchRemote = false,
+ required String hotelCode,
+ }) async {
emit(state.loading());
try {
if (fetchRemote) {
final bookingDetails = await bookingDetailsRepository.getRemoteBookingDetails(
- hmsConfirmationNumber, hotelCode);
+ hmsConfirmationNumber,
+ hotelCode,
+ );
booking = bookingDetails;
return booking;
} else {
user = await profileRepository.fetchProfileSettings();
final bookingDetails = await bookingDetailsRepository.getBookingDetails(
- hmsConfirmationNumber, hotelCode);
+ hmsConfirmationNumber,
+ hotelCode,
+ );
booking = bookingDetails;
return booking;
@@ -182,10 +204,10 @@ class BookingDetailsBloc
}
}
- Future<void> checkIfHouseKeepingOrdered(
- Emitter<BookingDetailsState> emit) async {
- final isHouseKeepingOrdered =
- await houseKeepingRepository.isHousesKeepingOrdered(booking.roomNumber);
+ Future<void> checkIfHouseKeepingOrdered(Emitter<BookingDetailsState> emit) async {
+ final isHouseKeepingOrdered = await houseKeepingRepository.isHousesKeepingOrdered(
+ booking.roomNumber,
+ );
if (isHouseKeepingOrdered) {
emit(state.houseKeepingOrdered());
@@ -193,20 +215,25 @@ class BookingDetailsBloc
}
Future<void> orderHouseKeeping(
- Emitter<BookingDetailsState> emit, List<String> selectedServices) async {
+ Emitter<BookingDetailsState> emit,
+ List<String> selectedServices,
+ ) async {
final housekeeping = Housekeeping.toJson(
- booking.hotelCode,
- booking.roomNumber,
- selectedServices
- .map((e) => HouseKeepingService.values
- .firstWhere((element) => element.name == e))
- .toList());
+ booking.hotelCode,
+ booking.roomNumber,
+ selectedServices
+ .map((e) => HouseKeepingService.values.firstWhere((element) => element.name == e))
+ .toList(),
+ );
await houseKeepingRepository.saveHouseKeepingOrdered(housekeeping);
emit(state.houseKeepingOrdered());
}
- Future<void> updateBooking(Emitter<BookingDetailsState> emit, Booking booking,
- UpdateBookingEvent event) async {
+ Future<void> updateBooking(
+ Emitter<BookingDetailsState> emit,
+ Booking booking,
+ UpdateBookingEvent event,
+ ) async {
try {
//TODO: add this when we have the backend
// await bookingDetailsRepository.updateBooking(event.booking);
@@ -220,8 +247,7 @@ class BookingDetailsBloc
_timer?.cancel();
_timer = Timer.periodic(
const Duration(seconds: 1),
- (_) => add(
- UpdateRemainingEvent(getCheckInTime().difference(DateTime.now()))),
+ (_) => add(UpdateRemainingEvent(getCheckInTime().difference(DateTime.now()))),
);
}
@@ -259,9 +285,11 @@ class BookingDetailsBloc
final now = DateTime.now();
final today = DateTime(now.year, now.month, now.day);
final checkInDate = DateTime(
- booking.startDate.year, booking.startDate.month, booking.startDate.day);
- final checkOutDate = DateTime(
- booking.endDate.year, booking.endDate.month, booking.endDate.day);
+ booking.startDate.year,
+ booking.startDate.month,
+ booking.startDate.day,
+ );
+ final checkOutDate = DateTime(booking.endDate.year, booking.endDate.month, booking.endDate.day);
if (checkInDate == checkOutDate) {
return false;
@@ -272,12 +300,9 @@ class BookingDetailsBloc
DateTime getCheckOutTime() => booking.endDate.add(const Duration(hours: 5));
- bool get isHouseKeepingTime =>
- booking.endDate.difference(booking.startDate).inDays >= 2;
+ bool get isHouseKeepingTime => booking.endDate.difference(booking.startDate).inDays >= 2;
- Future<void> getUser(Emitter<BookingDetailsState> emit,
- {bool fetchRemote = false}) async {
- user =
- await profileRepository.fetchProfileSettings(fetchRemote: fetchRemote);
+ Future<void> getUser(Emitter<BookingDetailsState> emit, {bool fetchRemote = false}) async {
+ user = await profileRepository.fetchProfileSettings(fetchRemote: fetchRemote);
}
}
diff --git a/comwell_key_app/lib/booking_details/bloc/booking_details_state.dart b/comwell_key_app/lib/booking_details/bloc/booking_details_state.dart
index de0409d2..fea90081 100644
--- a/comwell_key_app/lib/booking_details/bloc/booking_details_state.dart
+++ b/comwell_key_app/lib/booking_details/bloc/booking_details_state.dart
@@ -5,48 +5,61 @@ class BookingDetailsState extends Equatable {
final BookingDetailsStatus status;
final MobileKeysKey? key;
final List<MobileKeysKey> keys;
- final Iterable<Guest> guests;
+ final List<Guest> guests;
final Duration remainingTime;
final bool isLoading;
final UpSales? upSales;
final List<Upgrade> selectedUpSales;
- const BookingDetailsState._(
- {required this.status,
- required this.key,
- required this.keys,
- required this.isHouseKeepingOrdered,
- required this.guests,
- required this.remainingTime,
- required this.isLoading,
- this.upSales,
- required this.selectedUpSales});
+
+ const BookingDetailsState._({
+ required this.status,
+ required this.key,
+ required this.keys,
+ required this.isHouseKeepingOrdered,
+ required this.guests,
+ required this.remainingTime,
+ required this.isLoading,
+ this.upSales,
+ required this.selectedUpSales,
+ });
BookingDetailsState.initial(Booking booking)
- : this._(
- status: BookingDetailsStatus.initial,
- key: null,
- keys: [],
- isHouseKeepingOrdered: false,
- guests: booking.guests,
- remainingTime: Duration.zero,
- isLoading: false,
- upSales: null,
- selectedUpSales: []);
- BookingDetailsState setupError() =>
- copyWith(status: BookingDetailsStatus.setupError);
+ : this._(
+ status: BookingDetailsStatus.initial,
+ key: null,
+ keys: [],
+ isHouseKeepingOrdered: false,
+ guests: booking.guests,
+ remainingTime: Duration.zero,
+ isLoading: false,
+ upSales: null,
+ selectedUpSales: [],
+ );
+
+ BookingDetailsState setupError() => copyWith(status: BookingDetailsStatus.setupError);
+
BookingDetailsState updateKeys(List<MobileKeysKey> keys) =>
copyWith(status: BookingDetailsStatus.keysUpdated, keys: keys);
- BookingDetailsState houseKeepingOrdered() => copyWith(
- status: BookingDetailsStatus.houseKeepingOrdered,
- isHouseKeepingOrdered: true);
- BookingDetailsState updateGuests(Iterable<Guest> guests) =>
+
+ BookingDetailsState houseKeepingOrdered() =>
+ copyWith(status: BookingDetailsStatus.houseKeepingOrdered, isHouseKeepingOrdered: true);
+
+ BookingDetailsState updateGuests(List<Guest> guests) =>
copyWith(status: BookingDetailsStatus.guestsUpdated, guests: guests);
+
BookingDetailsState loading() => copyWith(status: BookingDetailsStatus.loading, isLoading: true);
+
BookingDetailsState loaded() => copyWith(status: BookingDetailsStatus.loaded, isLoading: false);
- BookingDetailsState updateRemainingTime(Duration remainingTime) => copyWith(remainingTime: remainingTime);
+
+ BookingDetailsState updateRemainingTime(Duration remainingTime) =>
+ copyWith(remainingTime: remainingTime);
+
BookingDetailsState main() => copyWith(status: BookingDetailsStatus.main, isLoading: false);
+
BookingDetailsState getUpSales(UpSales upSales) => copyWith(upSales: upSales);
+
BookingDetailsState upSalesError() => copyWith(status: BookingDetailsStatus.upSalesError);
+
@override
List<Object?> get props => [status, guests, isLoading, remainingTime, upSales];
@@ -55,7 +68,7 @@ class BookingDetailsState extends Equatable {
MobileKeysKey? key,
List<MobileKeysKey>? keys,
bool? isHouseKeepingOrdered,
- Iterable<Guest>? guests,
+ List<Guest>? guests,
bool? isLoading,
Duration? remainingTime,
UpSales? upSales,
@@ -65,13 +78,12 @@ class BookingDetailsState extends Equatable {
status: status ?? this.status,
key: key ?? this.key,
keys: keys ?? this.keys,
- isHouseKeepingOrdered:
- isHouseKeepingOrdered ?? this.isHouseKeepingOrdered,
+ isHouseKeepingOrdered: isHouseKeepingOrdered ?? this.isHouseKeepingOrdered,
guests: guests ?? this.guests,
isLoading: isLoading ?? this.isLoading,
remainingTime: remainingTime ?? this.remainingTime,
upSales: upSales ?? this.upSales,
- selectedUpSales: selectedUpSales ?? this.selectedUpSales
+ selectedUpSales: selectedUpSales ?? this.selectedUpSales,
);
}
@@ -91,5 +103,5 @@ enum BookingDetailsStatus {
houseKeepingOrdered,
loading,
loadingUpSales,
- upSalesError
+ upSalesError,
}
diff --git a/comwell_key_app/lib/booking_details/components/share_button.dart b/comwell_key_app/lib/booking_details/components/share_button.dart
index 5e5b0eb2..771c08de 100644
--- a/comwell_key_app/lib/booking_details/components/share_button.dart
+++ b/comwell_key_app/lib/booking_details/components/share_button.dart
@@ -12,18 +12,20 @@ import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:go_router/go_router.dart';
class ShareButton extends StatelessWidget {
- final Iterable<Guest> guests;
+ final List<Guest> guests;
final Color? buttonColor;
final double userButtonSize;
final double userButtonOverlap;
final bool isMyBooking;
- const ShareButton(
- {super.key,
- required this.guests,
- this.buttonColor,
- this.userButtonSize = 45,
- this.userButtonOverlap = 10,
- this.isMyBooking = false});
+
+ const ShareButton({
+ super.key,
+ required this.guests,
+ this.buttonColor,
+ this.userButtonSize = 45,
+ this.userButtonOverlap = 10,
+ this.isMyBooking = false,
+ });
@override
Widget build(BuildContext context) {
@@ -39,13 +41,12 @@ class ShareButton extends StatelessWidget {
Align(
alignment: Alignment.topLeft,
child: Padding(
- padding: EdgeInsets.only(
- left: isMyBooking ? 40 : 16.0, top: isMyBooking ? 24 : 16),
+ padding: EdgeInsets.only(left: isMyBooking ? 40 : 16.0, top: isMyBooking ? 24 : 16),
child: Stack(
children: [
Positioned(
- left: (numberOfUsers - 1) *
- (userButtonSize - userButtonOverlap) +
+ left:
+ (numberOfUsers - 1) * (userButtonSize - userButtonOverlap) +
userButtonSize -
userButtonOverlap,
child: SizedBox(
@@ -53,8 +54,7 @@ class ShareButton extends StatelessWidget {
height: userButtonSize,
child: ElevatedButton(
onPressed: () {
- context.pushNamed(AppRoutes.shareBooking.name,
- extra: booking);
+ context.pushNamed(AppRoutes.shareBooking.name, extra: booking);
},
style: ElevatedButton.styleFrom(
backgroundColor: buttonColor ?? sandColor[10],
@@ -63,9 +63,11 @@ class ShareButton extends StatelessWidget {
padding: EdgeInsets.zero,
),
child: Center(
- child: Icon(Icons.add,
- color: colorHeadlineText,
- size: isMyBooking ? 20 : 30),
+ child: Icon(
+ Icons.add,
+ color: colorHeadlineText,
+ size: isMyBooking ? 20 : 30,
+ ),
),
),
),
@@ -73,8 +75,7 @@ class ShareButton extends StatelessWidget {
...List.generate(
numberOfUsers,
(index) => Positioned(
- left: (numberOfUsers - 1 - index) *
- (userButtonSize - userButtonOverlap),
+ left: (numberOfUsers - 1 - index) * (userButtonSize - userButtonOverlap),
child: SizedBox(
width: userButtonSize,
height: userButtonSize,
@@ -84,20 +85,19 @@ class ShareButton extends StatelessWidget {
return;
}
final results = await _showGuestList(
- context,
- index,
- guests,
- "${booking.firstName} ${booking.lastName}");
+ context,
+ index,
+ guests,
+ "${booking.firstName} ${booking.lastName}",
+ );
- if (results is Iterable<String>) {
- final updatedBooking =
- booking.updateGuests(results);
+ if (results is List<String>) {
+ final updatedBooking = booking.updateGuests(results);
bloc.add(UpdateBookingEvent(updatedBooking));
}
},
style: ElevatedButton.styleFrom(
- backgroundColor:
- index % 2 == 0 ? sandColor : colorTertiary,
+ backgroundColor: index % 2 == 0 ? sandColor : colorTertiary,
elevation: 0,
shape: const CircleBorder(),
padding: EdgeInsets.zero,
@@ -124,8 +124,12 @@ class ShareButton extends StatelessWidget {
);
}
- Future<dynamic> _showGuestList(BuildContext context, int index,
- Iterable<Guest> guests, String booker) async {
+ Future<dynamic> _showGuestList(
+ BuildContext context,
+ int index,
+ List<Guest> guests,
+ String booker,
+ ) async {
final theme = Theme.of(context);
final selectedGuests = guests.map((e) => e.id.toString()).toList();
return showModalBottomSheet<dynamic>(
@@ -147,37 +151,39 @@ class ShareButton extends StatelessWidget {
),
child: Scaffold(
body: SizedBox(
- width: double.infinity,
- height: 450,
- child: Column(
- children: [
- Padding(
- padding: const EdgeInsets.symmetric(
- horizontal: 16.0, vertical: 8.0),
- child: Row(
- mainAxisAlignment: MainAxisAlignment.spaceBetween,
- children: [
- Text('handle_guests_title'.tr(),
- style: theme.textTheme.titleLarge?.copyWith(
- color: colorTertiary,
- fontWeight: FontWeight.w600,
- )),
- ElevatedButton(
- style: ElevatedButton.styleFrom(
- backgroundColor: sandColor[40],
- shape: const CircleBorder(),
- elevation: 0,
- minimumSize: const Size(40, 40)),
- child: const Icon(Icons.close,
- color: colorTertiary),
- onPressed: () {
- Navigator.pop(bottomSheetContext);
- },
+ width: double.infinity,
+ height: 450,
+ child: Column(
+ children: [
+ Padding(
+ padding: const EdgeInsets.symmetric(horizontal: 16.0, vertical: 8.0),
+ child: Row(
+ mainAxisAlignment: MainAxisAlignment.spaceBetween,
+ children: [
+ Text(
+ 'handle_guests_title'.tr(),
+ style: theme.textTheme.titleLarge?.copyWith(
+ color: colorTertiary,
+ fontWeight: FontWeight.w600,
),
- ],
- ),
+ ),
+ ElevatedButton(
+ style: ElevatedButton.styleFrom(
+ backgroundColor: sandColor[40],
+ shape: const CircleBorder(),
+ elevation: 0,
+ minimumSize: const Size(40, 40),
+ ),
+ child: const Icon(Icons.close, color: colorTertiary),
+ onPressed: () {
+ Navigator.pop(bottomSheetContext);
+ },
+ ),
+ ],
),
- Builder(builder: (context) {
+ ),
+ Builder(
+ builder: (context) {
if (state.isLoading) {
return const CircularProgressIndicator();
}
@@ -189,23 +195,30 @@ class ShareButton extends StatelessWidget {
);
}
return Expanded(
- child: GuestList(
- guests: guests,
- selectedGuests: selectedGuests,
- onGuestSelected: (Iterable<String> newSelection) {
- cubit.updateSelectedGuests(newSelection.map(
- (e) => Guest(
+ child: GuestList(
+ guests: guests,
+ selectedGuests: selectedGuests,
+ onGuestSelected: (Iterable<String> newSelection) {
+ cubit.updateSelectedGuests(
+ newSelection.map(
+ (e) => Guest(
id: int.parse(e),
firstName: e.split(' ')[0],
- lastName: e.split(' ')[1])));
- },
- onGuestRemoved: (int guestId) {
- cubit.removeGuests([guestId]);
- },
- ));
- })
- ],
- )),
+ lastName: e.split(' ')[1],
+ ),
+ ),
+ );
+ },
+ onGuestRemoved: (int guestId) {
+ cubit.removeGuests([guestId]);
+ },
+ ),
+ );
+ },
+ ),
+ ],
+ ),
+ ),
bottomNavigationBar: state.error != null
? null
: SafeArea(
@@ -223,11 +236,9 @@ class ShareButton extends StatelessWidget {
child: ElevatedButton(
onPressed: state.selectedGuests.isNotEmpty
? () async {
- final shouldRemove =
- await showDialog<bool>(
+ final shouldRemove = await showDialog<bool>(
context: bottomSheetContext,
- builder: (context) =>
- _buildRemoveGuestDialog(
+ builder: (context) => _buildRemoveGuestDialog(
context,
cubit,
bottomSheetContext,
@@ -235,17 +246,15 @@ class ShareButton extends StatelessWidget {
),
);
- if (shouldRemove == true &&
- context.mounted) {
+ if (shouldRemove == true && context.mounted) {
context.pop(state.selectedGuests);
}
}
: null,
style: ElevatedButton.styleFrom(
- backgroundColor:
- state.selectedGuests.isNotEmpty
- ? colorTertiary
- : const Color(0xffE0E0E0),
+ backgroundColor: state.selectedGuests.isNotEmpty
+ ? colorTertiary
+ : const Color(0xffE0E0E0),
minimumSize: const Size.fromHeight(50),
elevation: 0,
),
@@ -319,9 +328,7 @@ class ShareButton extends StatelessWidget {
minimumSize: const Size.fromHeight(50),
),
child: Text(
- selectedGuests.length > 1
- ? 'remove_guests'.tr()
- : 'remove_guest'.tr(),
+ selectedGuests.length > 1 ? 'remove_guests'.tr() : 'remove_guest'.tr(),
style: const TextStyle(
color: colorTertiary,
fontSize: 16,
diff --git a/comwell_key_app/lib/comwell_app.dart b/comwell_key_app/lib/comwell_app.dart
index 00177b4d..f32a2cd9 100644
--- a/comwell_key_app/lib/comwell_app.dart
+++ b/comwell_key_app/lib/comwell_app.dart
@@ -1,13 +1,10 @@
-import 'package:comwell_key_app/authentication/authentication_repository.dart';
import 'package:comwell_key_app/booking_details/booking_details_repository.dart';
import 'package:comwell_key_app/connection_state/connection_state_cubit.dart';
import 'package:comwell_key_app/key/bloc/key_bloc.dart';
import 'package:comwell_key_app/key/repository/key_repository.dart';
import 'package:comwell_key_app/overview/cubit/overview_cubit.dart';
import 'package:comwell_key_app/profile/cubit/profile_cubit.dart';
-import 'package:comwell_key_app/profile/profile_repository.dart';
import 'package:comwell_key_app/profile_settings/cubit/profile_settings_cubit.dart';
-import 'package:comwell_key_app/profile_settings/repostiory/profile_settings_repository.dart';
import 'package:comwell_key_app/routing/app_router.dart';
import 'package:comwell_key_app/themes/app_button_styles.dart';
import 'package:comwell_key_app/themes/app_textstyles.dart';
@@ -64,16 +61,16 @@ class ComwellApp extends StatelessWidget {
BlocProvider<ProfileCubit>(
lazy: false,
create: (BuildContext context) => ProfileCubit(
- profileRepository: locator<ProfileRepository>(),
- authenticationRepository: locator<AuthenticationRepository>(),
+ locator(),
+ locator(),
),
),
BlocProvider<ProfileSettingsCubit>(
lazy: false,
create: (BuildContext context) => ProfileSettingsCubit(
- profileRepository: locator<ProfileRepository>(),
- profileSettingsRepository: locator<ProfileSettingsRepository>(),
- authenticationRepository: locator<AuthenticationRepository>(),
+ locator(),
+ locator(),
+ locator(),
),
),
BlocProvider<PaymentCubit>(
diff --git a/comwell_key_app/lib/data/remote/msal_service.dart b/comwell_key_app/lib/data/remote/msal_service.dart
index 3c458c87..9f5f4e88 100644
--- a/comwell_key_app/lib/data/remote/msal_service.dart
+++ b/comwell_key_app/lib/data/remote/msal_service.dart
@@ -1,7 +1,7 @@
import 'package:comwell_key_app/.generated/assets/assets.gen.dart';
-import 'package:comwell_key_app/services/exceptions.dart';
import 'package:comwell_key_app/utils/env_utils.dart';
import 'package:comwell_key_app/utils/secure_storage.dart';
+import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_dotenv/flutter_dotenv.dart';
import 'package:msal_auth/msal_auth.dart';
@@ -12,9 +12,9 @@ class MSALService {
final SecureStorage _secureStorage;
final scopes = dotenv.ENTRA_API_URL.split(',');
+ final authorityUrl = dotenv.ENTRA_ID_AUTHORITY_URL;
late final PublicClientApplication msAuth;
late final String configFilePath;
- final String authorityUrl = dotenv.ENTRA_ID_AUTHORITY_URL;
MSALService(this._secureStorage);
@@ -45,30 +45,21 @@ class MSALService {
),
);
} catch (e) {
- print("qqq msauth init=$e");
+ debugPrint("qqq msauth init=$e");
rethrow;
}
}
Future<void> openAuth(Prompt prompt) async {
final response = await msAuth.acquireToken(scopes: scopes, prompt: prompt);
- print("qqq token=${response.accessToken}");
- print("qqq accId=${response.account.id}");
- print("qqq corrId=${response.correlationId}");
- print("qqq id=${response.idToken}");
-
await _secureStorage.write(constants.accessToken, response.accessToken);
- await _secureStorage.write(constants.identifier, response.account.id);
- await _secureStorage.write(constants.correlationId, response.correlationId ?? '');
}
- Future<void> acquireTokenSilent() async {
- final msalIdentifier = await _secureStorage.read(constants.identifier);
- if (msalIdentifier == null) throw UnauthorizedException();
+ Future<String> acquireTokenSilent() async {
final response = await msAuth.acquireTokenSilent(
scopes: scopes,
authority: authorityUrl,
);
- await _secureStorage.write(constants.accessToken, response.accessToken);
+ return response.accessToken;
}
}
diff --git a/comwell_key_app/lib/my_booking/my_booking_page.dart b/comwell_key_app/lib/my_booking/my_booking_page.dart
index bee48fa4..a96e6d30 100644
--- a/comwell_key_app/lib/my_booking/my_booking_page.dart
+++ b/comwell_key_app/lib/my_booking/my_booking_page.dart
@@ -10,7 +10,6 @@ import 'package:comwell_key_app/profile/profile_repository.dart';
import 'package:comwell_key_app/routing/app_routes.dart';
import 'package:comwell_key_app/services/mappers/booking_mapper.dart';
import 'package:comwell_key_app/themes/light_theme.dart';
-import 'package:comwell_key_app/up_sales/up_sales_repository.dart';
import 'package:comwell_key_app/utils/locator.dart';
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
@@ -21,6 +20,7 @@ import 'package:payment_plugin/presentation/app/bloc/payment_processing_state.da
class MyBookingPage extends StatelessWidget {
final Booking booking;
+
const MyBookingPage({super.key, required this.booking});
@override
@@ -28,71 +28,73 @@ class MyBookingPage extends StatelessWidget {
final theme = Theme.of(context);
return BlocBuilder<MyBookingCubit, MyBookingState>(
- builder: (context, state) {
-
-
- return BlocListener<PaymentCubit, PaymentProcessingState>(
- listener: (context, state) async {
- if (state is PaymentProcessingStateConfirmed) {
- await Future<void>.delayed(const Duration(seconds: 2));
- if (!context.mounted) return;
- Navigator.of(context).popUntil((route) =>
- route.settings.name == AppRoutes.bookingDetails.name);
- }
- },
- child: Builder(builder: (context) {
- return Scaffold(
- backgroundColor: Colors.white,
- appBar: const ComwellAppBar(
- shouldShowProfileButton: false,
- ),
- body: Stack(
- children: [
- SingleChildScrollView(
- child: Padding(
- padding: const EdgeInsets.all(16.0),
- child: Column(
- crossAxisAlignment: CrossAxisAlignment.start,
- children: [
- Text(
- 'my_booking'.tr(),
- style: theme.textTheme.titleLarge?.copyWith(
- fontWeight: FontWeight.bold,
- color: colorTertiary,
- ),
- ),
- const SizedBox(height: 8),
- Text(
- 'booking_reference'.tr(),
- style: theme.textTheme.bodySmall?.copyWith(
- color: colorHeadlineText,
- ),
- ),
- Text(
- booking.confirmationNumber,
- style: theme.textTheme.bodyMedium,
+ builder: (context, state) {
+ return BlocListener<PaymentCubit, PaymentProcessingState>(
+ listener: (context, state) async {
+ if (state is PaymentProcessingStateConfirmed) {
+ await Future<void>.delayed(const Duration(seconds: 2));
+ if (!context.mounted) return;
+ Navigator.of(
+ context,
+ ).popUntil((route) => route.settings.name == AppRoutes.bookingDetails.name);
+ }
+ },
+ child: Builder(
+ builder: (context) {
+ return Scaffold(
+ backgroundColor: Colors.white,
+ appBar: const ComwellAppBar(
+ shouldShowProfileButton: false,
+ ),
+ body: Stack(
+ children: [
+ SingleChildScrollView(
+ child: Padding(
+ padding: const EdgeInsets.all(16.0),
+ child: Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ Text(
+ 'my_booking'.tr(),
+ style: theme.textTheme.titleLarge?.copyWith(
+ fontWeight: FontWeight.bold,
+ color: colorTertiary,
+ ),
+ ),
+ const SizedBox(height: 8),
+ Text(
+ 'booking_reference'.tr(),
+ style: theme.textTheme.bodySmall?.copyWith(
+ color: colorHeadlineText,
+ ),
+ ),
+ Text(
+ booking.confirmationNumber,
+ style: theme.textTheme.bodyMedium,
+ ),
+ const SizedBox(height: 16),
+ const Divider(color: colorDivider),
+ _buildCheckInOutSection(theme),
+ const Divider(color: colorDivider),
+ _buildBookingDetails(theme),
+ const Divider(color: colorDivider),
+ _buildPaymentSection(theme),
+ const Divider(color: colorDivider),
+ _buildCancellationPolicy(theme),
+ const Divider(color: colorDivider),
+ const SizedBox(height: 100),
+ ],
),
- const SizedBox(height: 16),
- const Divider(color: colorDivider),
- _buildCheckInOutSection(theme),
- const Divider(color: colorDivider),
- _buildBookingDetails(theme),
- const Divider(color: colorDivider),
- _buildPaymentSection(theme),
- const Divider(color: colorDivider),
- _buildCancellationPolicy(theme),
- const Divider(color: colorDivider),
- const SizedBox(height: 100)
- ],
+ ),
),
- ),
+ ],
),
- ],
- ),
- );
- }),
- );
- });
+ );
+ },
+ ),
+ );
+ },
+ );
}
Widget _buildCheckInOutSection(ThemeData theme) {
@@ -102,15 +104,21 @@ class MyBookingPage extends StatelessWidget {
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
- Text('check_in'.tr(),
- style: theme.textTheme.bodySmall?.copyWith(
- color: colorHeadlineText,
- )),
+ Text(
+ 'check_in'.tr(),
+ style: theme.textTheme.bodySmall?.copyWith(
+ color: colorHeadlineText,
+ ),
+ ),
const SizedBox(height: 4),
- Text(DateFormat('d. MMM').format(booking.startDate),
- style: theme.textTheme.bodyMedium),
- Text(DateFormat('HH:mm').format(booking.startDate),
- style: theme.textTheme.bodyMedium),
+ Text(
+ DateFormat('d. MMM').format(booking.startDate),
+ style: theme.textTheme.bodyMedium,
+ ),
+ Text(
+ DateFormat('HH:mm').format(booking.startDate),
+ style: theme.textTheme.bodyMedium,
+ ),
],
),
),
@@ -119,10 +127,12 @@ class MyBookingPage extends StatelessWidget {
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
- Text('check_out'.tr(),
- style: theme.textTheme.bodySmall?.copyWith(
- color: colorHeadlineText,
- )),
+ Text(
+ 'check_out'.tr(),
+ style: theme.textTheme.bodySmall?.copyWith(
+ color: colorHeadlineText,
+ ),
+ ),
const SizedBox(height: 4),
Text(
DateFormat('d. MMM').format(booking.endDate),
@@ -144,10 +154,12 @@ class MyBookingPage extends StatelessWidget {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
- Text('booking_details'.tr(),
- style: theme.textTheme.bodySmall?.copyWith(
- color: colorHeadlineText,
- )),
+ Text(
+ 'booking_details'.tr(),
+ style: theme.textTheme.bodySmall?.copyWith(
+ color: colorHeadlineText,
+ ),
+ ),
Text(booking.toRoomType(), style: theme.textTheme.bodyMedium),
const SizedBox(height: 16),
const Divider(color: colorDivider),
@@ -158,8 +170,9 @@ class MyBookingPage extends StatelessWidget {
),
),
Text(
- '${booking.adults} ${booking.adults > 1 ? 'adults'.tr() : 'adult'.tr()}${booking.children > 0 ? ' | ${booking.children} ${booking.children > 1 ? 'children'.tr() : 'child'.tr()}' : ''}',
- style: theme.textTheme.bodyMedium),
+ '${booking.adults} ${booking.adults > 1 ? 'adults'.tr() : 'adult'.tr()}${booking.children > 0 ? ' | ${booking.children} ${booking.children > 1 ? 'children'.tr() : 'child'.tr()}' : ''}',
+ style: theme.textTheme.bodyMedium,
+ ),
const SizedBox(height: 8),
const Divider(color: colorDivider),
Text(
@@ -168,8 +181,7 @@ class MyBookingPage extends StatelessWidget {
color: colorHeadlineText,
),
),
- Text("${booking.firstName} ${booking.lastName}",
- style: theme.textTheme.bodyMedium),
+ Text("${booking.firstName} ${booking.lastName}", style: theme.textTheme.bodyMedium),
const SizedBox(height: 8),
const Divider(color: colorDivider),
Row(
@@ -193,11 +205,13 @@ class MyBookingPage extends StatelessWidget {
height: 70,
child: BlocProvider(
create: (context) => BookingDetailsBloc(
- booking,
- bookingDetailsRepository: locator<BookingDetailsRepository>(),
- profileRepository: locator<ProfileRepository>(),
- upSaleRepository: locator<UpSalesRepository>(),
- houseKeepingRepository: locator<HouseKeepingRepository>(),
+ booking: booking,
+ locator(),
+ locator(),
+ locator(),
+ locator(),
+ locator(),
+ locator(),
),
child: ShareButton(
isMyBooking: true,
@@ -231,10 +245,12 @@ class MyBookingPage extends StatelessWidget {
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
- Text('payment_method'.tr(),
- style: theme.textTheme.bodySmall?.copyWith(
- color: colorHeadlineText,
- )),
+ Text(
+ 'payment_method'.tr(),
+ style: theme.textTheme.bodySmall?.copyWith(
+ color: colorHeadlineText,
+ ),
+ ),
const SizedBox(width: 8),
//TODO: add card number when we can add it through the website
Text('•••• •••• •••• 1234', style: theme.textTheme.bodyMedium),
@@ -247,13 +263,14 @@ class MyBookingPage extends StatelessWidget {
const SizedBox(height: 16),
const Divider(color: colorDivider),
const SizedBox(height: 8),
- Text('payment_date'.tr(),
- style: theme.textTheme.bodySmall?.copyWith(
- color: colorHeadlineText,
- )),
+ Text(
+ 'payment_date'.tr(),
+ style: theme.textTheme.bodySmall?.copyWith(
+ color: colorHeadlineText,
+ ),
+ ),
const SizedBox(height: 4),
- Text(DateFormat('d. MMM').format(booking.bookingDate),
- style: theme.textTheme.bodyMedium),
+ Text(DateFormat('d. MMM').format(booking.bookingDate), style: theme.textTheme.bodyMedium),
const SizedBox(height: 16),
],
);
diff --git a/comwell_key_app/lib/overview/models/booking.dart b/comwell_key_app/lib/overview/models/booking.dart
index 84f8e3b1..070a3f14 100644
--- a/comwell_key_app/lib/overview/models/booking.dart
+++ b/comwell_key_app/lib/overview/models/booking.dart
@@ -22,7 +22,7 @@ class Booking extends Equatable {
final int children;
final DateTime bookingDate;
final bool digitalCard;
- final Iterable<Guest> guests;
+ final List<Guest> guests;
final num? balance;
final bool isPrimaryGuest;
final String? maskedCardNumber;
@@ -50,7 +50,7 @@ class Booking extends Equatable {
required this.balance,
required this.isPrimaryGuest,
required this.maskedCardNumber,
- Iterable<Guest>? guests,
+ List<Guest>? guests,
required this.addOnItems,
}) : guests = guests ?? [];
@@ -61,24 +61,24 @@ class Booking extends Equatable {
@override
List<Object?> get props => [
- id,
- roomNumber,
- startDate,
- endDate,
- image,
- hotelName,
- roomType,
- children,
- adults,
- hotelCode,
- bookingDate,
- guests,
- balance,
- isPrimaryGuest,
- maskedCardNumber,
- reservationStatus,
- addOnItems,
- ];
+ id,
+ roomNumber,
+ startDate,
+ endDate,
+ image,
+ hotelName,
+ roomType,
+ children,
+ adults,
+ hotelCode,
+ bookingDate,
+ guests,
+ balance,
+ isPrimaryGuest,
+ maskedCardNumber,
+ reservationStatus,
+ addOnItems,
+ ];
Booking copyWith({
String? id,
@@ -101,7 +101,7 @@ class Booking extends Equatable {
DateTime? bookingDate,
PaymentDetails? paymentDetails,
String? confirmationNumber,
- Iterable<Guest>? guests,
+ List<Guest>? guests,
num? totalCharge,
List<BookingAddonItem>? addOnItems,
}) {
@@ -114,7 +114,7 @@ class Booking extends Equatable {
image: image ?? this.image,
hotelName: hotelName ?? this.hotelName,
hotelCode: hotelCode ?? this.hotelCode,
- firstName: firstName,
+ firstName: firstName,
lastName: lastName,
bookerFirstName: bookerFirstName ?? this.bookerFirstName,
bookerLastName: bookerLastName ?? this.bookerLastName,
@@ -132,10 +132,12 @@ class Booking extends Equatable {
);
}
- Booking updateGuests(Iterable<String> guestNames) {
- final updatedGuests = guests.where((guest) =>
- !guestNames.contains(guest.firstName) &&
- !guestNames.contains(guest.lastName));
+ Booking updateGuests(List<String> guestNames) {
+ final updatedGuests = guests
+ .where(
+ (guest) => !guestNames.contains(guest.firstName) && !guestNames.contains(guest.lastName),
+ )
+ .toList();
return copyWith(guests: updatedGuests);
}
@@ -155,7 +157,8 @@ enum ReservationStatus {
return ReservationStatus.newreservation;
}
final status = ReservationStatus.values.firstWhere(
- (status) => status.name.toLowerCase() == value.toLowerCase());
+ (status) => status.name.toLowerCase() == value.toLowerCase(),
+ );
return status;
}
}
diff --git a/comwell_key_app/lib/overview/overview_route.dart b/comwell_key_app/lib/overview/overview_route.dart
index bbf04d50..e5016650 100644
--- a/comwell_key_app/lib/overview/overview_route.dart
+++ b/comwell_key_app/lib/overview/overview_route.dart
@@ -1,29 +1,21 @@
import 'package:comwell_key_app/booking_details/bloc/booking_details_bloc.dart';
import 'package:comwell_key_app/booking_details/booking_details_page.dart';
-import 'package:comwell_key_app/booking_details/booking_details_repository.dart';
import 'package:comwell_key_app/connection_state/connection_state_listener.dart';
-import 'package:comwell_key_app/housekeeping/housekeeping_repository.dart';
import 'package:comwell_key_app/key/key_page.dart';
import 'package:comwell_key_app/overview/models/booking.dart';
import 'package:comwell_key_app/overview/past_cancelled_booking_detail_page.dart';
-import 'package:comwell_key_app/profile_settings/cubit/profile_settings_cubit.dart';
-import 'package:comwell_key_app/up_sales/up_sales_repository.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:go_router/go_router.dart';
-import '../authentication/authentication_repository.dart';
-import '../profile/cubit/profile_cubit.dart';
import '../profile/profile_page.dart';
-import '../profile/profile_repository.dart';
import '../profile_settings/components/change_password_modal.dart';
import '../profile_settings/profile_settings_page.dart';
-import '../profile_settings/repostiory/profile_settings_repository.dart';
import '../routing/app_routes.dart';
import '../utils/locator.dart';
import 'overview_page.dart';
-RouteBase get overviewRoute => GoRoute(
+RouteBase overviewRoute = GoRoute(
path: AppRoutes.overview,
pageBuilder: (context, state) {
return const NoTransitionPage(
@@ -37,27 +29,14 @@ RouteBase get overviewRoute => GoRoute(
path: "profile",
name: AppRoutes.profile.name,
builder: (context, state) {
- return BlocProvider<ProfileCubit>(
- create: (BuildContext context) => ProfileCubit(
- profileRepository: locator<ProfileRepository>(),
- authenticationRepository: locator<AuthenticationRepository>(),
- )..init(),
- child: const ProfilePage(), //mobileKey: key);
- );
+ return const ProfilePage();
},
routes: [
GoRoute(
path: "profile_settings",
name: AppRoutes.profileSettings.name,
builder: (context, state) {
- return BlocProvider<ProfileSettingsCubit>(
- create: (BuildContext context) => ProfileSettingsCubit(
- profileRepository: locator<ProfileRepository>(),
- profileSettingsRepository: locator<ProfileSettingsRepository>(),
- authenticationRepository: locator<AuthenticationRepository>(),
- )..init(),
- child: const ProfileSettingsPage(),
- );
+ return const ProfileSettingsPage();
},
routes: [
GoRoute(
@@ -88,11 +67,13 @@ RouteBase get overviewRoute => GoRoute(
final booking = state.extra as Booking;
return BlocProvider<BookingDetailsBloc>(
create: (BuildContext context) => BookingDetailsBloc(
- booking,
- bookingDetailsRepository: locator<BookingDetailsRepository>(),
- profileRepository: locator<ProfileRepository>(),
- upSaleRepository: locator<UpSalesRepository>(),
- houseKeepingRepository: locator<HouseKeepingRepository>(),
+ booking: booking,
+ locator(),
+ locator(),
+ locator(),
+ locator(),
+ locator(),
+ locator(),
),
child: const BookingDetailsPage(),
);
diff --git a/comwell_key_app/lib/profile/cubit/profile_cubit.dart b/comwell_key_app/lib/profile/cubit/profile_cubit.dart
index d517bbde..84f6139a 100644
--- a/comwell_key_app/lib/profile/cubit/profile_cubit.dart
+++ b/comwell_key_app/lib/profile/cubit/profile_cubit.dart
@@ -9,18 +9,24 @@ import 'package:package_info_plus/package_info_plus.dart';
part 'profile_state.dart';
class ProfileCubit extends Cubit<ProfileState> {
- final ProfileRepository profileRepository;
- final AuthenticationRepository authenticationRepository;
+ final ProfileRepository _profileRepository;
+ final AuthenticationRepository _authenticationRepository;
+
+ ProfileCubit(
+ this._profileRepository,
+ this._authenticationRepository,
+ ) : super(
+ const ProfileState(
+ isLoading: false,
+ user: null,
+ error: null,
+ isToSAccepted: false,
+ isNewsletterAccepted: false,
+ ),
+ ) {
+ init();
+ }
- ProfileCubit({
- required this.profileRepository,
- required this.authenticationRepository,
- }) : super(const ProfileState(
- isLoading: false,
- user: null,
- error: null,
- isToSAccepted: false,
- isNewsletterAccepted: false));
void sendPageViewEvent() async {
await FirebaseAnalytics.instance.logScreenView(
screenName: 'Profile',
@@ -34,29 +40,35 @@ class ProfileCubit extends Cubit<ProfileState> {
}
void logOutPressed() {
- authenticationRepository.logOut();
- emit(const ProfileState(
+ _authenticationRepository.logOut();
+ emit(
+ const ProfileState(
isLoading: false,
user: null,
error: null,
isToSAccepted: false,
- isNewsletterAccepted: false));
+ isNewsletterAccepted: false,
+ ),
+ );
}
void deleteAllInfoOnLogOut() async {
- emit(const ProfileState(
+ emit(
+ const ProfileState(
isLoading: false,
user: null,
error: null,
isToSAccepted: false,
- isNewsletterAccepted: false));
+ isNewsletterAccepted: false,
+ ),
+ );
}
void init() async {
emit(const ProfileState(isLoading: true, user: null, error: null));
try {
- final user = await profileRepository.fetchProfileSettings();
+ final user = await _profileRepository.fetchProfileSettings();
sendPageViewEvent();
if (!isClosed) emit(ProfileState(user: user, isLoading: false));
} catch (e) {
@@ -67,7 +79,7 @@ class ProfileCubit extends Cubit<ProfileState> {
void fetchRemoteProfile() async {
emit(const ProfileState(isLoading: true, user: null, error: null));
try {
- final user = await profileRepository.fetchProfileSettings(fetchRemote: true);
+ final user = await _profileRepository.fetchProfileSettings(fetchRemote: true);
if (!isClosed) emit(ProfileState(user: user, isLoading: false));
} catch (e) {
@@ -97,7 +109,7 @@ class ProfileCubit extends Cubit<ProfileState> {
Future<dynamic> onComwellClubSignupClick(User user) async {
try {
emit(const ProfileState(isLoading: true, user: null, error: null));
- User updatedUser = await profileRepository.signupForComwellClub(user);
+ User updatedUser = await _profileRepository.signupForComwellClub(user);
emit(ProfileState(user: updatedUser, isLoading: false, error: null));
return updatedUser;
} catch (e) {
diff --git a/comwell_key_app/lib/profile_settings/cubit/profile_settings_cubit.dart b/comwell_key_app/lib/profile_settings/cubit/profile_settings_cubit.dart
index 764d15f6..926cebc8 100644
--- a/comwell_key_app/lib/profile_settings/cubit/profile_settings_cubit.dart
+++ b/comwell_key_app/lib/profile_settings/cubit/profile_settings_cubit.dart
@@ -14,9 +14,9 @@ import 'package:flutter/material.dart';
part 'profile_settings_state.dart';
class ProfileSettingsCubit extends Cubit<ProfileSettingsState> {
- final ProfileRepository profileRepository;
- final ProfileSettingsRepository profileSettingsRepository;
- final AuthenticationRepository authenticationRepository;
+ final ProfileRepository _profileRepository;
+ final ProfileSettingsRepository _profileSettingsRepository;
+ final AuthenticationRepository _authenticationRepository;
final TextEditingController firstNameController = TextEditingController();
final TextEditingController lastNameController = TextEditingController();
final TextEditingController phoneNumberController = TextEditingController();
@@ -25,20 +25,17 @@ class ProfileSettingsCubit extends Cubit<ProfileSettingsState> {
String? phoneNumber;
ProfileSettingsCubit(
- {required this.profileRepository,
- required this.profileSettingsRepository,
- required this.authenticationRepository,
- firstNameController,
- lastNameController,
- phoneNumberController})
- : super(const ProfileSettingsState.initial());
+ this._profileRepository,
+ this._profileSettingsRepository,
+ this._authenticationRepository,
+ ) : super(const ProfileSettingsState.initial()) {
+ init();
+ }
void init() async {
emit(const ProfileSettingsState(isLoading: true, user: null, error: null));
try {
- final user = await profileRepository.fetchProfileSettings();
-
-
+ final user = await _profileRepository.fetchProfileSettings();
countryCode = getCountryCodeFromPhoneNumber(user.phoneNumber).$1;
phoneNumber = getCountryCodeFromPhoneNumber(user.phoneNumber).$2;
@@ -51,7 +48,6 @@ class ProfileSettingsCubit extends Cubit<ProfileSettingsState> {
phoneNumberController.text = phoneNumber!;
-
emit(ProfileSettingsState(isLoading: false, user: user, error: null));
} catch (e) {
emit(ProfileSettingsState(isLoading: false, user: null, error: Error()));
@@ -60,14 +56,12 @@ class ProfileSettingsCubit extends Cubit<ProfileSettingsState> {
void deleteProfile() async {
try {
- await profileSettingsRepository.deleteProfile();
+ await _profileSettingsRepository.deleteProfile();
locator<ComwellTracking>().trackEvent('delete_profile');
- await authenticationRepository.logOut();
- emit(const ProfileSettingsState(
- isDeleted: true, isLoading: false, user: null, error: null));
+ await _authenticationRepository.logOut();
+ emit(const ProfileSettingsState(isDeleted: true, isLoading: false, user: null, error: null));
} catch (e) {
- emit(ProfileSettingsState(
- isDeleted: false, isLoading: false, user: null, error: Error()));
+ emit(ProfileSettingsState(isDeleted: false, isLoading: false, user: null, error: Error()));
}
}
@@ -86,8 +80,7 @@ class ProfileSettingsCubit extends Cubit<ProfileSettingsState> {
void updateProfile() async {
emit(ProfileSettingsState(isLoading: true, user: state.user, error: null));
try {
- final phoneNumber = concatCountryCodeAndPhoneNumber(
- countryCode!, phoneNumberController.text);
+ final phoneNumber = concatCountryCodeAndPhoneNumber(countryCode!, phoneNumberController.text);
final updatedUser = state.user!.copyWith(
id: state.user!.id,
@@ -104,7 +97,7 @@ class ProfileSettingsCubit extends Cubit<ProfileSettingsState> {
isClubMember: state.user!.isClubMember,
);
- await profileSettingsRepository.updateUser(updatedUser);
+ await _profileSettingsRepository.updateUser(updatedUser);
emit(ProfileSettingsState(isLoading: false, user: updatedUser, error: null));
} catch (e) {
debugPrint("error in cubit: $e");
diff --git a/comwell_key_app/lib/services/http_client.dart b/comwell_key_app/lib/services/http_client.dart
index 51065b12..d67b6fbc 100644
--- a/comwell_key_app/lib/services/http_client.dart
+++ b/comwell_key_app/lib/services/http_client.dart
@@ -22,10 +22,7 @@ class ComwellHttpClient {
),
);
dio.interceptors.add(
- ResponseHandleInterceptor(
- locator.get(),
- locator.get(),
- ),
+ ResponseHandleInterceptor(locator.get()),
);
if (kDebugMode) dio.interceptors.add(PrettyDioLogger(requestHeader: true));
return dio;
diff --git a/comwell_key_app/lib/services/interceptors/response_handle_interceptor.dart b/comwell_key_app/lib/services/interceptors/response_handle_interceptor.dart
index 51b4a13c..485aec58 100644
--- a/comwell_key_app/lib/services/interceptors/response_handle_interceptor.dart
+++ b/comwell_key_app/lib/services/interceptors/response_handle_interceptor.dart
@@ -6,16 +6,14 @@ import 'package:comwell_key_app/utils/locator.dart';
import 'package:comwell_key_app/utils/secure_storage.dart';
import 'package:dio/dio.dart';
import 'package:flutter_dotenv/flutter_dotenv.dart';
-import 'package:comwell_key_app/common/const.dart' as constants;
import 'package:go_router/go_router.dart';
import 'package:flutter/material.dart';
import 'package:msal_auth/msal_auth.dart';
class ResponseHandleInterceptor extends Interceptor {
- final SecureStorage _secureStorage;
final MSALService _msalService;
- ResponseHandleInterceptor(this._secureStorage, this._msalService);
+ ResponseHandleInterceptor(this._msalService);
BuildContext? get context {
final navigatorKey = locator<GlobalKey<NavigatorState>>();
@@ -24,9 +22,8 @@ class ResponseHandleInterceptor extends Interceptor {
Future<void> checkAuth(RequestOptions requestOptions) async {
try {
- await _msalService.acquireTokenSilent();
- final accessToken = await _secureStorage.read(constants.accessToken);
- requestOptions.headers['Authorization'] = accessToken!;
+ final accessToken = await _msalService.acquireTokenSilent();
+ requestOptions.headers['Authorization'] = accessToken;
} catch (e, _) {
debugPrint("checkAuthError=$e");
throw UnauthorizedException();
@@ -67,7 +64,7 @@ class ResponseHandleInterceptor extends Interceptor {
final response = err.response;
if (response == null) {
- debugPrint('Error: No response received - ${_extractErrorMessage}');
+ debugPrint('Error: No response received');
return handler.next(err);
}
debugPrint('Error: ${_extractErrorMessage(response.data, "No data")}');
diff --git a/comwell_key_app/lib/services/mappers/booking_mapper.dart b/comwell_key_app/lib/services/mappers/booking_mapper.dart
index eee6f5ee..146cd756 100644
--- a/comwell_key_app/lib/services/mappers/booking_mapper.dart
+++ b/comwell_key_app/lib/services/mappers/booking_mapper.dart
@@ -10,11 +10,13 @@ extension BookingDTOMapper on BookingDTO {
Booking toBooking() {
final startDate = DateTime.parse(dayIn);
final endDate = DateTime.parse(dayOut);
- final mappedGuests = guests.map((guest) => Guest(
- firstName: guest.firstName,
- lastName: guest.lastName,
- id: guest.id,
- ));
+ final mappedGuests = guests.map(
+ (guest) => Guest(
+ firstName: guest.firstName,
+ lastName: guest.lastName,
+ id: guest.id,
+ ),
+ ).toList();
return Booking(
id: confirmationNumber,
confirmationNumber: confirmationNumber,
@@ -26,7 +28,6 @@ extension BookingDTOMapper on BookingDTO {
hotelName: "Hotel $hotelCode",
roomType: roomType ?? '',
addOnItems: addOnItems,
-
balance: balance ?? 0,
children: children,
firstName: firstName,
@@ -48,32 +49,37 @@ extension BookingMapper on Booking {
BookingDTO toDTO() {
final firstName = this.firstName;
final lastName = this.lastName;
- final mappedGuests = guests.map((guest) => GuestDTO(
- id: guest.id,
- firstName: guest.firstName,
- lastName: guest.lastName,
- )).toList();
+ final mappedGuests = guests
+ .map(
+ (guest) => GuestDTO(
+ id: guest.id,
+ firstName: guest.firstName,
+ lastName: guest.lastName,
+ ),
+ )
+ .toList();
return BookingDTO(
- roomNumber: roomNumber,
- hotelCode: hotelCode,
- firstName: firstName,
- lastName: lastName,
- bookerFirstName: firstName,
- bookerLastName: lastName,
- guests: mappedGuests,
- confirmationNumber: confirmationNumber,
- dayIn: startDate.toIso8601String(),
- dayOut: endDate.toIso8601String(),
- cancelTime: null,
- isCancelled: false,
- bookTime: startDate.toIso8601String(),
- status: reservationStatus.name,
- roomType: roomType,
- adults: adults,
- children: children,
- balance: balance ?? 0,
- isPrimaryGuest: false,
- addOnItems: addOnItems ?? []);
+ roomNumber: roomNumber,
+ hotelCode: hotelCode,
+ firstName: firstName,
+ lastName: lastName,
+ bookerFirstName: firstName,
+ bookerLastName: lastName,
+ guests: mappedGuests,
+ confirmationNumber: confirmationNumber,
+ dayIn: startDate.toIso8601String(),
+ dayOut: endDate.toIso8601String(),
+ cancelTime: null,
+ isCancelled: false,
+ bookTime: startDate.toIso8601String(),
+ status: reservationStatus.name,
+ roomType: roomType,
+ adults: adults,
+ children: children,
+ balance: balance ?? 0,
+ isPrimaryGuest: false,
+ addOnItems: addOnItems ?? [],
+ );
}
}
@@ -106,13 +112,12 @@ extension BookingWithRoomsMapper on Booking {
}
}
- extension ListRoomMapper on List<RoomDto> {
- List<Room> toRooms() => map((dto) => dto.toRoom()).toList();
- }
+extension ListRoomMapper on List<RoomDto> {
+ List<Room> toRooms() => map((dto) => dto.toRoom()).toList();
+}
extension ListBookingMapper on Iterable<BookingDTO> {
- Iterable<Booking> toBookings() =>
- map((dto) => dto.toBooking());
+ Iterable<Booking> toBookings() => map((dto) => dto.toBooking());
}
extension RoomTypeMapper on Booking {
diff --git a/comwell_key_app/test/booking_details_test/booking_details_bloc_test.dart b/comwell_key_app/test/booking_details_test/booking_details_bloc_test.dart
index 2e7bc644..287c77f5 100644
--- a/comwell_key_app/test/booking_details_test/booking_details_bloc_test.dart
+++ b/comwell_key_app/test/booking_details_test/booking_details_bloc_test.dart
@@ -4,6 +4,7 @@ import 'package:comwell_key_app/booking_details/booking_details_repository.dart'
import 'package:comwell_key_app/check_in/check_in_repository.dart';
import 'package:comwell_key_app/housekeeping/housekeeping_repository.dart';
import 'package:comwell_key_app/profile/profile_repository.dart';
+import 'package:comwell_key_app/share/share_booking_repository.dart';
import 'package:comwell_key_app/up_sales/up_sales_repository.dart';
import 'package:comwell_key_app/utils/locator.dart';
import 'package:comwell_key_app/utils/seos_repository.dart';
@@ -11,8 +12,9 @@ import 'package:flutter_test/flutter_test.dart';
import 'package:bloc_test/bloc_test.dart';
import 'package:mocktail/mocktail.dart';
-class MockBookingDetailsRepository extends Mock
- implements BookingDetailsRepository {}
+import '../overview_test/overview_cubic_test.dart';
+
+class MockBookingDetailsRepository extends Mock implements BookingDetailsRepository {}
class MockProfileRepository extends Mock implements ProfileRepository {}
@@ -28,6 +30,8 @@ void main() {
late ProfileRepository mockProfileRepository;
late UpSalesRepository mockUpSalesRepository;
late HouseKeepingRepository mockHouseKeepingRepository;
+ late SeosRepository mockSeosRepository;
+ late ShareBookingRepository mockShareBookingRepository;
// Setup function runs before every test
setUp(() {
// Initialize the mock HomeRepository
@@ -35,6 +39,8 @@ void main() {
mockProfileRepository = MockProfileRepository();
mockUpSalesRepository = MockUpSalesRepository();
mockHouseKeepingRepository = MockHouseKeepingRepository();
+ mockSeosRepository = MockSeosRepository();
+ mockShareBookingRepository = MockShareBookingRepository();
setupLocator();
});
@@ -44,11 +50,13 @@ void main() {
build: () {
// Return bloc with mocked repository
return BookingDetailsBloc(
- CheckInRepository.mockBooking,
- bookingDetailsRepository: mockBookingDetailsRepository,
- profileRepository: mockProfileRepository,
- upSaleRepository: mockUpSalesRepository,
- houseKeepingRepository: mockHouseKeepingRepository,
+ booking: CheckInRepository.mockBooking,
+ mockBookingDetailsRepository,
+ mockProfileRepository,
+ mockSeosRepository,
+ mockUpSalesRepository,
+ mockShareBookingRepository,
+ mockHouseKeepingRepository,
);
},
act: (bloc) => bloc.add(const InitialEvent()),
@@ -57,5 +65,3 @@ void main() {
// Add more tests for other scenarios and events...
}
-
-
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 88f48e08..16c3889e 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
@@ -8,11 +8,9 @@ import 'package:flutter_test/flutter_test.dart';
import 'package:mocktail/mocktail.dart';
import 'package:comwell_key_app/profile_settings/cubit/profile_settings_cubit.dart';
-class MockProfileSettingsRepository extends Mock
- implements ProfileSettingsRepository {}
+class MockProfileSettingsRepository extends Mock implements ProfileSettingsRepository {}
-class MockAuthenticationRepository extends Mock
- implements AuthenticationRepository {}
+class MockAuthenticationRepository extends Mock implements AuthenticationRepository {}
class MockProfileRepository extends Mock implements ProfileRepository {}
@@ -26,9 +24,10 @@ void main() {
mockAuthenticationRepository = MockAuthenticationRepository();
mockProfileRepository = MockProfileRepository();
profileSettingsCubit = ProfileSettingsCubit(
- profileRepository: mockProfileRepository,
- profileSettingsRepository: mockProfileSettingsRepository,
- authenticationRepository: mockAuthenticationRepository);
+ mockProfileRepository,
+ mockProfileSettingsRepository,
+ mockAuthenticationRepository,
+ );
});
tearDown(() {
@@ -43,7 +42,7 @@ void main() {
emailVerified: true,
locale: 'en',
wasRecentlyCreated: false,
- firstName: 'John',
+ firstName: 'John',
lastName: 'Doe',
phoneNumber: '1234567890',
gender: 'Male',
@@ -56,14 +55,14 @@ void main() {
birthDate: DateTime(1990, 1, 1),
addressCountry: 'SE',
shopperReference: '1234567890',
- points: 100, isClubMember: false,
+ points: 100,
+ isClubMember: false,
);
blocTest<ProfileSettingsCubit, ProfileSettingsState>(
'emits [ProfileSettingsLoading, ProfileSettingsLoaded] when fetchProfileSettings is successful',
build: () {
- when(() => mockProfileRepository.fetchProfileSettings())
- .thenAnswer((_) async => user);
+ when(() => mockProfileRepository.fetchProfileSettings()).thenAnswer((_) async => user);
return profileSettingsCubit;
},
act: (cubit) => cubit.init(),
@@ -75,8 +74,9 @@ void main() {
blocTest<ProfileSettingsCubit, ProfileSettingsState>(
'emits [ProfileSettingsLoading, ProfileSettingsError] when fetchProfileSettings fails',
build: () {
- when(() => mockProfileRepository.fetchProfileSettings())
- .thenThrow(Exception('Failed to fetch profile settings'));
+ when(
+ () => mockProfileRepository.fetchProfileSettings(),
+ ).thenThrow(Exception('Failed to fetch profile settings'));
return profileSettingsCubit;
},
act: (cubit) => cubit.init(),
@@ -88,10 +88,8 @@ void main() {
blocTest<ProfileSettingsCubit, ProfileSettingsState>(
'emits [ProfileSettingsDeleted] when deleteProfile is successful',
build: () {
- when(() => mockProfileSettingsRepository.deleteProfile())
- .thenAnswer((_) async => {});
- when(() => mockAuthenticationRepository.logOut())
- .thenAnswer((_) async => {});
+ when(() => mockProfileSettingsRepository.deleteProfile()).thenAnswer((_) async => {});
+ when(() => mockAuthenticationRepository.logOut()).thenAnswer((_) async => {});
return profileSettingsCubit;
},
act: (cubit) => cubit.deleteProfile(),
@@ -103,8 +101,9 @@ void main() {
blocTest<ProfileSettingsCubit, ProfileSettingsState>(
'emits [ProfileSettingsError] when deleteProfile fails',
build: () {
- when(() => mockProfileSettingsRepository.deleteProfile())
- .thenThrow(Exception('Failed to delete profile'));
+ when(
+ () => mockProfileSettingsRepository.deleteProfile(),
+ ).thenThrow(Exception('Failed to delete profile'));
return profileSettingsCubit;
},
act: (cubit) => cubit.deleteProfile(),