6177214e-ce7c-49e3-99de-ff9721b26f63 — Commit 87485e24

AuthorMikkel Thygesen<mikkelet@gmail.com>
Date2026-02-20 01:32:02 +0100
3672: moved profile screen into presentation

Changed files

.../profile/bloc/profile_state.freezed.dart        | 274 +++++++++++++++++++
 .../screens/profile/profile_route.g.dart           |  32 +++
 .../lib/check_out/bloc/check_out_cubit.dart        |   2 +-
 .../lib/my_booking/cubit/my_booking_cubit.dart     |   4 +-
 comwell_key_app/lib/overview/overview_page.dart    |   2 +-
 .../lib/presentation/app/bloc/profile_cubit.dart   |  15 +-
 .../components/booking_details_bottom_sheet.dart   |   2 +-
 .../profile/components/card_content_widget.dart    |  94 +++++++
 .../profile/components/comwell_club_container.dart |  76 ++++++
 .../comwell_club_signup_bottom_sheet.dart          | 295 +++++++++++++++++++++
 .../profile/components/error_page_widget.dart      |  84 ++++++
 .../profile/components/logout_dialog_widget.dart   |  81 ++++++
 .../profile/components/profile_page_widget.dart    | 183 +++++++++++++
 .../profile/components/profile_settings_item.dart  |  26 ++
 .../screens/profile/profile_route.dart             |  17 ++
 .../screens/profile/profile_screen.dart            |  47 ++++
 .../profile/components/card_content_widget.dart    |  94 -------
 .../profile/components/comwell_club_container.dart |  76 ------
 .../comwell_club_signup_bottom_sheet.dart          | 295 ---------------------
 .../lib/profile/components/error_page_widget.dart  |  84 ------
 .../profile/components/logout_dialog_widget.dart   |  81 ------
 .../profile/components/profile_page_widget.dart    | 183 -------------
 .../profile/components/profile_settings_item.dart  |  26 --
 comwell_key_app/lib/profile/profile_page.dart      |  66 -----
 comwell_key_app/lib/profile/profile_route.dart     |  10 -
 comwell_key_app/lib/profile/utils/constants.dart   |   7 -
 comwell_key_app/lib/profile/utils/urls.dart        |   6 -
 comwell_key_app/lib/routing/app_router.dart        |   4 +-
 .../up_sales/pages/up_sale_confirmation_page.dart  |   2 +-
 comwell_key_app/lib/utils/constants.dart           |   7 +
 comwell_key_app/lib/utils/urls.dart                |   6 +
 31 files changed, 1231 insertions(+), 950 deletions(-)

Diff

diff --git a/comwell_key_app/lib/.generated/presentation/screens/profile/bloc/profile_state.freezed.dart b/comwell_key_app/lib/.generated/presentation/screens/profile/bloc/profile_state.freezed.dart
new file mode 100644
index 00000000..bd6574db
--- /dev/null
+++ b/comwell_key_app/lib/.generated/presentation/screens/profile/bloc/profile_state.freezed.dart
@@ -0,0 +1,274 @@
+// GENERATED CODE - DO NOT MODIFY BY HAND
+// coverage:ignore-file
+// ignore_for_file: type=lint
+// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark
+
+part of '../../../../../presentation/screens/profile/bloc/profile_state.dart';
+
+// **************************************************************************
+// FreezedGenerator
+// **************************************************************************
+
+// dart format off
+T _$identity<T>(T value) => value;
+/// @nodoc
+mixin _$ProfileState {
+
+ bool get isLoading; AppError get error;
+/// Create a copy of ProfileState
+/// with the given fields replaced by the non-null parameter values.
+@JsonKey(includeFromJson: false, includeToJson: false)
+@pragma('vm:prefer-inline')
+$ProfileStateCopyWith<ProfileState> get copyWith => _$ProfileStateCopyWithImpl<ProfileState>(this as ProfileState, _$identity);
+
+
+
+@override
+bool operator ==(Object other) {
+ return identical(this, other) || (other.runtimeType == runtimeType&&other is ProfileState&&(identical(other.isLoading, isLoading) || other.isLoading == isLoading)&&(identical(other.error, error) || other.error == error));
+}
+
+
+@override
+int get hashCode => Object.hash(runtimeType,isLoading,error);
+
+@override
+String toString() {
+ return 'ProfileState(isLoading: $isLoading, error: $error)';
+}
+
+
+}
+
+/// @nodoc
+abstract mixin class $ProfileStateCopyWith<$Res> {
+ factory $ProfileStateCopyWith(ProfileState value, $Res Function(ProfileState) _then) = _$ProfileStateCopyWithImpl;
+@useResult
+$Res call({
+ bool isLoading, AppError error
+});
+
+
+
+
+}
+/// @nodoc
+class _$ProfileStateCopyWithImpl<$Res>
+ implements $ProfileStateCopyWith<$Res> {
+ _$ProfileStateCopyWithImpl(this._self, this._then);
+
+ final ProfileState _self;
+ final $Res Function(ProfileState) _then;
+
+/// Create a copy of ProfileState
+/// with the given fields replaced by the non-null parameter values.
+@pragma('vm:prefer-inline') @override $Res call({Object? isLoading = null,Object? error = null,}) {
+ return _then(_self.copyWith(
+isLoading: null == isLoading ? _self.isLoading : isLoading // ignore: cast_nullable_to_non_nullable
+as bool,error: null == error ? _self.error : error // ignore: cast_nullable_to_non_nullable
+as AppError,
+ ));
+}
+
+}
+
+
+/// Adds pattern-matching-related methods to [ProfileState].
+extension ProfileStatePatterns on ProfileState {
+/// A variant of `map` that fallback to returning `orElse`.
+///
+/// It is equivalent to doing:
+/// ```dart
+/// switch (sealedClass) {
+/// case final Subclass value:
+/// return ...;
+/// case _:
+/// return orElse();
+/// }
+/// ```
+
+@optionalTypeArgs TResult maybeMap<TResult extends Object?>(TResult Function( _ProfileState value)? $default,{required TResult orElse(),}){
+final _that = this;
+switch (_that) {
+case _ProfileState() when $default != null:
+return $default(_that);case _:
+ return orElse();
+
+}
+}
+/// A `switch`-like method, using callbacks.
+///
+/// Callbacks receives the raw object, upcasted.
+/// It is equivalent to doing:
+/// ```dart
+/// switch (sealedClass) {
+/// case final Subclass value:
+/// return ...;
+/// case final Subclass2 value:
+/// return ...;
+/// }
+/// ```
+
+@optionalTypeArgs TResult map<TResult extends Object?>(TResult Function( _ProfileState value) $default,){
+final _that = this;
+switch (_that) {
+case _ProfileState():
+return $default(_that);case _:
+ throw StateError('Unexpected subclass');
+
+}
+}
+/// A variant of `map` that fallback to returning `null`.
+///
+/// It is equivalent to doing:
+/// ```dart
+/// switch (sealedClass) {
+/// case final Subclass value:
+/// return ...;
+/// case _:
+/// return null;
+/// }
+/// ```
+
+@optionalTypeArgs TResult? mapOrNull<TResult extends Object?>(TResult? Function( _ProfileState value)? $default,){
+final _that = this;
+switch (_that) {
+case _ProfileState() when $default != null:
+return $default(_that);case _:
+ return null;
+
+}
+}
+/// A variant of `when` that fallback to an `orElse` callback.
+///
+/// It is equivalent to doing:
+/// ```dart
+/// switch (sealedClass) {
+/// case Subclass(:final field):
+/// return ...;
+/// case _:
+/// return orElse();
+/// }
+/// ```
+
+@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( bool isLoading, AppError error)? $default,{required TResult orElse(),}) {final _that = this;
+switch (_that) {
+case _ProfileState() when $default != null:
+return $default(_that.isLoading,_that.error);case _:
+ return orElse();
+
+}
+}
+/// A `switch`-like method, using callbacks.
+///
+/// As opposed to `map`, this offers destructuring.
+/// It is equivalent to doing:
+/// ```dart
+/// switch (sealedClass) {
+/// case Subclass(:final field):
+/// return ...;
+/// case Subclass2(:final field2):
+/// return ...;
+/// }
+/// ```
+
+@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( bool isLoading, AppError error) $default,) {final _that = this;
+switch (_that) {
+case _ProfileState():
+return $default(_that.isLoading,_that.error);case _:
+ throw StateError('Unexpected subclass');
+
+}
+}
+/// A variant of `when` that fallback to returning `null`
+///
+/// It is equivalent to doing:
+/// ```dart
+/// switch (sealedClass) {
+/// case Subclass(:final field):
+/// return ...;
+/// case _:
+/// return null;
+/// }
+/// ```
+
+@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( bool isLoading, AppError error)? $default,) {final _that = this;
+switch (_that) {
+case _ProfileState() when $default != null:
+return $default(_that.isLoading,_that.error);case _:
+ return null;
+
+}
+}
+
+}
+
+/// @nodoc
+
+
+class _ProfileState implements ProfileState {
+ const _ProfileState({this.isLoading = false, this.error = AppError.none});
+
+
+@override@JsonKey() final bool isLoading;
+@override@JsonKey() final AppError error;
+
+/// Create a copy of ProfileState
+/// with the given fields replaced by the non-null parameter values.
+@override @JsonKey(includeFromJson: false, includeToJson: false)
+@pragma('vm:prefer-inline')
+_$ProfileStateCopyWith<_ProfileState> get copyWith => __$ProfileStateCopyWithImpl<_ProfileState>(this, _$identity);
+
+
+
+@override
+bool operator ==(Object other) {
+ return identical(this, other) || (other.runtimeType == runtimeType&&other is _ProfileState&&(identical(other.isLoading, isLoading) || other.isLoading == isLoading)&&(identical(other.error, error) || other.error == error));
+}
+
+
+@override
+int get hashCode => Object.hash(runtimeType,isLoading,error);
+
+@override
+String toString() {
+ return 'ProfileState(isLoading: $isLoading, error: $error)';
+}
+
+
+}
+
+/// @nodoc
+abstract mixin class _$ProfileStateCopyWith<$Res> implements $ProfileStateCopyWith<$Res> {
+ factory _$ProfileStateCopyWith(_ProfileState value, $Res Function(_ProfileState) _then) = __$ProfileStateCopyWithImpl;
+@override @useResult
+$Res call({
+ bool isLoading, AppError error
+});
+
+
+
+
+}
+/// @nodoc
+class __$ProfileStateCopyWithImpl<$Res>
+ implements _$ProfileStateCopyWith<$Res> {
+ __$ProfileStateCopyWithImpl(this._self, this._then);
+
+ final _ProfileState _self;
+ final $Res Function(_ProfileState) _then;
+
+/// Create a copy of ProfileState
+/// with the given fields replaced by the non-null parameter values.
+@override @pragma('vm:prefer-inline') $Res call({Object? isLoading = null,Object? error = null,}) {
+ return _then(_ProfileState(
+isLoading: null == isLoading ? _self.isLoading : isLoading // ignore: cast_nullable_to_non_nullable
+as bool,error: null == error ? _self.error : error // ignore: cast_nullable_to_non_nullable
+as AppError,
+ ));
+}
+
+
+}
+
+// dart format on
diff --git a/comwell_key_app/lib/.generated/presentation/screens/profile/profile_route.g.dart b/comwell_key_app/lib/.generated/presentation/screens/profile/profile_route.g.dart
new file mode 100644
index 00000000..12f5959a
--- /dev/null
+++ b/comwell_key_app/lib/.generated/presentation/screens/profile/profile_route.g.dart
@@ -0,0 +1,32 @@
+// GENERATED CODE - DO NOT MODIFY BY HAND
+
+part of '../../../../presentation/screens/profile/profile_route.dart';
+
+// **************************************************************************
+// GoRouterGenerator
+// **************************************************************************
+
+List<RouteBase> get $appRoutes => [$profileRoute];
+
+RouteBase get $profileRoute =>
+ GoRouteData.$route(path: '/profile', factory: $ProfileRoute._fromState);
+
+mixin $ProfileRoute on GoRouteData {
+ static ProfileRoute _fromState(GoRouterState state) => ProfileRoute();
+
+ @override
+ String get location => GoRouteData.$location('/profile');
+
+ @override
+ void go(BuildContext context) => context.go(location);
+
+ @override
+ Future<T?> push<T>(BuildContext context) => context.push<T>(location);
+
+ @override
+ void pushReplacement(BuildContext context) =>
+ context.pushReplacement(location);
+
+ @override
+ void replace(BuildContext context) => context.replace(location);
+}
diff --git a/comwell_key_app/lib/check_out/bloc/check_out_cubit.dart b/comwell_key_app/lib/check_out/bloc/check_out_cubit.dart
index 0ea2f787..5841b6d3 100644
--- a/comwell_key_app/lib/check_out/bloc/check_out_cubit.dart
+++ b/comwell_key_app/lib/check_out/bloc/check_out_cubit.dart
@@ -7,12 +7,12 @@ import 'package:comwell_key_app/domain/repositories/booking_details_repository.d
import 'package:comwell_key_app/overview/models/booking.dart';
import 'package:comwell_key_app/pregistration/pregistration_repository.dart';
import 'package:comwell_key_app/domain/repositories/profile_repository.dart';
-import 'package:comwell_key_app/profile/utils/urls.dart';
import 'package:comwell_key_app/routing/app_routes.dart';
import 'package:comwell_key_app/services/models/booking_dto.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';
+import 'package:comwell_key_app/utils/urls.dart';
import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
import 'package:payment_plugin/presentation/app/bloc/payment_cubit.dart';
diff --git a/comwell_key_app/lib/my_booking/cubit/my_booking_cubit.dart b/comwell_key_app/lib/my_booking/cubit/my_booking_cubit.dart
index 0d6c6df7..de66ecc6 100644
--- a/comwell_key_app/lib/my_booking/cubit/my_booking_cubit.dart
+++ b/comwell_key_app/lib/my_booking/cubit/my_booking_cubit.dart
@@ -1,9 +1,7 @@
import 'package:comwell_key_app/my_booking/cubit/my_booking_state.dart';
import 'package:comwell_key_app/my_booking/my_booking_repository.dart';
import 'package:comwell_key_app/overview/models/booking.dart';
-
import 'package:comwell_key_app/domain/repositories/profile_repository.dart';
-import 'package:comwell_key_app/profile/utils/urls.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';
@@ -11,6 +9,8 @@ import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:payment_plugin/presentation/app/bloc/payment_cubit.dart';
import 'package:url_launcher/url_launcher.dart';
+import '../../utils/urls.dart';
+
class MyBookingCubit extends Cubit<MyBookingState> {
final MyBookingRepository myBookingRepository;
final ProfileRepository profileRepository = locator<ProfileRepository>();
diff --git a/comwell_key_app/lib/overview/overview_page.dart b/comwell_key_app/lib/overview/overview_page.dart
index da9c0aff..ee8addfb 100644
--- a/comwell_key_app/lib/overview/overview_page.dart
+++ b/comwell_key_app/lib/overview/overview_page.dart
@@ -7,11 +7,11 @@ import 'package:comwell_key_app/overview/components/find_booking_button.dart';
import 'package:comwell_key_app/overview/cubit/overview_cubit.dart';
import 'package:comwell_key_app/overview/cubit/overview_state.dart';
import 'package:comwell_key_app/overview/models/bookings.dart';
-import 'package:comwell_key_app/profile/utils/urls.dart';
import 'package:comwell_key_app/routing/app_routes.dart';
import 'package:comwell_key_app/themes/light_theme.dart';
import 'package:comwell_key_app/utils/context_utils.dart';
import 'package:comwell_key_app/utils/l10n_utils.dart';
+import 'package:comwell_key_app/utils/urls.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:go_router/go_router.dart';
diff --git a/comwell_key_app/lib/presentation/app/bloc/profile_cubit.dart b/comwell_key_app/lib/presentation/app/bloc/profile_cubit.dart
index eaa8a706..3f1f1f0f 100644
--- a/comwell_key_app/lib/presentation/app/bloc/profile_cubit.dart
+++ b/comwell_key_app/lib/presentation/app/bloc/profile_cubit.dart
@@ -40,21 +40,8 @@ class ProfileCubit extends BaseCubit<ProfileState> {
void init() async {
try {
safeEmit(state.loading());
- final user = await _profileRepository.fetchProfileSettings();
- sendPageViewEvent();
- safeEmit(state.copyWith(user: user));
- } catch (e, st) {
- logError(e, st);
- safeEmit(state.copyWith(error: AppError.unknown(e.toString())));
- } finally {
- safeEmit(state.copyWith(isLoading: false));
- }
- }
-
- void fetchRemoteProfile() async {
- safeEmit(state.loading());
- try {
final user = await _profileRepository.fetchProfileSettings(fetchRemote: true);
+ sendPageViewEvent();
safeEmit(state.copyWith(user: user));
} catch (e, st) {
logError(e, st);
diff --git a/comwell_key_app/lib/presentation/screens/booking_details/components/booking_details_bottom_sheet.dart b/comwell_key_app/lib/presentation/screens/booking_details/components/booking_details_bottom_sheet.dart
index 71a47f48..a09defa2 100644
--- a/comwell_key_app/lib/presentation/screens/booking_details/components/booking_details_bottom_sheet.dart
+++ b/comwell_key_app/lib/presentation/screens/booking_details/components/booking_details_bottom_sheet.dart
@@ -6,7 +6,7 @@ import 'package:comwell_key_app/presentation/screens/booking_details/components/
import 'package:comwell_key_app/presentation/screens/booking_details/components/concierge_button.dart';
import 'package:comwell_key_app/presentation/screens/booking_details/components/housekeeping_button.dart';
import 'package:comwell_key_app/presentation/screens/booking_details/components/practical_information_button.dart';
-import 'package:comwell_key_app/profile/components/comwell_club_container.dart';
+import 'package:comwell_key_app/presentation/screens/profile/components/comwell_club_container.dart';
import 'package:comwell_key_app/routing/app_routes.dart';
import 'package:comwell_key_app/themes/light_theme.dart';
import 'package:comwell_key_app/up_sales/components/catalog/service_catalog.dart';
diff --git a/comwell_key_app/lib/presentation/screens/profile/components/card_content_widget.dart b/comwell_key_app/lib/presentation/screens/profile/components/card_content_widget.dart
new file mode 100644
index 00000000..d28d2d59
--- /dev/null
+++ b/comwell_key_app/lib/presentation/screens/profile/components/card_content_widget.dart
@@ -0,0 +1,94 @@
+import 'package:comwell_key_app/presentation/app/bloc/profile_cubit.dart';
+import 'package:comwell_key_app/utils/l10n_utils.dart';
+import 'package:flutter/material.dart';
+
+class CardContentWidget extends StatelessWidget {
+ final ProfileCubit cubit;
+ final bool isActive;
+
+ const CardContentWidget({super.key, required this.cubit, required this.isActive});
+
+ @override
+ Widget build(BuildContext context) {
+ final theme = Theme.of(context);
+ final user = cubit.state.user!;
+
+ return SizedBox(
+ width: double.infinity,
+ height: double.infinity,
+ child: Stack(
+ children: [
+ Positioned(
+ top: 20,
+ left: 20,
+ child: Container(
+ padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 6),
+ decoration: BoxDecoration(
+ color: Theme.of(context).colorScheme.surface,
+ borderRadius: BorderRadius.circular(32),
+ ),
+ child: Text(
+ isActive ? 'Comwell Club' : context.strings.comwell_club_inactive,
+ style: theme.textTheme.bodySmall!.copyWith(
+ color: Theme.of(context).colorScheme.onSurface,
+ fontWeight: FontWeight.w600,
+ ),
+ ),
+ ),
+ ),
+ Positioned(
+ bottom: 20,
+ left: 20,
+ child: Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ Text(
+ 'Navn',
+ style: TextStyle(
+ color: isActive ? Colors.white : Theme.of(context).colorScheme.onSurface,
+ fontSize: 14,
+ fontWeight: FontWeight.w400,
+ ),
+ ),
+ Text(
+ '${user.firstName} ${user.lastName}',
+ style: TextStyle(
+ color: isActive ? Colors.white : Theme.of(context).colorScheme.onSurface,
+ fontSize: 16,
+ fontWeight: FontWeight.w600,
+ ),
+ ),
+ ],
+ ),
+ ),
+ if (isActive)
+ Positioned(
+ bottom: 20,
+ right: 20,
+ child: Column(
+ crossAxisAlignment: CrossAxisAlignment.end,
+ children: [
+ Text(
+ context.strings.points,
+ style: const TextStyle(
+ color: Colors.white,
+ fontSize: 14,
+ fontWeight: FontWeight.w400,
+ ),
+ ),
+ Text(
+ '${user.points} ${context.strings.points}',
+ style: const TextStyle(
+ color: Colors.white,
+ fontSize: 16,
+ fontWeight: FontWeight.w600,
+ ),
+ ),
+ ],
+ ),
+ ),
+ ],
+ ),
+ );
+ }
+}
diff --git a/comwell_key_app/lib/presentation/screens/profile/components/comwell_club_container.dart b/comwell_key_app/lib/presentation/screens/profile/components/comwell_club_container.dart
new file mode 100644
index 00000000..7ae87176
--- /dev/null
+++ b/comwell_key_app/lib/presentation/screens/profile/components/comwell_club_container.dart
@@ -0,0 +1,76 @@
+import 'package:comwell_key_app/domain/models/user.dart';
+import 'comwell_club_signup_bottom_sheet.dart';
+import 'package:comwell_key_app/presentation/app/bloc/profile_cubit.dart';
+import 'package:comwell_key_app/themes/light_theme.dart';
+import 'package:comwell_key_app/utils/l10n_utils.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter_bloc/flutter_bloc.dart';
+
+class ComwellClubContainer extends StatelessWidget {
+ final User user;
+ final VoidCallback onSignupClick;
+ const ComwellClubContainer({super.key, required this.user, required this.onSignupClick});
+
+ @override
+ Widget build(BuildContext context) {
+ final cubit = context.read<ProfileCubit>();
+
+ return Container(
+ margin: const EdgeInsets.symmetric(horizontal: 16),
+ padding: const EdgeInsets.symmetric(vertical: 16),
+ decoration: BoxDecoration(
+ color: sandColor[10],
+ borderRadius: const BorderRadius.all(Radius.circular(10)),
+ ),
+ child: Row(
+ mainAxisAlignment: MainAxisAlignment.spaceAround,
+ children: [
+ GestureDetector(
+ onTap: () async {
+ await showModalBottomSheet<void>(
+ context: context,
+ isScrollControlled: true,
+ backgroundColor: Colors.white,
+ builder: (_) => BlocProvider.value(
+ value: cubit,
+ child: ComwellClubSignupBottomSheet(user: user),
+ ),
+ );
+ if (context.mounted) {
+ onSignupClick();
+ }
+ },
+ child: Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ Text(context.strings.become_cc_member_title,
+ textAlign: TextAlign.start,
+ style: const TextStyle(
+ color: colorTertiary,
+ fontSize: 16,
+ fontWeight: FontWeight.w600)),
+ SizedBox(
+ width: 250,
+ child: Text(
+ context.strings.become_cc_member_subtitle,
+ textAlign: TextAlign.start,
+ maxLines: 4,
+ style: const TextStyle(
+ color: colorTertiary,
+ fontSize: 14,
+ fontWeight: FontWeight.w500),
+ ),
+ ),
+ ],
+ ),
+ ),
+ const Icon(
+ Icons.chevron_right,
+ color: colorTertiary,
+ size: 24,
+ ),
+ ],
+ ),
+ );
+ }
+}
diff --git a/comwell_key_app/lib/presentation/screens/profile/components/comwell_club_signup_bottom_sheet.dart b/comwell_key_app/lib/presentation/screens/profile/components/comwell_club_signup_bottom_sheet.dart
new file mode 100644
index 00000000..5c0dd2a2
--- /dev/null
+++ b/comwell_key_app/lib/presentation/screens/profile/components/comwell_club_signup_bottom_sheet.dart
@@ -0,0 +1,295 @@
+import 'package:comwell_key_app/common/components/round_icon_button.dart';
+import 'package:comwell_key_app/domain/models/user.dart';
+import 'package:comwell_key_app/presentation/app/bloc/profile_cubit.dart';
+import 'package:comwell_key_app/presentation/screens/profile_settings/components/comwell_text_field.dart';
+import 'package:comwell_key_app/utils/constants.dart';
+import 'package:comwell_key_app/domain/models/address.dart';
+import 'package:comwell_key_app/themes/light_theme.dart';
+import 'package:comwell_key_app/utils/l10n_utils.dart';
+import 'package:comwell_key_app/utils/urls.dart';
+import 'package:flutter/gestures.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter_bloc/flutter_bloc.dart';
+import 'package:go_router/go_router.dart';
+import 'package:url_launcher/url_launcher.dart';
+
+class ComwellClubSignupBottomSheet extends StatefulWidget {
+ final User user;
+
+ const ComwellClubSignupBottomSheet({super.key, required this.user});
+
+ @override
+ State<ComwellClubSignupBottomSheet> createState() => _ComwellClubSignupBottomSheetState();
+}
+
+class _ComwellClubSignupBottomSheetState extends State<ComwellClubSignupBottomSheet> {
+ late final TextEditingController _postNumberController;
+ String _selectedGender = '';
+
+ @override
+ void initState() {
+ super.initState();
+ _postNumberController = TextEditingController(text: widget.user.address.zipCode);
+ }
+
+ @override
+ void dispose() {
+ _postNumberController.dispose();
+ super.dispose();
+ }
+
+ @override
+ Widget build(BuildContext context) {
+ final theme = Theme.of(context);
+ final cubit = context.read<ProfileCubit>();
+ return Wrap(
+ children: [
+ Padding(
+ padding: MediaQuery.of(context).viewInsets,
+ child: Container(
+ decoration: const BoxDecoration(
+ color: Colors.white,
+ borderRadius: BorderRadius.only(
+ topLeft: Radius.circular(24),
+ topRight: Radius.circular(24),
+ ),
+ ),
+ height:
+ MediaQuery.of(context).copyWith(viewInsets: EdgeInsets.zero).size.height *
+ ComwellClubConstants.imageHeightRatio,
+ child: Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ Padding(
+ padding: const EdgeInsets.only(top: 40, left: 16),
+ child: Container(
+ height: 47,
+ color: Colors.white,
+ child: Stack(
+ children: [
+ Row(
+ mainAxisAlignment: MainAxisAlignment.spaceBetween,
+ children: [
+ Text(
+ context.strings.comwell_club_dialog_title,
+ style: theme.textTheme.headlineLarge,
+ ),
+ RoundIconButton(
+ icon: 'assets/icons/close-icon.svg',
+ color: sandColor[20]!,
+ onPressed: () {
+ Navigator.pop(context);
+ },
+ ),
+ ],
+ ),
+ ],
+ ),
+ ),
+ ),
+ const SizedBox(height: 24),
+ Padding(
+ padding: const EdgeInsets.symmetric(horizontal: 16),
+ child: ComwellTextField(
+ fieldName: context.strings.postal_code,
+ initialValue: widget.user.address.zipCode,
+ readOnly: false,
+ controller: _postNumberController,
+ ),
+ ),
+ const SizedBox(height: 16),
+ Padding(
+ padding: const EdgeInsets.symmetric(horizontal: 16),
+ child: Container(
+ height: 62,
+ decoration: BoxDecoration(
+ borderRadius: BorderRadius.circular(8),
+ border: Border.all(color: colorDivider),
+ ),
+ child: DropdownButtonHideUnderline(
+ child: DropdownButton<String>(
+ value: _selectedGender.isEmpty ? null : _selectedGender,
+ isExpanded: true,
+ dropdownColor: Colors.white,
+ alignment: Alignment.centerLeft,
+ padding: const EdgeInsets.symmetric(horizontal: 16),
+ hint: Text(
+ context.strings.gender,
+ style: theme.textTheme.headlineSmall,
+ ),
+ items: [
+ DropdownMenuItem(
+ value: "Male",
+ child: Text(
+ context.strings.male,
+ style: theme.textTheme.headlineSmall,
+ ),
+ ),
+ DropdownMenuItem(
+ value: "Female",
+ child: Text(
+ context.strings.female,
+ style: theme.textTheme.headlineSmall,
+ ),
+ ),
+ DropdownMenuItem(
+ value: "Other",
+ child: Text(
+ context.strings.not_specified,
+ style: theme.textTheme.headlineSmall,
+ ),
+ ),
+ ],
+ onChanged: (String? value) {
+ if (value != null) {
+ setState(() {
+ _selectedGender = value;
+ });
+ }
+ },
+ ),
+ ),
+ ),
+ ),
+ const SizedBox(height: 16),
+
+ const SizedBox(height: 10),
+ Padding(
+ padding: const EdgeInsets.symmetric(horizontal: 16),
+ child: Row(
+ children: [
+ Checkbox(
+ value: cubit.state.isToSAccepted,
+ onChanged: (bool? value) {
+ setState(() {
+ cubit.onToSClick(value);
+ });
+ },
+ ),
+ Expanded(
+ child: Row(
+ children: [
+ Expanded(
+ child: RichText(
+ text: TextSpan(
+ children: <TextSpan>[
+ TextSpan(
+ text: context.strings.tos_accept,
+ style: TextStyle(
+ fontSize: theme.textTheme.bodySmall!.fontSize,
+ color: theme.textTheme.bodySmall!.color,
+ fontWeight: FontWeight.w300,
+ ),
+ ),
+ TextSpan(
+ text: context.strings.tos_accept_link,
+ recognizer: TapGestureRecognizer()
+ ..onTap = () {
+ launchUrl(Uri.parse(ComwellUrls.clubRules));
+ },
+ style: TextStyle(
+ fontSize: theme.textTheme.bodySmall!.fontSize,
+ color: sandColor[80],
+ decoration: TextDecoration.underline,
+ ),
+ ),
+ ],
+ ),
+ ),
+ ),
+ ],
+ ),
+ ),
+ ],
+ ),
+ ),
+ const SizedBox(height: 8),
+ Padding(
+ padding: const EdgeInsets.symmetric(horizontal: 16),
+ child: Row(
+ children: [
+ Checkbox(
+ value: cubit.state.isNewsletterAccepted,
+ onChanged: (bool? value) {
+ setState(() {
+ cubit.onNewsletterClick(value);
+ });
+ },
+ ),
+ Expanded(
+ child: RichText(
+ text: TextSpan(
+ children: <TextSpan>[
+ TextSpan(
+ text: context.strings.newsletter_accept,
+ style: TextStyle(
+ fontSize: theme.textTheme.bodySmall!.fontSize,
+ color: theme.textTheme.bodySmall!.color,
+ fontWeight: FontWeight.w300,
+ ),
+ ),
+ TextSpan(
+ text: context.strings.read_more,
+ recognizer: TapGestureRecognizer()
+ ..onTap = () {
+ launchUrl(Uri.parse(ComwellUrls.clubPermission));
+ },
+ style: TextStyle(
+ fontSize: theme.textTheme.bodySmall!.fontSize,
+ color: sandColor[80],
+ decoration: TextDecoration.underline,
+ ),
+ ),
+ ],
+ ),
+ ),
+ ),
+ ],
+ ),
+ ),
+ const SizedBox(height: 16),
+ const Divider(color: colorDivider),
+ const SizedBox(height: 16),
+ Padding(
+ padding: const EdgeInsets.symmetric(horizontal: 16),
+ child: ElevatedButton(
+ style: theme.elevatedButtonTheme.style?.copyWith(
+ backgroundColor: WidgetStatePropertyAll(
+ cubit.state.isToSAccepted && _selectedGender.isNotEmpty
+ ? sandColor
+ : Colors.grey[200],
+ ),
+ ),
+ onPressed: () async {
+ final response = await cubit.onComwellClubSignupClick(
+ widget.user.copyWith(
+ gender: _selectedGender,
+ address: Address(
+ zipCode: _postNumberController.text,
+ street: '',
+ city: '',
+ country: '',
+ ),
+ ),
+ );
+
+ if (response == true && context.mounted) {
+ context.pop();
+ }
+ },
+ child: Text(
+ context.strings.save,
+ style: theme.textTheme.headlineSmall?.copyWith(
+ color: cubit.state.isToSAccepted ? Colors.white : Colors.grey[400],
+ ),
+ ),
+ ),
+ ),
+ ],
+ ),
+ ),
+ ),
+ ],
+ );
+ }
+}
diff --git a/comwell_key_app/lib/presentation/screens/profile/components/error_page_widget.dart b/comwell_key_app/lib/presentation/screens/profile/components/error_page_widget.dart
new file mode 100644
index 00000000..a84fe633
--- /dev/null
+++ b/comwell_key_app/lib/presentation/screens/profile/components/error_page_widget.dart
@@ -0,0 +1,84 @@
+import 'package:comwell_key_app/common/components/comwell_card_component.dart';
+import 'package:comwell_key_app/common/components/comwell_error_widget.dart';
+import 'package:comwell_key_app/common/components/round_icon_button.dart';
+import 'logout_dialog_widget.dart';
+import 'package:comwell_key_app/presentation/app/bloc/profile_cubit.dart';
+import 'package:comwell_key_app/themes/light_theme.dart';
+import 'package:comwell_key_app/utils/l10n_utils.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter_bloc/flutter_bloc.dart';
+import 'package:go_router/go_router.dart';
+
+class ErrorPageWidget extends StatelessWidget {
+ const ErrorPageWidget({super.key});
+
+ @override
+ Widget build(BuildContext context) {
+ return Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ mainAxisAlignment: MainAxisAlignment.start,
+ children: [
+ Padding(
+ padding: const EdgeInsets.only(top: 80),
+ child: Container(
+ alignment: Alignment.centerRight,
+ child: RoundIconButton(
+ icon: "assets/icons/close-icon.svg",
+ color: Colors.white,
+ onPressed: () {
+ context.pop();
+ }),
+ ),
+ ),
+ Padding(
+ padding: const EdgeInsets.all(16.0),
+ child: Column(
+ children: [
+ ComwellCard(
+ content: const SizedBox.shrink(),
+ backgroundColor: sandColor[10]!),
+ ],
+ ),
+ ),
+ const SizedBox(height: 10),
+ Expanded(
+ child: Container(
+ decoration: BoxDecoration(
+ color: Colors.white,
+ border: Border.all(color: colorDivider),
+ ),
+ padding: const EdgeInsets.symmetric(horizontal: 16.0),
+ child: Column(
+ children: [
+ ComwellErrorWidget(
+ title: context.strings.profile_error_title,
+ subtitle: context.strings.profile_error_subtitle,
+ border: true),
+ const SizedBox(height: 30),
+ Center(
+ child: OutlinedButton(
+ style: OutlinedButton.styleFrom(
+ side: const BorderSide(color: colorDivider),
+ ),
+ onPressed: () {
+ showDialog<void>(
+ context: context,
+ builder: (context) => LogoutDialogWidget(
+ cubit: context.read<ProfileCubit>(),
+ ),
+ );
+ },
+ child: Text(
+ context.strings.logout_profile_menu,
+ style: const TextStyle(color: colorGrey),
+ ),
+ ),
+ ),
+ ],
+ ),
+ ),
+ ),
+ ],
+ );
+ }
+}
diff --git a/comwell_key_app/lib/presentation/screens/profile/components/logout_dialog_widget.dart b/comwell_key_app/lib/presentation/screens/profile/components/logout_dialog_widget.dart
new file mode 100644
index 00000000..3f3b13b8
--- /dev/null
+++ b/comwell_key_app/lib/presentation/screens/profile/components/logout_dialog_widget.dart
@@ -0,0 +1,81 @@
+import 'package:comwell_key_app/presentation/app/bloc/profile_cubit.dart';
+import 'package:comwell_key_app/routing/app_routes.dart';
+import 'package:comwell_key_app/utils/l10n_utils.dart';
+import 'package:flutter/material.dart';
+import 'package:go_router/go_router.dart';
+
+class LogoutDialogWidget extends StatelessWidget {
+ final ProfileCubit cubit;
+ const LogoutDialogWidget({super.key, required this.cubit});
+
+ @override
+ Widget build(BuildContext context) {
+ final theme = Theme.of(context);
+
+ return Dialog(
+ shape: RoundedRectangleBorder(
+ borderRadius: BorderRadius.circular(20),
+ ),
+ child: Padding(
+ padding: const EdgeInsets.all(24.0),
+ child: Column(
+ mainAxisSize: MainAxisSize.min,
+ children: [
+ Text(
+ context.strings.logout_dialog_title,
+ textAlign: TextAlign.center,
+ style: TextStyle(
+ color: Theme.of(context).colorScheme.onSurface,
+ fontSize: 18,
+ fontWeight: FontWeight.w600,
+ ),
+ ),
+ const SizedBox(height: 24),
+ SizedBox(
+ width: double.infinity,
+ child: ElevatedButton(
+ style: theme.elevatedButtonTheme.style?.copyWith(
+ padding: const WidgetStatePropertyAll(
+ EdgeInsets.symmetric(vertical: 16)),
+ ),
+ onPressed: () {
+ cubit.logOutPressed();
+ context.go(AppRoutes.login);
+ },
+ child: Text(
+ context.strings.logout_profile_menu,
+ style: TextStyle(
+ fontSize: 16,
+ fontWeight: FontWeight.w600,
+ color: Theme.of(context).colorScheme.surface,
+ ),
+ ),
+ ),
+ ),
+ const SizedBox(height: 12),
+ SizedBox(
+ width: double.infinity,
+ child: OutlinedButton(
+ style: OutlinedButton.styleFrom(
+ side: BorderSide(color: Colors.grey[400]!),
+ padding: const EdgeInsets.symmetric(vertical: 16),
+ ),
+ onPressed: () {
+ Navigator.of(context).pop();
+ },
+ child: Text(
+ context.strings.cancel,
+ style: TextStyle(
+ fontSize: 16,
+ fontWeight: FontWeight.w600,
+ color: Theme.of(context).colorScheme.onSurface,
+ ),
+ ),
+ ),
+ ),
+ ],
+ ),
+ ),
+ );
+ }
+}
diff --git a/comwell_key_app/lib/presentation/screens/profile/components/profile_page_widget.dart b/comwell_key_app/lib/presentation/screens/profile/components/profile_page_widget.dart
new file mode 100644
index 00000000..082fff0b
--- /dev/null
+++ b/comwell_key_app/lib/presentation/screens/profile/components/profile_page_widget.dart
@@ -0,0 +1,183 @@
+import 'package:comwell_key_app/.generated/assets/assets.gen.dart';
+import 'package:comwell_key_app/common/components/comwell_card_component.dart';
+import 'package:comwell_key_app/common/components/round_icon_button.dart';
+import 'package:comwell_key_app/presentation/screens/permission_overview/permission_overview_route.dart';
+import 'card_content_widget.dart';
+import 'comwell_club_container.dart';
+import 'logout_dialog_widget.dart';
+import 'profile_settings_item.dart';
+import 'package:comwell_key_app/presentation/app/bloc/profile_cubit.dart';
+import 'package:comwell_key_app/routing/app_routes.dart';
+import 'package:comwell_key_app/themes/app_spaces.dart';
+import 'package:comwell_key_app/themes/light_theme.dart';
+import 'package:comwell_key_app/utils/l10n_utils.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter_bloc/flutter_bloc.dart';
+import 'package:go_router/go_router.dart';
+import 'package:url_launcher/url_launcher.dart';
+
+class ProfilePageWidget extends StatelessWidget {
+ final ProfileCubit cubit;
+
+ const ProfilePageWidget({super.key, required this.cubit});
+
+ @override
+ Widget build(BuildContext context) {
+ final user = cubit.state.user;
+ final isActive = cubit.state.user?.isClubMember == true;
+
+ return SingleChildScrollView(
+ child: Column(
+ children: [
+ Padding(
+ padding: const EdgeInsets.only(top: 60, right: 10),
+ child: Container(
+ alignment: Alignment.centerRight,
+ child: RoundIconButton(
+ icon: "assets/icons/close-icon.svg",
+ color: Colors.white,
+ onPressed: () {
+ context.pop();
+ },
+ ),
+ ),
+ ),
+ Padding(
+ padding: const EdgeInsets.all(16.0),
+ child: Column(
+ children: [
+ ComwellCard(
+ content: CardContentWidget(cubit: cubit, isActive: isActive),
+ backgroundColor: isActive ? sandColor : sandColor[10]!,
+ ),
+ ],
+ ),
+ ),
+ const SizedBox(height: 10),
+ Container(
+ color: Colors.white,
+ child: Column(
+ mainAxisSize: MainAxisSize.min,
+ children: [
+ const SizedBox(height: 10),
+ !isActive
+ ? ComwellClubContainer(
+ user: user!,
+ onSignupClick: () {
+ cubit.init();
+ },
+ )
+ : const SizedBox(),
+ const SizedBox(height: 10),
+ profileSettingsItem(
+ context,
+ icon: Assets.icons.userCircleSvg.svg(),
+ text: context.strings.profile_settings_profile_menu,
+ trailingIcon: Icons.chevron_right,
+ onTap: () async {
+ await context.push(AppRoutes.profileSettings);
+ cubit.init();
+ },
+ ),
+ const Padding(
+ padding: EdgeInsets.symmetric(horizontal: 16.0),
+ child: Divider(color: colorDivider),
+ ),
+ profileSettingsItem(
+ context,
+ icon: Assets.icons.calendarPng.image(),
+ text: context.strings.payment_card_profile_menu,
+ trailingIcon: Icons.chevron_right,
+ onTap: () {
+ context.push("${AppRoutes.paymentCards}?needsScaffold=true");
+ },
+ ),
+ const Padding(
+ padding: EdgeInsets.symmetric(horizontal: 16.0),
+ child: Divider(color: colorDivider),
+ ),
+ profileSettingsItem(
+ context,
+ icon: const Icon(Icons.check),
+ trailingIcon: Icons.chevron_right,
+ text: context.strings.permissions,
+ onTap: () {
+ PermissionOverviewRoute().push(context);
+ },
+ ),
+ const Padding(
+ padding: EdgeInsets.symmetric(horizontal: 16.0),
+ child: Divider(color: colorDivider),
+ ),
+ profileSettingsItem(
+ context,
+ icon: Assets.icons.bell.image(),
+ trailingIcon: Icons.chevron_right,
+ text: context.strings.notifications_profile_menu,
+ onTap: () {
+ context.push(AppRoutes.notifications);
+ },
+ ),
+ const Padding(
+ padding: EdgeInsets.symmetric(horizontal: 16.0),
+ child: Divider(color: colorDivider),
+ ),
+ const SizedBox(height: 10),
+ if (isActive) ...[
+ profileSettingsItem(
+ context,
+ icon: Assets.icons.cLogo.svg(),
+ text: "Comwell Club",
+ trailingIcon: Icons.open_in_new,
+ onTap: () {
+ launchUrl(Uri.parse('https://comwell.com/profile'));
+ },
+ ),
+ const Padding(
+ padding: EdgeInsets.symmetric(horizontal: 16.0),
+ child: Divider(color: colorDivider),
+ ),
+ ],
+ const SizedBox(height: 10),
+ Center(
+ child: OutlinedButton(
+ style: OutlinedButton.styleFrom(
+ side: const BorderSide(color: colorDivider),
+ ),
+ onPressed: () {
+ showDialog<void>(
+ context: context,
+ builder: (context) => LogoutDialogWidget(
+ cubit: context.read<ProfileCubit>(),
+ ),
+ );
+ },
+ child: Text(
+ context.strings.logout_profile_menu,
+ style: TextStyle(color: Colors.grey[600]),
+ ),
+ ),
+ ),
+ AppSpaces.gap16,
+ FutureBuilder<String>(
+ future: context.read<ProfileCubit>().getVersion(),
+ builder: (context, snapshot) {
+ if (snapshot.hasData) {
+ return Text(
+ snapshot.requireData,
+ style: TextStyle(color: Colors.grey[500]),
+ );
+ }
+ return const SizedBox.shrink();
+ },
+ ),
+ AppSpaces.gap40,
+
+ ],
+ ),
+ ),
+ ],
+ ),
+ );
+ }
+}
diff --git a/comwell_key_app/lib/presentation/screens/profile/components/profile_settings_item.dart b/comwell_key_app/lib/presentation/screens/profile/components/profile_settings_item.dart
new file mode 100644
index 00000000..23dbc0fd
--- /dev/null
+++ b/comwell_key_app/lib/presentation/screens/profile/components/profile_settings_item.dart
@@ -0,0 +1,26 @@
+import 'package:comwell_key_app/themes/light_theme.dart';
+import 'package:flutter/material.dart';
+
+Widget profileSettingsItem(
+ BuildContext context, {
+ required Widget icon,
+ required String text,
+ required IconData trailingIcon,
+ required VoidCallback onTap,
+}) {
+ return ListTile(
+ leading: Container(
+ width: 36,
+ height: 36,
+ padding: const EdgeInsets.all(8.0),
+ decoration: BoxDecoration(
+ color: sandColor[20],
+ shape: BoxShape.circle,
+ ),
+ child: icon,
+ ),
+ title: Text(text, style: const TextStyle(color: colorTertiary)),
+ trailing: Icon(trailingIcon, color: colorTertiary, size: 24),
+ onTap: onTap,
+ );
+}
diff --git a/comwell_key_app/lib/presentation/screens/profile/profile_route.dart b/comwell_key_app/lib/presentation/screens/profile/profile_route.dart
new file mode 100644
index 00000000..870ba88a
--- /dev/null
+++ b/comwell_key_app/lib/presentation/screens/profile/profile_route.dart
@@ -0,0 +1,17 @@
+import 'package:flutter/material.dart';
+import 'package:go_router/go_router.dart';
+import 'package:comwell_key_app/presentation/screens/profile/profile_screen.dart';
+
+import '../../../routing/app_routes.dart';
+
+part '../../../.generated/presentation/screens/profile/profile_route.g.dart';
+
+@TypedGoRoute<ProfileRoute>(path: AppRoutes.profile)
+class ProfileRoute extends GoRouteData with $ProfileRoute {
+ @override
+ Page<void> buildPage(BuildContext context, GoRouterState state) {
+ return const MaterialPage(
+ child: ProfileScreen(),
+ );
+ }
+}
diff --git a/comwell_key_app/lib/presentation/screens/profile/profile_screen.dart b/comwell_key_app/lib/presentation/screens/profile/profile_screen.dart
new file mode 100644
index 00000000..2940c1aa
--- /dev/null
+++ b/comwell_key_app/lib/presentation/screens/profile/profile_screen.dart
@@ -0,0 +1,47 @@
+import 'package:comwell_key_app/common/components/shimmer_loader/profile_shimmer_loader.dart';
+import 'package:comwell_key_app/presentation/app/bloc/profile_cubit.dart';
+import 'package:comwell_key_app/presentation/screens/profile/components/error_page_widget.dart';
+import 'package:comwell_key_app/presentation/screens/profile/components/profile_page_widget.dart';
+import 'package:concierge/presentation/theme/app_colors.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter_bloc/flutter_bloc.dart';
+
+class ProfileScreen extends StatelessWidget {
+ const ProfileScreen({super.key});
+
+ @override
+ Widget build(BuildContext context) {
+ return BlocBuilder<ProfileCubit, ProfileState>(
+ builder: (context, state) {
+ final cubit = context.read<ProfileCubit>();
+ return MultiBlocListener(
+ listeners: [
+ BlocListener<ProfileCubit, ProfileState>(
+ listenWhen: (prev, curr) => prev.isLoading && !curr.isLoading && curr.error.isError,
+ listener: (context, state) {
+ // context.showErrorSnackBar(state.errorMessage);
+ },
+ ),
+ ],
+ child: Scaffold(
+ backgroundColor: AppColors.sandColor[20],
+ body: BlocBuilder<ProfileCubit, ProfileState>(
+ builder: (context, state) {
+ if (state.isLoading) {
+ return const Padding(
+ padding: EdgeInsets.symmetric(horizontal: 16.0, vertical: 40.0),
+ child: ProfileShimmerLoader(),
+ );
+ } else if (state.error.isError) {
+ return const ErrorPageWidget();
+ } else {
+ return ProfilePageWidget(cubit: cubit);
+ }
+ },
+ ),
+ ),
+ );
+ },
+ );
+ }
+}
diff --git a/comwell_key_app/lib/profile/components/card_content_widget.dart b/comwell_key_app/lib/profile/components/card_content_widget.dart
deleted file mode 100644
index d28d2d59..00000000
--- a/comwell_key_app/lib/profile/components/card_content_widget.dart
+++ /dev/null
@@ -1,94 +0,0 @@
-import 'package:comwell_key_app/presentation/app/bloc/profile_cubit.dart';
-import 'package:comwell_key_app/utils/l10n_utils.dart';
-import 'package:flutter/material.dart';
-
-class CardContentWidget extends StatelessWidget {
- final ProfileCubit cubit;
- final bool isActive;
-
- const CardContentWidget({super.key, required this.cubit, required this.isActive});
-
- @override
- Widget build(BuildContext context) {
- final theme = Theme.of(context);
- final user = cubit.state.user!;
-
- return SizedBox(
- width: double.infinity,
- height: double.infinity,
- child: Stack(
- children: [
- Positioned(
- top: 20,
- left: 20,
- child: Container(
- padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 6),
- decoration: BoxDecoration(
- color: Theme.of(context).colorScheme.surface,
- borderRadius: BorderRadius.circular(32),
- ),
- child: Text(
- isActive ? 'Comwell Club' : context.strings.comwell_club_inactive,
- style: theme.textTheme.bodySmall!.copyWith(
- color: Theme.of(context).colorScheme.onSurface,
- fontWeight: FontWeight.w600,
- ),
- ),
- ),
- ),
- Positioned(
- bottom: 20,
- left: 20,
- child: Column(
- crossAxisAlignment: CrossAxisAlignment.start,
- children: [
- Text(
- 'Navn',
- style: TextStyle(
- color: isActive ? Colors.white : Theme.of(context).colorScheme.onSurface,
- fontSize: 14,
- fontWeight: FontWeight.w400,
- ),
- ),
- Text(
- '${user.firstName} ${user.lastName}',
- style: TextStyle(
- color: isActive ? Colors.white : Theme.of(context).colorScheme.onSurface,
- fontSize: 16,
- fontWeight: FontWeight.w600,
- ),
- ),
- ],
- ),
- ),
- if (isActive)
- Positioned(
- bottom: 20,
- right: 20,
- child: Column(
- crossAxisAlignment: CrossAxisAlignment.end,
- children: [
- Text(
- context.strings.points,
- style: const TextStyle(
- color: Colors.white,
- fontSize: 14,
- fontWeight: FontWeight.w400,
- ),
- ),
- Text(
- '${user.points} ${context.strings.points}',
- style: const TextStyle(
- color: Colors.white,
- fontSize: 16,
- fontWeight: FontWeight.w600,
- ),
- ),
- ],
- ),
- ),
- ],
- ),
- );
- }
-}
diff --git a/comwell_key_app/lib/profile/components/comwell_club_container.dart b/comwell_key_app/lib/profile/components/comwell_club_container.dart
deleted file mode 100644
index 60dd2ad9..00000000
--- a/comwell_key_app/lib/profile/components/comwell_club_container.dart
+++ /dev/null
@@ -1,76 +0,0 @@
-import 'package:comwell_key_app/domain/models/user.dart';
-import 'package:comwell_key_app/profile/components/comwell_club_signup_bottom_sheet.dart';
-import 'package:comwell_key_app/presentation/app/bloc/profile_cubit.dart';
-import 'package:comwell_key_app/themes/light_theme.dart';
-import 'package:comwell_key_app/utils/l10n_utils.dart';
-import 'package:flutter/material.dart';
-import 'package:flutter_bloc/flutter_bloc.dart';
-
-class ComwellClubContainer extends StatelessWidget {
- final User user;
- final VoidCallback onSignupClick;
- const ComwellClubContainer({super.key, required this.user, required this.onSignupClick});
-
- @override
- Widget build(BuildContext context) {
- final cubit = context.read<ProfileCubit>();
-
- return Container(
- margin: const EdgeInsets.symmetric(horizontal: 16),
- padding: const EdgeInsets.symmetric(vertical: 16),
- decoration: BoxDecoration(
- color: sandColor[10],
- borderRadius: const BorderRadius.all(Radius.circular(10)),
- ),
- child: Row(
- mainAxisAlignment: MainAxisAlignment.spaceAround,
- children: [
- GestureDetector(
- onTap: () async {
- await showModalBottomSheet<void>(
- context: context,
- isScrollControlled: true,
- backgroundColor: Colors.white,
- builder: (_) => BlocProvider.value(
- value: cubit,
- child: ComwellClubSignupBottomSheet(user: user),
- ),
- );
- if (context.mounted) {
- onSignupClick();
- }
- },
- child: Column(
- crossAxisAlignment: CrossAxisAlignment.start,
- children: [
- Text(context.strings.become_cc_member_title,
- textAlign: TextAlign.start,
- style: const TextStyle(
- color: colorTertiary,
- fontSize: 16,
- fontWeight: FontWeight.w600)),
- SizedBox(
- width: 250,
- child: Text(
- context.strings.become_cc_member_subtitle,
- textAlign: TextAlign.start,
- maxLines: 4,
- style: const TextStyle(
- color: colorTertiary,
- fontSize: 14,
- fontWeight: FontWeight.w500),
- ),
- ),
- ],
- ),
- ),
- const Icon(
- Icons.chevron_right,
- color: colorTertiary,
- size: 24,
- ),
- ],
- ),
- );
- }
-}
diff --git a/comwell_key_app/lib/profile/components/comwell_club_signup_bottom_sheet.dart b/comwell_key_app/lib/profile/components/comwell_club_signup_bottom_sheet.dart
deleted file mode 100644
index 902075af..00000000
--- a/comwell_key_app/lib/profile/components/comwell_club_signup_bottom_sheet.dart
+++ /dev/null
@@ -1,295 +0,0 @@
-import 'package:comwell_key_app/common/components/round_icon_button.dart';
-import 'package:comwell_key_app/domain/models/user.dart';
-import 'package:comwell_key_app/presentation/app/bloc/profile_cubit.dart';
-import 'package:comwell_key_app/presentation/screens/profile_settings/components/comwell_text_field.dart';
-import 'package:comwell_key_app/profile/utils/constants.dart';
-import 'package:comwell_key_app/profile/utils/urls.dart';
-import 'package:comwell_key_app/domain/models/address.dart';
-import 'package:comwell_key_app/themes/light_theme.dart';
-import 'package:comwell_key_app/utils/l10n_utils.dart';
-import 'package:flutter/gestures.dart';
-import 'package:flutter/material.dart';
-import 'package:flutter_bloc/flutter_bloc.dart';
-import 'package:go_router/go_router.dart';
-import 'package:url_launcher/url_launcher.dart';
-
-class ComwellClubSignupBottomSheet extends StatefulWidget {
- final User user;
-
- const ComwellClubSignupBottomSheet({super.key, required this.user});
-
- @override
- State<ComwellClubSignupBottomSheet> createState() => _ComwellClubSignupBottomSheetState();
-}
-
-class _ComwellClubSignupBottomSheetState extends State<ComwellClubSignupBottomSheet> {
- late final TextEditingController _postNumberController;
- String _selectedGender = '';
-
- @override
- void initState() {
- super.initState();
- _postNumberController = TextEditingController(text: widget.user.address.zipCode);
- }
-
- @override
- void dispose() {
- _postNumberController.dispose();
- super.dispose();
- }
-
- @override
- Widget build(BuildContext context) {
- final theme = Theme.of(context);
- final cubit = context.read<ProfileCubit>();
- return Wrap(
- children: [
- Padding(
- padding: MediaQuery.of(context).viewInsets,
- child: Container(
- decoration: const BoxDecoration(
- color: Colors.white,
- borderRadius: BorderRadius.only(
- topLeft: Radius.circular(24),
- topRight: Radius.circular(24),
- ),
- ),
- height:
- MediaQuery.of(context).copyWith(viewInsets: EdgeInsets.zero).size.height *
- ComwellClubConstants.imageHeightRatio,
- child: Column(
- crossAxisAlignment: CrossAxisAlignment.start,
- children: [
- Padding(
- padding: const EdgeInsets.only(top: 40, left: 16),
- child: Container(
- height: 47,
- color: Colors.white,
- child: Stack(
- children: [
- Row(
- mainAxisAlignment: MainAxisAlignment.spaceBetween,
- children: [
- Text(
- context.strings.comwell_club_dialog_title,
- style: theme.textTheme.headlineLarge,
- ),
- RoundIconButton(
- icon: 'assets/icons/close-icon.svg',
- color: sandColor[20]!,
- onPressed: () {
- Navigator.pop(context);
- },
- ),
- ],
- ),
- ],
- ),
- ),
- ),
- const SizedBox(height: 24),
- Padding(
- padding: const EdgeInsets.symmetric(horizontal: 16),
- child: ComwellTextField(
- fieldName: context.strings.postal_code,
- initialValue: widget.user.address.zipCode,
- readOnly: false,
- controller: _postNumberController,
- ),
- ),
- const SizedBox(height: 16),
- Padding(
- padding: const EdgeInsets.symmetric(horizontal: 16),
- child: Container(
- height: 62,
- decoration: BoxDecoration(
- borderRadius: BorderRadius.circular(8),
- border: Border.all(color: colorDivider),
- ),
- child: DropdownButtonHideUnderline(
- child: DropdownButton<String>(
- value: _selectedGender.isEmpty ? null : _selectedGender,
- isExpanded: true,
- dropdownColor: Colors.white,
- alignment: Alignment.centerLeft,
- padding: const EdgeInsets.symmetric(horizontal: 16),
- hint: Text(
- context.strings.gender,
- style: theme.textTheme.headlineSmall,
- ),
- items: [
- DropdownMenuItem(
- value: "Male",
- child: Text(
- context.strings.male,
- style: theme.textTheme.headlineSmall,
- ),
- ),
- DropdownMenuItem(
- value: "Female",
- child: Text(
- context.strings.female,
- style: theme.textTheme.headlineSmall,
- ),
- ),
- DropdownMenuItem(
- value: "Other",
- child: Text(
- context.strings.not_specified,
- style: theme.textTheme.headlineSmall,
- ),
- ),
- ],
- onChanged: (String? value) {
- if (value != null) {
- setState(() {
- _selectedGender = value;
- });
- }
- },
- ),
- ),
- ),
- ),
- const SizedBox(height: 16),
-
- const SizedBox(height: 10),
- Padding(
- padding: const EdgeInsets.symmetric(horizontal: 16),
- child: Row(
- children: [
- Checkbox(
- value: cubit.state.isToSAccepted,
- onChanged: (bool? value) {
- setState(() {
- cubit.onToSClick(value);
- });
- },
- ),
- Expanded(
- child: Row(
- children: [
- Expanded(
- child: RichText(
- text: TextSpan(
- children: <TextSpan>[
- TextSpan(
- text: context.strings.tos_accept,
- style: TextStyle(
- fontSize: theme.textTheme.bodySmall!.fontSize,
- color: theme.textTheme.bodySmall!.color,
- fontWeight: FontWeight.w300,
- ),
- ),
- TextSpan(
- text: context.strings.tos_accept_link,
- recognizer: TapGestureRecognizer()
- ..onTap = () {
- launchUrl(Uri.parse(ComwellUrls.clubRules));
- },
- style: TextStyle(
- fontSize: theme.textTheme.bodySmall!.fontSize,
- color: sandColor[80],
- decoration: TextDecoration.underline,
- ),
- ),
- ],
- ),
- ),
- ),
- ],
- ),
- ),
- ],
- ),
- ),
- const SizedBox(height: 8),
- Padding(
- padding: const EdgeInsets.symmetric(horizontal: 16),
- child: Row(
- children: [
- Checkbox(
- value: cubit.state.isNewsletterAccepted,
- onChanged: (bool? value) {
- setState(() {
- cubit.onNewsletterClick(value);
- });
- },
- ),
- Expanded(
- child: RichText(
- text: TextSpan(
- children: <TextSpan>[
- TextSpan(
- text: context.strings.newsletter_accept,
- style: TextStyle(
- fontSize: theme.textTheme.bodySmall!.fontSize,
- color: theme.textTheme.bodySmall!.color,
- fontWeight: FontWeight.w300,
- ),
- ),
- TextSpan(
- text: context.strings.read_more,
- recognizer: TapGestureRecognizer()
- ..onTap = () {
- launchUrl(Uri.parse(ComwellUrls.clubPermission));
- },
- style: TextStyle(
- fontSize: theme.textTheme.bodySmall!.fontSize,
- color: sandColor[80],
- decoration: TextDecoration.underline,
- ),
- ),
- ],
- ),
- ),
- ),
- ],
- ),
- ),
- const SizedBox(height: 16),
- const Divider(color: colorDivider),
- const SizedBox(height: 16),
- Padding(
- padding: const EdgeInsets.symmetric(horizontal: 16),
- child: ElevatedButton(
- style: theme.elevatedButtonTheme.style?.copyWith(
- backgroundColor: WidgetStatePropertyAll(
- cubit.state.isToSAccepted && _selectedGender.isNotEmpty
- ? sandColor
- : Colors.grey[200],
- ),
- ),
- onPressed: () async {
- final response = await cubit.onComwellClubSignupClick(
- widget.user.copyWith(
- gender: _selectedGender,
- address: Address(
- zipCode: _postNumberController.text,
- street: '',
- city: '',
- country: '',
- ),
- ),
- );
-
- if (response == true && context.mounted) {
- context.pop();
- }
- },
- child: Text(
- context.strings.save,
- style: theme.textTheme.headlineSmall?.copyWith(
- color: cubit.state.isToSAccepted ? Colors.white : Colors.grey[400],
- ),
- ),
- ),
- ),
- ],
- ),
- ),
- ),
- ],
- );
- }
-}
diff --git a/comwell_key_app/lib/profile/components/error_page_widget.dart b/comwell_key_app/lib/profile/components/error_page_widget.dart
deleted file mode 100644
index 2a8a413d..00000000
--- a/comwell_key_app/lib/profile/components/error_page_widget.dart
+++ /dev/null
@@ -1,84 +0,0 @@
-import 'package:comwell_key_app/common/components/comwell_card_component.dart';
-import 'package:comwell_key_app/common/components/comwell_error_widget.dart';
-import 'package:comwell_key_app/common/components/round_icon_button.dart';
-import 'package:comwell_key_app/profile/components/logout_dialog_widget.dart';
-import 'package:comwell_key_app/presentation/app/bloc/profile_cubit.dart';
-import 'package:comwell_key_app/themes/light_theme.dart';
-import 'package:comwell_key_app/utils/l10n_utils.dart';
-import 'package:flutter/material.dart';
-import 'package:flutter_bloc/flutter_bloc.dart';
-import 'package:go_router/go_router.dart';
-
-class ErrorPageWidget extends StatelessWidget {
- const ErrorPageWidget({super.key});
-
- @override
- Widget build(BuildContext context) {
- return Column(
- crossAxisAlignment: CrossAxisAlignment.start,
- mainAxisAlignment: MainAxisAlignment.start,
- children: [
- Padding(
- padding: const EdgeInsets.only(top: 80),
- child: Container(
- alignment: Alignment.centerRight,
- child: RoundIconButton(
- icon: "assets/icons/close-icon.svg",
- color: Colors.white,
- onPressed: () {
- context.pop();
- }),
- ),
- ),
- Padding(
- padding: const EdgeInsets.all(16.0),
- child: Column(
- children: [
- ComwellCard(
- content: const SizedBox.shrink(),
- backgroundColor: sandColor[10]!),
- ],
- ),
- ),
- const SizedBox(height: 10),
- Expanded(
- child: Container(
- decoration: BoxDecoration(
- color: Colors.white,
- border: Border.all(color: colorDivider),
- ),
- padding: const EdgeInsets.symmetric(horizontal: 16.0),
- child: Column(
- children: [
- ComwellErrorWidget(
- title: context.strings.profile_error_title,
- subtitle: context.strings.profile_error_subtitle,
- border: true),
- const SizedBox(height: 30),
- Center(
- child: OutlinedButton(
- style: OutlinedButton.styleFrom(
- side: const BorderSide(color: colorDivider),
- ),
- onPressed: () {
- showDialog<void>(
- context: context,
- builder: (context) => LogoutDialogWidget(
- cubit: context.read<ProfileCubit>(),
- ),
- );
- },
- child: Text(
- context.strings.logout_profile_menu,
- style: const TextStyle(color: colorGrey),
- ),
- ),
- ),
- ],
- ),
- ),
- ),
- ],
- );
- }
-}
diff --git a/comwell_key_app/lib/profile/components/logout_dialog_widget.dart b/comwell_key_app/lib/profile/components/logout_dialog_widget.dart
deleted file mode 100644
index 3f3b13b8..00000000
--- a/comwell_key_app/lib/profile/components/logout_dialog_widget.dart
+++ /dev/null
@@ -1,81 +0,0 @@
-import 'package:comwell_key_app/presentation/app/bloc/profile_cubit.dart';
-import 'package:comwell_key_app/routing/app_routes.dart';
-import 'package:comwell_key_app/utils/l10n_utils.dart';
-import 'package:flutter/material.dart';
-import 'package:go_router/go_router.dart';
-
-class LogoutDialogWidget extends StatelessWidget {
- final ProfileCubit cubit;
- const LogoutDialogWidget({super.key, required this.cubit});
-
- @override
- Widget build(BuildContext context) {
- final theme = Theme.of(context);
-
- return Dialog(
- shape: RoundedRectangleBorder(
- borderRadius: BorderRadius.circular(20),
- ),
- child: Padding(
- padding: const EdgeInsets.all(24.0),
- child: Column(
- mainAxisSize: MainAxisSize.min,
- children: [
- Text(
- context.strings.logout_dialog_title,
- textAlign: TextAlign.center,
- style: TextStyle(
- color: Theme.of(context).colorScheme.onSurface,
- fontSize: 18,
- fontWeight: FontWeight.w600,
- ),
- ),
- const SizedBox(height: 24),
- SizedBox(
- width: double.infinity,
- child: ElevatedButton(
- style: theme.elevatedButtonTheme.style?.copyWith(
- padding: const WidgetStatePropertyAll(
- EdgeInsets.symmetric(vertical: 16)),
- ),
- onPressed: () {
- cubit.logOutPressed();
- context.go(AppRoutes.login);
- },
- child: Text(
- context.strings.logout_profile_menu,
- style: TextStyle(
- fontSize: 16,
- fontWeight: FontWeight.w600,
- color: Theme.of(context).colorScheme.surface,
- ),
- ),
- ),
- ),
- const SizedBox(height: 12),
- SizedBox(
- width: double.infinity,
- child: OutlinedButton(
- style: OutlinedButton.styleFrom(
- side: BorderSide(color: Colors.grey[400]!),
- padding: const EdgeInsets.symmetric(vertical: 16),
- ),
- onPressed: () {
- Navigator.of(context).pop();
- },
- child: Text(
- context.strings.cancel,
- style: TextStyle(
- fontSize: 16,
- fontWeight: FontWeight.w600,
- color: Theme.of(context).colorScheme.onSurface,
- ),
- ),
- ),
- ),
- ],
- ),
- ),
- );
- }
-}
diff --git a/comwell_key_app/lib/profile/components/profile_page_widget.dart b/comwell_key_app/lib/profile/components/profile_page_widget.dart
deleted file mode 100644
index dff00027..00000000
--- a/comwell_key_app/lib/profile/components/profile_page_widget.dart
+++ /dev/null
@@ -1,183 +0,0 @@
-import 'package:comwell_key_app/.generated/assets/assets.gen.dart';
-import 'package:comwell_key_app/common/components/comwell_card_component.dart';
-import 'package:comwell_key_app/common/components/round_icon_button.dart';
-import 'package:comwell_key_app/presentation/screens/permission_overview/permission_overview_route.dart';
-import 'package:comwell_key_app/profile/components/card_content_widget.dart';
-import 'package:comwell_key_app/profile/components/comwell_club_container.dart';
-import 'package:comwell_key_app/profile/components/logout_dialog_widget.dart';
-import 'package:comwell_key_app/profile/components/profile_settings_item.dart';
-import 'package:comwell_key_app/presentation/app/bloc/profile_cubit.dart';
-import 'package:comwell_key_app/routing/app_routes.dart';
-import 'package:comwell_key_app/themes/app_spaces.dart';
-import 'package:comwell_key_app/themes/light_theme.dart';
-import 'package:comwell_key_app/utils/l10n_utils.dart';
-import 'package:flutter/material.dart';
-import 'package:flutter_bloc/flutter_bloc.dart';
-import 'package:go_router/go_router.dart';
-import 'package:url_launcher/url_launcher.dart';
-
-class ProfilePageWidget extends StatelessWidget {
- final ProfileCubit cubit;
-
- const ProfilePageWidget({super.key, required this.cubit});
-
- @override
- Widget build(BuildContext context) {
- final user = cubit.state.user;
- final isActive = cubit.state.user?.isClubMember == true;
-
- return SingleChildScrollView(
- child: Column(
- children: [
- Padding(
- padding: const EdgeInsets.only(top: 60, right: 10),
- child: Container(
- alignment: Alignment.centerRight,
- child: RoundIconButton(
- icon: "assets/icons/close-icon.svg",
- color: Colors.white,
- onPressed: () {
- context.pop();
- },
- ),
- ),
- ),
- Padding(
- padding: const EdgeInsets.all(16.0),
- child: Column(
- children: [
- ComwellCard(
- content: CardContentWidget(cubit: cubit, isActive: isActive),
- backgroundColor: isActive ? sandColor : sandColor[10]!,
- ),
- ],
- ),
- ),
- const SizedBox(height: 10),
- Container(
- color: Colors.white,
- child: Column(
- mainAxisSize: MainAxisSize.min,
- children: [
- const SizedBox(height: 10),
- !isActive
- ? ComwellClubContainer(
- user: user!,
- onSignupClick: () {
- cubit.init();
- },
- )
- : const SizedBox(),
- const SizedBox(height: 10),
- profileSettingsItem(
- context,
- icon: Assets.icons.userCircleSvg.svg(),
- text: context.strings.profile_settings_profile_menu,
- trailingIcon: Icons.chevron_right,
- onTap: () async {
- await context.push(AppRoutes.profileSettings);
- cubit.init();
- },
- ),
- const Padding(
- padding: EdgeInsets.symmetric(horizontal: 16.0),
- child: Divider(color: colorDivider),
- ),
- profileSettingsItem(
- context,
- icon: Assets.icons.calendarPng.image(),
- text: context.strings.payment_card_profile_menu,
- trailingIcon: Icons.chevron_right,
- onTap: () {
- context.push("${AppRoutes.paymentCards}?needsScaffold=true");
- },
- ),
- const Padding(
- padding: EdgeInsets.symmetric(horizontal: 16.0),
- child: Divider(color: colorDivider),
- ),
- profileSettingsItem(
- context,
- icon: const Icon(Icons.check),
- trailingIcon: Icons.chevron_right,
- text: context.strings.permissions,
- onTap: () {
- PermissionOverviewRoute().push(context);
- },
- ),
- const Padding(
- padding: EdgeInsets.symmetric(horizontal: 16.0),
- child: Divider(color: colorDivider),
- ),
- profileSettingsItem(
- context,
- icon: Assets.icons.bell.image(),
- trailingIcon: Icons.chevron_right,
- text: context.strings.notifications_profile_menu,
- onTap: () {
- context.push(AppRoutes.notifications);
- },
- ),
- const Padding(
- padding: EdgeInsets.symmetric(horizontal: 16.0),
- child: Divider(color: colorDivider),
- ),
- const SizedBox(height: 10),
- if (isActive) ...[
- profileSettingsItem(
- context,
- icon: Assets.icons.cLogo.svg(),
- text: "Comwell Club",
- trailingIcon: Icons.open_in_new,
- onTap: () {
- launchUrl(Uri.parse('https://comwell.com/profile'));
- },
- ),
- const Padding(
- padding: EdgeInsets.symmetric(horizontal: 16.0),
- child: Divider(color: colorDivider),
- ),
- ],
- const SizedBox(height: 10),
- Center(
- child: OutlinedButton(
- style: OutlinedButton.styleFrom(
- side: const BorderSide(color: colorDivider),
- ),
- onPressed: () {
- showDialog<void>(
- context: context,
- builder: (context) => LogoutDialogWidget(
- cubit: context.read<ProfileCubit>(),
- ),
- );
- },
- child: Text(
- context.strings.logout_profile_menu,
- style: TextStyle(color: Colors.grey[600]),
- ),
- ),
- ),
- AppSpaces.gap16,
- FutureBuilder<String>(
- future: context.read<ProfileCubit>().getVersion(),
- builder: (context, snapshot) {
- if (snapshot.hasData) {
- return Text(
- snapshot.requireData,
- style: TextStyle(color: Colors.grey[500]),
- );
- }
- return const SizedBox.shrink();
- },
- ),
- AppSpaces.gap40,
-
- ],
- ),
- ),
- ],
- ),
- );
- }
-}
diff --git a/comwell_key_app/lib/profile/components/profile_settings_item.dart b/comwell_key_app/lib/profile/components/profile_settings_item.dart
deleted file mode 100644
index 23dbc0fd..00000000
--- a/comwell_key_app/lib/profile/components/profile_settings_item.dart
+++ /dev/null
@@ -1,26 +0,0 @@
-import 'package:comwell_key_app/themes/light_theme.dart';
-import 'package:flutter/material.dart';
-
-Widget profileSettingsItem(
- BuildContext context, {
- required Widget icon,
- required String text,
- required IconData trailingIcon,
- required VoidCallback onTap,
-}) {
- return ListTile(
- leading: Container(
- width: 36,
- height: 36,
- padding: const EdgeInsets.all(8.0),
- decoration: BoxDecoration(
- color: sandColor[20],
- shape: BoxShape.circle,
- ),
- child: icon,
- ),
- title: Text(text, style: const TextStyle(color: colorTertiary)),
- trailing: Icon(trailingIcon, color: colorTertiary, size: 24),
- onTap: onTap,
- );
-}
diff --git a/comwell_key_app/lib/profile/profile_page.dart b/comwell_key_app/lib/profile/profile_page.dart
deleted file mode 100644
index 7e99488b..00000000
--- a/comwell_key_app/lib/profile/profile_page.dart
+++ /dev/null
@@ -1,66 +0,0 @@
-import 'package:comwell_key_app/profile/components/error_page_widget.dart';
-import 'package:comwell_key_app/profile/components/profile_page_widget.dart';
-import 'package:comwell_key_app/presentation/app/bloc/profile_cubit.dart';
-import 'package:comwell_key_app/themes/light_theme.dart';
-import 'package:comwell_key_app/utils/secure_storage.dart';
-import 'package:flutter/material.dart';
-import 'package:flutter_bloc/flutter_bloc.dart';
-import '../common/components/shimmer_loader/profile_shimmer_loader.dart';
-
-class ProfilePage extends StatefulWidget {
- const ProfilePage({super.key});
-
- @override
- State<ProfilePage> createState() => _ProfilePageState();
-}
-
-class _ProfilePageState extends State<ProfilePage> with WidgetsBindingObserver {
- final SecureStorage secureStorage = SecureStorage();
- late final ProfileCubit _cubit = context.read<ProfileCubit>();
-
- @override
- void initState() {
- WidgetsBinding.instance.addObserver(this);
- super.initState();
- }
-
- @override
- void didChangeDependencies() {
- super.didChangeDependencies();
- _cubit.fetchRemoteProfile();
- }
-
- @override
- void dispose() {
- WidgetsBinding.instance.removeObserver(this);
- super.dispose();
- }
-
- @override
- void didChangeAppLifecycleState(AppLifecycleState state) {
- if (state == AppLifecycleState.resumed && mounted) {
- _cubit.fetchRemoteProfile();
- }
- }
-
- @override
- Widget build(BuildContext context) {
- return Scaffold(
- backgroundColor: sandColor[20],
- body: BlocBuilder<ProfileCubit, ProfileState>(
- builder: (context, state) {
- if (state.isLoading) {
- return const Padding(
- padding: EdgeInsets.symmetric(horizontal: 16.0, vertical: 40.0),
- child: ProfileShimmerLoader(),
- );
- } else if (state.error.isError) {
- return const ErrorPageWidget();
- } else {
- return ProfilePageWidget(cubit: _cubit);
- }
- },
- ),
- );
- }
-}
diff --git a/comwell_key_app/lib/profile/profile_route.dart b/comwell_key_app/lib/profile/profile_route.dart
deleted file mode 100644
index eab94e9e..00000000
--- a/comwell_key_app/lib/profile/profile_route.dart
+++ /dev/null
@@ -1,10 +0,0 @@
-import 'package:comwell_key_app/profile/profile_page.dart';
-import 'package:comwell_key_app/routing/app_routes.dart';
-import 'package:go_router/go_router.dart';
-
-final profileRoute = GoRoute(
- path: AppRoutes.profile,
- builder: (context, state) {
- return const ProfilePage();
- },
-);
diff --git a/comwell_key_app/lib/profile/utils/constants.dart b/comwell_key_app/lib/profile/utils/constants.dart
deleted file mode 100644
index a9665db6..00000000
--- a/comwell_key_app/lib/profile/utils/constants.dart
+++ /dev/null
@@ -1,7 +0,0 @@
-class ComwellClubConstants {
- static const double imageHeightRatio = 0.7;
-}
-
-const String merchantId = "merchant.ComwellHotelsECOM";
-const String merchantName = "Comwell";
-
diff --git a/comwell_key_app/lib/profile/utils/urls.dart b/comwell_key_app/lib/profile/utils/urls.dart
deleted file mode 100644
index 9270906a..00000000
--- a/comwell_key_app/lib/profile/utils/urls.dart
+++ /dev/null
@@ -1,6 +0,0 @@
-class ComwellUrls {
- static const String clubRules = 'https://comwell.com/club/club-regler';
- static const String clubPermission = 'https://comwell.com/club/club-permission';
- static const String comwellWebsite = 'https://comwell.com/';
- static const String termsAndConditions = 'https://comwell.com/en/about-comwell/trade-conditions';
-}
diff --git a/comwell_key_app/lib/routing/app_router.dart b/comwell_key_app/lib/routing/app_router.dart
index c7ca2db1..f9d0800f 100644
--- a/comwell_key_app/lib/routing/app_router.dart
+++ b/comwell_key_app/lib/routing/app_router.dart
@@ -12,6 +12,7 @@ import 'package:comwell_key_app/presentation/screens/concierge/concierge_route.d
import 'package:comwell_key_app/presentation/screens/notifications/notifications_route.dart';
import 'package:comwell_key_app/presentation/screens/payment_processing/payment_processing_route.dart';
import 'package:comwell_key_app/presentation/screens/permission_overview/permission_overview_route.dart';
+import 'package:comwell_key_app/presentation/screens/profile/profile_route.dart';
import 'package:comwell_key_app/presentation/screens/profile_settings/profile_settings_route.dart';
import 'package:comwell_key_app/presentation/screens/room_info/room_info_route.dart';
import 'package:comwell_key_app/contact/contact_route.dart';
@@ -21,7 +22,6 @@ import 'package:comwell_key_app/key/key_route.dart';
import 'package:comwell_key_app/overview/overview_route.dart';
import 'package:comwell_key_app/presentation/screens/past_cancelled_booking_details/past_cancelled_booking_detail_route.dart';
import 'package:comwell_key_app/presentation/screens/webview/webview_route.dart';
-import 'package:comwell_key_app/profile/profile_route.dart';
import 'package:comwell_key_app/routing/app_routes.dart';
import 'package:comwell_key_app/routing/go_router_observer.dart';
import 'package:comwell_key_app/share/share_booking_route.dart';
@@ -81,8 +81,8 @@ final router = GoRouter(
$internetDisabledRoute,
$permissionOverviewRoute,
$profileSettingsRoute,
+ $profileRoute,
overviewRoute,
- profileRoute,
changePasswordRoute,
webviewRoute,
pastCancelledBookingDetailsRoute,
diff --git a/comwell_key_app/lib/up_sales/pages/up_sale_confirmation_page.dart b/comwell_key_app/lib/up_sales/pages/up_sale_confirmation_page.dart
index d49cc920..4707f4d6 100644
--- a/comwell_key_app/lib/up_sales/pages/up_sale_confirmation_page.dart
+++ b/comwell_key_app/lib/up_sales/pages/up_sale_confirmation_page.dart
@@ -1,5 +1,4 @@
import 'package:comwell_key_app/common/components/comwell_app_bar.dart';
-import 'package:comwell_key_app/profile/utils/urls.dart';
import 'package:comwell_key_app/routing/app_routes.dart';
import 'package:comwell_key_app/up_sales/cubit/up_sales_cubit.dart';
import 'package:comwell_key_app/up_sales/cubit/up_sales_state.dart';
@@ -7,6 +6,7 @@ import 'package:comwell_key_app/up_sales/models/addon_upgrade.dart';
import 'package:comwell_key_app/up_sales/models/room_upgrade.dart';
import 'package:comwell_key_app/themes/light_theme.dart';
import 'package:comwell_key_app/utils/l10n_utils.dart';
+import 'package:comwell_key_app/utils/urls.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:go_router/go_router.dart';
diff --git a/comwell_key_app/lib/utils/constants.dart b/comwell_key_app/lib/utils/constants.dart
new file mode 100644
index 00000000..a9665db6
--- /dev/null
+++ b/comwell_key_app/lib/utils/constants.dart
@@ -0,0 +1,7 @@
+class ComwellClubConstants {
+ static const double imageHeightRatio = 0.7;
+}
+
+const String merchantId = "merchant.ComwellHotelsECOM";
+const String merchantName = "Comwell";
+
diff --git a/comwell_key_app/lib/utils/urls.dart b/comwell_key_app/lib/utils/urls.dart
new file mode 100644
index 00000000..460dfd46
--- /dev/null
+++ b/comwell_key_app/lib/utils/urls.dart
@@ -0,0 +1,6 @@
+abstract class ComwellUrls {
+ static const String clubRules = 'https://comwell.com/club/club-regler';
+ static const String clubPermission = 'https://comwell.com/club/club-permission';
+ static const String comwellWebsite = 'https://comwell.com/';
+ static const String termsAndConditions = 'https://comwell.com/en/about-comwell/trade-conditions';
+}