diff --git a/data/lib/api/user/user_models.dart b/data/lib/api/user/user_models.dart index 69525df0..d917ed62 100644 --- a/data/lib/api/user/user_models.dart +++ b/data/lib/api/user/user_models.dart @@ -5,6 +5,7 @@ import 'dart:convert'; import 'package:freezed_annotation/freezed_annotation.dart'; part 'user_models.freezed.dart'; + part 'user_models.g.dart'; @freezed @@ -39,6 +40,28 @@ class UserModel with _$UserModel { UserModel.fromJson(jsonDecode(json)); } +extension ProfileCompleteExtension on UserModel { + double get progress { + final fields = [ + profile_img_url, + name, + email, + location, + dob, + gender, + player_role, + batting_style, + bowling_style + ]; + + final completedFields = fields + .where((field) => field != null && field.toString().isNotEmpty) + .length; + + return completedFields / fields.length; + } +} + @JsonEnum(valueField: "value") enum UserGender { unknown(0), diff --git a/khelo/assets/locales/app_en.arb b/khelo/assets/locales/app_en.arb index 3fd97276..77abf480 100644 --- a/khelo/assets/locales/app_en.arb +++ b/khelo/assets/locales/app_en.arb @@ -680,9 +680,11 @@ "contact_support_attachment": "Attachment (if any)", "large_attachment_upload_error_text": "Oops! Your file exceeds the maximum allowed size of 25 MB. Please choose a smaller file and try again.", - "profile_complete_profile_btn_title": "Complete Profile", "profile_complete_your_profile_title": "Complete your profile", - "profile_complete_profile_description": "Enhance your profile by filling in the remaining details. Let's make it more comprehensive and appealing.", + "profile_complete_description_title": "Enhance your profile with more details to make it better!", + "profile_complete_add_profile_picture": "Add profile picture", + "profile_complete_add_personal_details": "Add personal details", + "profile_complete_add_playing_style": "Add playing style", "image_picker_choose_option_title": "Choose an option", "image_picker_camera_option_text": "Camera", diff --git a/khelo/lib/ui/flow/profile/components/complete_profile_progress.dart b/khelo/lib/ui/flow/profile/components/complete_profile_progress.dart new file mode 100644 index 00000000..c2b02e69 --- /dev/null +++ b/khelo/lib/ui/flow/profile/components/complete_profile_progress.dart @@ -0,0 +1,102 @@ +import 'package:data/api/user/user_models.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:khelo/domain/extensions/context_extensions.dart'; +import 'package:khelo/ui/app_route.dart'; +import 'package:style/animations/on_tap_scale.dart'; +import 'package:style/extensions/context_extensions.dart'; +import 'package:style/text/app_text_style.dart'; + +class CompleteProfileProgress extends ConsumerStatefulWidget { + final UserModel? user; + + const CompleteProfileProgress({super.key, this.user}); + + @override + ConsumerState createState() => + _CompleteProfileProgressState(); +} + +class _CompleteProfileProgressState + extends ConsumerState { + @override + Widget build(BuildContext context) { + if (widget.user?.profile_img_url != null && + widget.user?.gender != null && + widget.user?.player_role != null && + widget.user?.batting_style != null && + widget.user?.bowling_style != null) return const SizedBox(); + + return OnTapScale( + onTap: () => AppRoute.editProfile().push(context), + child: Container( + padding: const EdgeInsets.all(16), + margin: const EdgeInsets.only(top: 24), + decoration: BoxDecoration( + border: Border.all(color: context.colorScheme.outline), + borderRadius: BorderRadius.circular(16), + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + context.l10n.profile_complete_your_profile_title, + style: AppTextStyle.header4.copyWith( + color: context.colorScheme.textPrimary, + ), + ), + const SizedBox(height: 8), + Text( + context.l10n.profile_complete_description_title, + style: AppTextStyle.subtitle3.copyWith( + color: context.colorScheme.textSecondary, + ), + ), + const SizedBox(height: 16), + LinearProgressIndicator( + value: widget.user?.progress, + minHeight: 6, + borderRadius: BorderRadius.circular(12), + backgroundColor: context.colorScheme.outline, + valueColor: + AlwaysStoppedAnimation(context.colorScheme.primary), + ), + const SizedBox(height: 8), + if (widget.user?.profile_img_url == null) ...[ + _fieldStatus(context.l10n.profile_complete_add_profile_picture), + ], + if (widget.user?.dob == null || widget.user?.gender == null) ...[ + _fieldStatus(context.l10n.profile_complete_add_personal_details), + ], + if (widget.user?.player_role == null || + widget.user?.batting_style == null || + widget.user?.bowling_style == null) ...[ + _fieldStatus(context.l10n.profile_complete_add_playing_style), + ], + ], + ), + ), + ); + } + + Widget _fieldStatus(String title) { + return Padding( + padding: const EdgeInsets.symmetric(vertical: 8.0), + child: Row( + children: [ + Icon( + Icons.check_circle_rounded, + color: context.colorScheme.containerHigh, + ), + const SizedBox(width: 16), + Text( + title, + style: AppTextStyle.body1.copyWith( + color: context.colorScheme.textSecondary, + ), + ) + ], + ), + ); + } +} diff --git a/khelo/lib/ui/flow/profile/profile_screen.dart b/khelo/lib/ui/flow/profile/profile_screen.dart index a408d005..ffcbf85c 100644 --- a/khelo/lib/ui/flow/profile/profile_screen.dart +++ b/khelo/lib/ui/flow/profile/profile_screen.dart @@ -1,4 +1,3 @@ -import 'package:data/api/user/user_models.dart'; import 'package:data/storage/app_preferences.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; @@ -10,9 +9,9 @@ import 'package:khelo/components/error_snackbar.dart'; import 'package:khelo/components/image_avatar.dart'; import 'package:khelo/domain/extensions/context_extensions.dart'; import 'package:khelo/ui/app_route.dart'; +import 'package:khelo/ui/flow/profile/components/complete_profile_progress.dart'; import 'package:khelo/ui/flow/profile/profile_view_model.dart'; import 'package:style/animations/on_tap_scale.dart'; -import 'package:style/button/primary_button.dart'; import 'package:style/extensions/context_extensions.dart'; import 'package:style/text/app_text_style.dart'; @@ -38,8 +37,7 @@ class ProfileScreen extends ConsumerWidget { children: [ _userProfileView(context, state), if (state.currentUser != null) ...[ - const SizedBox(height: 24), - _inCompleteProfileView(context, state.currentUser!) + CompleteProfileProgress(user: state.currentUser!) ], const SizedBox(height: 24), Text( @@ -98,42 +96,6 @@ class ProfileScreen extends ConsumerWidget { ); } - Widget _inCompleteProfileView(BuildContext context, UserModel currentUser) { - if (currentUser.profile_img_url == null || - currentUser.batting_style == null || - currentUser.bowling_style == null) { - return Container( - padding: const EdgeInsets.all(24), - decoration: BoxDecoration( - border: Border.all(color: context.colorScheme.outline), - borderRadius: BorderRadius.circular(16)), - child: Column( - children: [ - Text( - context.l10n.profile_complete_your_profile_title, - textAlign: TextAlign.center, - style: AppTextStyle.header4 - .copyWith(color: context.colorScheme.textPrimary), - ), - const SizedBox(height: 16), - Text( - context.l10n.profile_complete_profile_description, - textAlign: TextAlign.center, - style: AppTextStyle.body1 - .copyWith(color: context.colorScheme.textSecondary), - ), - const SizedBox(height: 16), - PrimaryButton( - onPressed: () => AppRoute.editProfile().push(context), - context.l10n.profile_complete_profile_btn_title) - ], - ), - ); - } else { - return const SizedBox(); - } - } - Widget _settingsView( BuildContext context, ProfileViewNotifier notifier,