fix: user profile data

This commit is contained in:
akhdanre 2025-05-25 22:05:55 +07:00
parent e5f84ee727
commit 43fe1b275a
5 changed files with 61 additions and 53 deletions

View File

@ -6,6 +6,7 @@ class UserEntity {
final String? birthDate; final String? birthDate;
final String? locale; final String? locale;
final String? phone; final String? phone;
final String? createdAt;
UserEntity({ UserEntity({
required this.id, required this.id,
@ -15,6 +16,7 @@ class UserEntity {
this.birthDate, this.birthDate,
this.locale, this.locale,
this.phone, this.phone,
this.createdAt,
}); });
factory UserEntity.fromJson(Map<String, dynamic> json) { factory UserEntity.fromJson(Map<String, dynamic> json) {
@ -26,6 +28,7 @@ class UserEntity {
birthDate: json['birth_date'], birthDate: json['birth_date'],
locale: json['locale'], locale: json['locale'],
phone: json['phone'], phone: json['phone'],
createdAt: json['created_at'],
); );
} }
@ -37,6 +40,7 @@ class UserEntity {
'pic_url': picUrl, 'pic_url': picUrl,
'birth_date': birthDate, 'birth_date': birthDate,
'locale': locale, 'locale': locale,
"create_at": createdAt,
}; };
} }
} }

View File

@ -3,12 +3,12 @@ class LoginResponseModel {
final String? googleId; final String? googleId;
final String email; final String email;
final String name; final String name;
final DateTime? birthDate; final String? birthDate;
final String? picUrl; final String? picUrl;
final String? phone; final String? phone;
final String locale; final String locale;
// final DateTime? createdAt; final String? createdAt;
// final DateTime? updatedAt; // final String? updatedAt;
LoginResponseModel({ LoginResponseModel({
this.id, this.id,
@ -19,7 +19,7 @@ class LoginResponseModel {
this.picUrl, this.picUrl,
this.phone, this.phone,
this.locale = "en-US", this.locale = "en-US",
// this.createdAt, this.createdAt,
// this.updatedAt, // this.updatedAt,
}); });
@ -29,12 +29,12 @@ class LoginResponseModel {
googleId: json['google_id'], googleId: json['google_id'],
email: json['email'], email: json['email'],
name: json['name'], name: json['name'],
birthDate: json['birth_date'] != null ? DateTime.parse(json['birth_date']) : null, birthDate: json['birth_date'],
picUrl: json['pic_url'], picUrl: json['pic_url'],
phone: json['phone'], phone: json['phone'],
locale: json['locale'] ?? 'en-US', locale: json['locale'] ?? 'en-US',
// createdAt: json['created_at'] != null ? DateTime.parse(json['created_at']) : null, createdAt: json['created_at'],
// updatedAt: json['updated_at'] != null ? DateTime.parse(json['updated_at']) : null, // updatedAt: json['updated_at'],
); );
} }
@ -44,12 +44,12 @@ class LoginResponseModel {
'google_id': googleId, 'google_id': googleId,
'email': email, 'email': email,
'name': name, 'name': name,
'birth_date': birthDate?.toIso8601String(), 'birth_date': birthDate,
'pic_url': picUrl, 'pic_url': picUrl,
'phone': phone, 'phone': phone,
'locale': locale, 'locale': locale,
// 'created_at': createdAt?.toIso8601String(), 'created_at': createdAt,
// 'updated_at': updatedAt?.toIso8601String(), // 'updated_at': updatedAt,
}; };
} }
} }

View File

@ -149,6 +149,9 @@ class LoginController extends GetxController {
email: response.email, email: response.email,
picUrl: response.picUrl, picUrl: response.picUrl,
locale: response.locale, locale: response.locale,
birthDate: response.birthDate,
createdAt: response.createdAt,
phone: response.phone,
); );
} }
} }

View File

@ -59,7 +59,6 @@ class ProfileController extends GetxController {
void onInit() { void onInit() {
super.onInit(); super.onInit();
loadUserStat(); loadUserStat();
// In a real app, you would load these from your API or local storage
loadUserProfileData(); loadUserProfileData();
} }
@ -67,7 +66,9 @@ class ProfileController extends GetxController {
try { try {
birthDate.value = _userController.userData?.birthDate ?? ""; birthDate.value = _userController.userData?.birthDate ?? "";
phoneNumber.value = _userController.userData?.phone ?? ""; phoneNumber.value = _userController.userData?.phone ?? "";
// joinDate.value = _userController.userData?. ?? ""; joinDate.value = _userController.userData?.createdAt ?? "";
print(_userController.userData!.toJson());
} catch (e, stackTrace) { } catch (e, stackTrace) {
logC.e("Failed to load user profile data: $e", stackTrace: stackTrace); logC.e("Failed to load user profile data: $e", stackTrace: stackTrace);
} }

View File

@ -32,13 +32,13 @@ class ProfileView extends GetView<ProfileController> {
// const SizedBox(height: 16), // const SizedBox(height: 16),
// _userHeader(), // _userHeader(),
const SizedBox(height: 24), const SizedBox(height: 24),
_statsCard(context: context, cardRadius: cardRadius), _statsCard(cardRadius: cardRadius),
const SizedBox(height: 10), const SizedBox(height: 10),
_profileDetails(context: context, cardRadius: cardRadius), _profileDetails(cardRadius: cardRadius),
const SizedBox(height: 10), const SizedBox(height: 10),
_settingsSection(context: context, cardRadius: cardRadius), _settingsSection(cardRadius: cardRadius),
const SizedBox(height: 10), const SizedBox(height: 10),
_legalSection(context: context, cardRadius: cardRadius), _legalSection(cardRadius: cardRadius),
const SizedBox(height: 20), const SizedBox(height: 20),
], ],
), ),
@ -96,7 +96,7 @@ class ProfileView extends GetView<ProfileController> {
// ], // ],
// ); // );
Widget _statsCard({required BuildContext context, required BorderRadius cardRadius}) => Card( Widget _statsCard({required BorderRadius cardRadius}) => Card(
color: Colors.white, color: Colors.white,
elevation: 1, elevation: 1,
shadowColor: AppColors.shadowPrimary, shadowColor: AppColors.shadowPrimary,
@ -106,15 +106,15 @@ class ProfileView extends GetView<ProfileController> {
child: Row( child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly, mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [ children: [
_statChip(context.tr('total_quiz'), controller.data.value?.totalQuiz.toString() ?? '0'), _statChip(tr('total_quiz'), controller.data.value?.totalQuiz.toString() ?? '0'),
_statChip(context.tr('total_solve'), controller.data.value?.totalSolve.toString() ?? '0'), _statChip(tr('total_solve'), controller.data.value?.totalSolve.toString() ?? '0'),
_statChip(context.tr('avg_score'), '${controller.data.value?.avgScore ?? 100}%'), _statChip(tr('avg_score'), '${controller.data.value?.avgScore ?? 100}%'),
], ],
), ),
), ),
); );
Widget _profileDetails({required BuildContext context, required BorderRadius cardRadius}) => Card( Widget _profileDetails({required BorderRadius cardRadius}) => Card(
color: Colors.white, color: Colors.white,
elevation: 1, elevation: 1,
shadowColor: AppColors.shadowPrimary, shadowColor: AppColors.shadowPrimary,
@ -124,44 +124,44 @@ class ProfileView extends GetView<ProfileController> {
child: Column( child: Column(
children: [ children: [
SectionHeader( SectionHeader(
title: context.tr('personal_info'), title: tr('personal_info'),
icon: LucideIcons.userCog, icon: LucideIcons.userCog,
onEdit: controller.editProfile, onEdit: controller.editProfile,
), ),
const Divider(height: 1), const Divider(height: 1),
const SizedBox(height: 20), const SizedBox(height: 20),
InfoRow(icon: LucideIcons.user, label: context.tr('full_name'), value: controller.userName.value), InfoRow(icon: LucideIcons.user, label: tr('full_name'), value: controller.userName.value),
InfoRow( InfoRow(
icon: LucideIcons.cake, icon: LucideIcons.cake,
label: context.tr('birth_date'), label: tr('birth_date'),
value: controller.birthDate.value ?? context.tr('not_set'), value: controller.birthDate.value ?? tr('not_set'),
), ),
InfoRow( InfoRow(
icon: LucideIcons.phone, icon: LucideIcons.phone,
label: context.tr('phone'), label: tr('phone'),
value: controller.phoneNumber.value ?? context.tr('not_set'), value: controller.phoneNumber.value ?? tr('not_set'),
),
InfoRow(
icon: LucideIcons.mapPin,
label: context.tr('location'),
value: controller.location.value ?? context.tr('not_set'),
), ),
// InfoRow(
// icon: LucideIcons.mapPin,
// label: tr('location'),
// value: controller.location.value ?? tr('not_set'),
// ),
InfoRow( InfoRow(
icon: LucideIcons.calendar, icon: LucideIcons.calendar,
label: context.tr('joined'), label: tr('joined'),
value: controller.joinDate.value ?? context.tr('not_available'), value: controller.joinDate.value ?? tr('not_available'),
),
InfoRow(
icon: LucideIcons.graduationCap,
label: context.tr('education'),
value: controller.education.value ?? context.tr('not_set'),
), ),
// InfoRow(
// icon: LucideIcons.graduationCap,
// label: tr('education'),
// value: controller.education.value ?? tr('not_set'),
// ),
], ],
), ),
), ),
); );
Widget _settingsSection({required BuildContext context, required BorderRadius cardRadius}) => Card( Widget _settingsSection({required BorderRadius cardRadius}) => Card(
color: Colors.white, color: Colors.white,
elevation: 1, elevation: 1,
shadowColor: AppColors.shadowPrimary, shadowColor: AppColors.shadowPrimary,
@ -172,18 +172,18 @@ class ProfileView extends GetView<ProfileController> {
children: [ children: [
Padding( Padding(
padding: const EdgeInsets.symmetric(horizontal: 15.0, vertical: 10), padding: const EdgeInsets.symmetric(horizontal: 15.0, vertical: 10),
child: SectionHeader(title: context.tr('settings'), icon: LucideIcons.settings), child: SectionHeader(title: tr('settings'), icon: LucideIcons.settings),
), ),
const Divider(height: 1), const Divider(height: 1),
_settingsTile(Get.context!, icon: LucideIcons.languages, title: context.tr('change_language'), onTap: () => _showLanguageDialog(Get.context!)), _settingsTile(Get.context!, icon: LucideIcons.languages, title: tr('change_language'), onTap: () => _showLanguageDialog(Get.context!)),
_settingsTile(Get.context!, _settingsTile(Get.context!,
icon: LucideIcons.logOut, title: context.tr('logout'), iconColor: Colors.red, textColor: Colors.red, onTap: controller.logout), icon: LucideIcons.logOut, title: tr('logout'), iconColor: Colors.red, textColor: Colors.red, onTap: controller.logout),
], ],
), ),
), ),
); );
Widget _legalSection({required BuildContext context, required BorderRadius cardRadius}) => Card( Widget _legalSection({required BorderRadius cardRadius}) => Card(
color: Colors.white, color: Colors.white,
elevation: 1, elevation: 1,
shadowColor: AppColors.shadowPrimary, shadowColor: AppColors.shadowPrimary,
@ -194,14 +194,14 @@ class ProfileView extends GetView<ProfileController> {
children: [ children: [
Padding( Padding(
padding: const EdgeInsets.symmetric(horizontal: 15.0, vertical: 10), padding: const EdgeInsets.symmetric(horizontal: 15.0, vertical: 10),
child: SectionHeader(title: context.tr('legal_and_support'), icon: LucideIcons.shieldQuestion), child: SectionHeader(title: tr('legal_and_support'), icon: LucideIcons.shieldQuestion),
), ),
const Divider(height: 1), const Divider(height: 1),
_settingsTile(Get.context!, icon: LucideIcons.shield, title: context.tr('privacy_policy'), onTap: controller.openPrivacyPolicy), _settingsTile(Get.context!, icon: LucideIcons.shield, title: tr('privacy_policy'), onTap: controller.openPrivacyPolicy),
_settingsTile(Get.context!, icon: LucideIcons.fileText, title: context.tr('terms_of_service'), onTap: controller.openTermsOfService), _settingsTile(Get.context!, icon: LucideIcons.fileText, title: tr('terms_of_service'), onTap: controller.openTermsOfService),
_settingsTile(Get.context!, icon: LucideIcons.helpCircle, title: context.tr('help_center'), onTap: controller.openHelpCenter), _settingsTile(Get.context!, icon: LucideIcons.helpCircle, title: tr('help_center'), onTap: controller.openHelpCenter),
_settingsTile(Get.context!, icon: LucideIcons.mail, title: context.tr('contact_us'), onTap: controller.contactSupport), _settingsTile(Get.context!, icon: LucideIcons.mail, title: tr('contact_us'), onTap: controller.contactSupport),
_settingsTile(Get.context!, icon: LucideIcons.info, title: context.tr('about_app'), onTap: () => _showAboutAppDialog(Get.context!)), _settingsTile(Get.context!, icon: LucideIcons.info, title: tr('about_app'), onTap: () => _showAboutAppDialog(Get.context!)),
], ],
), ),
), ),
@ -211,7 +211,7 @@ class ProfileView extends GetView<ProfileController> {
showDialog( showDialog(
context: context, context: context,
builder: (_) => AlertDialog( builder: (_) => AlertDialog(
title: Text(context.tr('select_language'), style: AppTextStyles.title), title: Text(tr('select_language'), style: AppTextStyles.title),
content: Column( content: Column(
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
children: [ children: [
@ -255,7 +255,7 @@ class ProfileView extends GetView<ProfileController> {
const AppName(), const AppName(),
const SizedBox(height: 16), const SizedBox(height: 16),
Text(controller.appName.value, style: AppTextStyles.title), Text(controller.appName.value, style: AppTextStyles.title),
Text("${context.tr('version')}: ${controller.appVersion.value}", style: AppTextStyles.caption), Text("${tr('version')}: ${controller.appVersion.value}", style: AppTextStyles.caption),
const SizedBox(height: 16), const SizedBox(height: 16),
Text(controller.appDescription.value, textAlign: TextAlign.center, style: AppTextStyles.body), Text(controller.appDescription.value, textAlign: TextAlign.center, style: AppTextStyles.body),
const SizedBox(height: 16), const SizedBox(height: 16),
@ -263,7 +263,7 @@ class ProfileView extends GetView<ProfileController> {
], ],
), ),
actions: [ actions: [
TextButton(onPressed: () => Navigator.of(context).pop(), child: Text(context.tr('close'), style: AppTextStyles.optionText)), TextButton(onPressed: () => Navigator.of(context).pop(), child: Text(tr('close'), style: AppTextStyles.optionText)),
], ],
), ),
); );