fix: user profile data
This commit is contained in:
parent
e5f84ee727
commit
43fe1b275a
|
@ -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,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
Loading…
Reference in New Issue