develop #1

Merged
akhdanre merged 104 commits from develop into main 2025-07-10 12:38:53 +07:00
5 changed files with 61 additions and 53 deletions
Showing only changes of commit 43fe1b275a - Show all commits

View File

@ -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,
};
}
}

View File

@ -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,
};
}
}

View File

@ -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,
);
}
}

View File

@ -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);
}

View File

@ -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)),
],
),
);