develop #1
|
@ -6,6 +6,7 @@ class UserEntity {
|
|||
final String? birthDate;
|
||||
final String? locale;
|
||||
final String? phone;
|
||||
final String? createdAt;
|
||||
|
||||
UserEntity({
|
||||
required this.id,
|
||||
|
@ -15,6 +16,7 @@ class UserEntity {
|
|||
this.birthDate,
|
||||
this.locale,
|
||||
this.phone,
|
||||
this.createdAt,
|
||||
});
|
||||
|
||||
factory UserEntity.fromJson(Map<String, dynamic> json) {
|
||||
|
@ -26,6 +28,7 @@ class UserEntity {
|
|||
birthDate: json['birth_date'],
|
||||
locale: json['locale'],
|
||||
phone: json['phone'],
|
||||
createdAt: json['created_at'],
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -37,6 +40,7 @@ class UserEntity {
|
|||
'pic_url': picUrl,
|
||||
'birth_date': birthDate,
|
||||
'locale': locale,
|
||||
"create_at": createdAt,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,12 +3,12 @@ class LoginResponseModel {
|
|||
final String? googleId;
|
||||
final String email;
|
||||
final String name;
|
||||
final DateTime? birthDate;
|
||||
final String? birthDate;
|
||||
final String? picUrl;
|
||||
final String? phone;
|
||||
final String locale;
|
||||
// final DateTime? createdAt;
|
||||
// final DateTime? updatedAt;
|
||||
final String? createdAt;
|
||||
// final String? updatedAt;
|
||||
|
||||
LoginResponseModel({
|
||||
this.id,
|
||||
|
@ -19,7 +19,7 @@ class LoginResponseModel {
|
|||
this.picUrl,
|
||||
this.phone,
|
||||
this.locale = "en-US",
|
||||
// this.createdAt,
|
||||
this.createdAt,
|
||||
// this.updatedAt,
|
||||
});
|
||||
|
||||
|
@ -29,12 +29,12 @@ class LoginResponseModel {
|
|||
googleId: json['google_id'],
|
||||
email: json['email'],
|
||||
name: json['name'],
|
||||
birthDate: json['birth_date'] != null ? DateTime.parse(json['birth_date']) : null,
|
||||
birthDate: json['birth_date'],
|
||||
picUrl: json['pic_url'],
|
||||
phone: json['phone'],
|
||||
locale: json['locale'] ?? 'en-US',
|
||||
// createdAt: json['created_at'] != null ? DateTime.parse(json['created_at']) : null,
|
||||
// updatedAt: json['updated_at'] != null ? DateTime.parse(json['updated_at']) : null,
|
||||
createdAt: json['created_at'],
|
||||
// updatedAt: json['updated_at'],
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -44,12 +44,12 @@ class LoginResponseModel {
|
|||
'google_id': googleId,
|
||||
'email': email,
|
||||
'name': name,
|
||||
'birth_date': birthDate?.toIso8601String(),
|
||||
'birth_date': birthDate,
|
||||
'pic_url': picUrl,
|
||||
'phone': phone,
|
||||
'locale': locale,
|
||||
// 'created_at': createdAt?.toIso8601String(),
|
||||
// 'updated_at': updatedAt?.toIso8601String(),
|
||||
'created_at': createdAt,
|
||||
// 'updated_at': updatedAt,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -149,6 +149,9 @@ class LoginController extends GetxController {
|
|||
email: response.email,
|
||||
picUrl: response.picUrl,
|
||||
locale: response.locale,
|
||||
birthDate: response.birthDate,
|
||||
createdAt: response.createdAt,
|
||||
phone: response.phone,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -59,7 +59,6 @@ class ProfileController extends GetxController {
|
|||
void onInit() {
|
||||
super.onInit();
|
||||
loadUserStat();
|
||||
// In a real app, you would load these from your API or local storage
|
||||
loadUserProfileData();
|
||||
}
|
||||
|
||||
|
@ -67,7 +66,9 @@ class ProfileController extends GetxController {
|
|||
try {
|
||||
birthDate.value = _userController.userData?.birthDate ?? "";
|
||||
phoneNumber.value = _userController.userData?.phone ?? "";
|
||||
// joinDate.value = _userController.userData?. ?? "";
|
||||
joinDate.value = _userController.userData?.createdAt ?? "";
|
||||
|
||||
print(_userController.userData!.toJson());
|
||||
} catch (e, 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),
|
||||
// _userHeader(),
|
||||
const SizedBox(height: 24),
|
||||
_statsCard(context: context, cardRadius: cardRadius),
|
||||
_statsCard(cardRadius: cardRadius),
|
||||
const SizedBox(height: 10),
|
||||
_profileDetails(context: context, cardRadius: cardRadius),
|
||||
_profileDetails(cardRadius: cardRadius),
|
||||
const SizedBox(height: 10),
|
||||
_settingsSection(context: context, cardRadius: cardRadius),
|
||||
_settingsSection(cardRadius: cardRadius),
|
||||
const SizedBox(height: 10),
|
||||
_legalSection(context: context, cardRadius: cardRadius),
|
||||
_legalSection(cardRadius: cardRadius),
|
||||
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,
|
||||
elevation: 1,
|
||||
shadowColor: AppColors.shadowPrimary,
|
||||
|
@ -106,15 +106,15 @@ class ProfileView extends GetView<ProfileController> {
|
|||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
||||
children: [
|
||||
_statChip(context.tr('total_quiz'), controller.data.value?.totalQuiz.toString() ?? '0'),
|
||||
_statChip(context.tr('total_solve'), controller.data.value?.totalSolve.toString() ?? '0'),
|
||||
_statChip(context.tr('avg_score'), '${controller.data.value?.avgScore ?? 100}%'),
|
||||
_statChip(tr('total_quiz'), controller.data.value?.totalQuiz.toString() ?? '0'),
|
||||
_statChip(tr('total_solve'), controller.data.value?.totalSolve.toString() ?? '0'),
|
||||
_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,
|
||||
elevation: 1,
|
||||
shadowColor: AppColors.shadowPrimary,
|
||||
|
@ -124,44 +124,44 @@ class ProfileView extends GetView<ProfileController> {
|
|||
child: Column(
|
||||
children: [
|
||||
SectionHeader(
|
||||
title: context.tr('personal_info'),
|
||||
title: tr('personal_info'),
|
||||
icon: LucideIcons.userCog,
|
||||
onEdit: controller.editProfile,
|
||||
),
|
||||
const Divider(height: 1),
|
||||
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(
|
||||
icon: LucideIcons.cake,
|
||||
label: context.tr('birth_date'),
|
||||
value: controller.birthDate.value ?? context.tr('not_set'),
|
||||
label: tr('birth_date'),
|
||||
value: controller.birthDate.value ?? tr('not_set'),
|
||||
),
|
||||
InfoRow(
|
||||
icon: LucideIcons.phone,
|
||||
label: context.tr('phone'),
|
||||
value: controller.phoneNumber.value ?? context.tr('not_set'),
|
||||
),
|
||||
InfoRow(
|
||||
icon: LucideIcons.mapPin,
|
||||
label: context.tr('location'),
|
||||
value: controller.location.value ?? context.tr('not_set'),
|
||||
label: tr('phone'),
|
||||
value: controller.phoneNumber.value ?? tr('not_set'),
|
||||
),
|
||||
// InfoRow(
|
||||
// icon: LucideIcons.mapPin,
|
||||
// label: tr('location'),
|
||||
// value: controller.location.value ?? tr('not_set'),
|
||||
// ),
|
||||
InfoRow(
|
||||
icon: LucideIcons.calendar,
|
||||
label: context.tr('joined'),
|
||||
value: controller.joinDate.value ?? context.tr('not_available'),
|
||||
),
|
||||
InfoRow(
|
||||
icon: LucideIcons.graduationCap,
|
||||
label: context.tr('education'),
|
||||
value: controller.education.value ?? context.tr('not_set'),
|
||||
label: tr('joined'),
|
||||
value: controller.joinDate.value ?? tr('not_available'),
|
||||
),
|
||||
// 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,
|
||||
elevation: 1,
|
||||
shadowColor: AppColors.shadowPrimary,
|
||||
|
@ -172,18 +172,18 @@ class ProfileView extends GetView<ProfileController> {
|
|||
children: [
|
||||
Padding(
|
||||
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),
|
||||
_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!,
|
||||
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,
|
||||
elevation: 1,
|
||||
shadowColor: AppColors.shadowPrimary,
|
||||
|
@ -194,14 +194,14 @@ class ProfileView extends GetView<ProfileController> {
|
|||
children: [
|
||||
Padding(
|
||||
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),
|
||||
_settingsTile(Get.context!, icon: LucideIcons.shield, title: context.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.helpCircle, title: context.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.info, title: context.tr('about_app'), onTap: () => _showAboutAppDialog(Get.context!)),
|
||||
_settingsTile(Get.context!, icon: LucideIcons.shield, title: tr('privacy_policy'), onTap: controller.openPrivacyPolicy),
|
||||
_settingsTile(Get.context!, icon: LucideIcons.fileText, title: tr('terms_of_service'), onTap: controller.openTermsOfService),
|
||||
_settingsTile(Get.context!, icon: LucideIcons.helpCircle, title: tr('help_center'), onTap: controller.openHelpCenter),
|
||||
_settingsTile(Get.context!, icon: LucideIcons.mail, title: tr('contact_us'), onTap: controller.contactSupport),
|
||||
_settingsTile(Get.context!, icon: LucideIcons.info, title: tr('about_app'), onTap: () => _showAboutAppDialog(Get.context!)),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
@ -211,7 +211,7 @@ class ProfileView extends GetView<ProfileController> {
|
|||
showDialog(
|
||||
context: context,
|
||||
builder: (_) => AlertDialog(
|
||||
title: Text(context.tr('select_language'), style: AppTextStyles.title),
|
||||
title: Text(tr('select_language'), style: AppTextStyles.title),
|
||||
content: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
|
@ -255,7 +255,7 @@ class ProfileView extends GetView<ProfileController> {
|
|||
const AppName(),
|
||||
const SizedBox(height: 16),
|
||||
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),
|
||||
Text(controller.appDescription.value, textAlign: TextAlign.center, style: AppTextStyles.body),
|
||||
const SizedBox(height: 16),
|
||||
|
@ -263,7 +263,7 @@ class ProfileView extends GetView<ProfileController> {
|
|||
],
|
||||
),
|
||||
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