From ede385041e59c3b4f249fa0b5fd232cee6491a7e Mon Sep 17 00:00:00 2001 From: akhdanre Date: Thu, 29 May 2025 15:59:13 +0700 Subject: [PATCH] feat: adjustement on the serveral part on the profile and quiz result --- assets/translations/en-US.json | 4 +- assets/translations/id-ID.json | 4 +- assets/translations/ms-MY.json | 3 +- .../notification/pop_up_confirmation.dart | 84 +++++++++++++++++++ lib/core/endpoint/api_endpoint.dart | 4 +- lib/data/entity/user/user_entity.dart | 1 + .../login/controllers/login_controller.dart | 2 +- .../controller/profile_controller.dart | 30 ++++--- lib/feature/profile/view/profile_view.dart | 6 +- .../profile/view/update_profile_view.dart | 6 +- .../quiz_result/view/quiz_result_view.dart | 2 +- 11 files changed, 125 insertions(+), 21 deletions(-) diff --git a/assets/translations/en-US.json b/assets/translations/en-US.json index c0cf4ee..ef0aed4 100644 --- a/assets/translations/en-US.json +++ b/assets/translations/en-US.json @@ -151,5 +151,7 @@ "quiz_description": "Description", "quiz_total_question": "Total Questions", "quiz_duration": "Duration" - } + }, + + "save_changes" : "Save Changes" } diff --git a/assets/translations/id-ID.json b/assets/translations/id-ID.json index 8b829f1..2413acc 100644 --- a/assets/translations/id-ID.json +++ b/assets/translations/id-ID.json @@ -134,5 +134,7 @@ "quiz_description": "Deskripsi", "quiz_total_question": "Total Pertanyaan", "quiz_duration": "Durasi" - } + }, + "save_changes": "Simpan Perubahan" + } diff --git a/assets/translations/ms-MY.json b/assets/translations/ms-MY.json index 8a4b48c..31bbb63 100644 --- a/assets/translations/ms-MY.json +++ b/assets/translations/ms-MY.json @@ -136,5 +136,6 @@ "quiz_description": "Penerangan", "quiz_total_question": "Jumlah Soalan", "quiz_duration": "Tempoh" - } + }, + "save_changes": "Simpan Perubahan" } diff --git a/lib/component/notification/pop_up_confirmation.dart b/lib/component/notification/pop_up_confirmation.dart index 76fc147..46cbe7e 100644 --- a/lib/component/notification/pop_up_confirmation.dart +++ b/lib/component/notification/pop_up_confirmation.dart @@ -119,4 +119,88 @@ class AppDialog { }, ); } + + static Future showConfirmationDialog( + BuildContext context, { + required String title, + required String message, + String cancelText = "Batal", + String confirmText = "Yakin", + Color confirmColor = AppColors.primaryBlue, + }) async { + return showDialog( + context: context, + barrierDismissible: true, + builder: (BuildContext context) { + return Dialog( + backgroundColor: AppColors.background, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(16), + ), + child: Padding( + padding: const EdgeInsets.all(20), + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Text( + title, + style: const TextStyle( + fontSize: 18, + fontWeight: FontWeight.bold, + color: AppColors.darkText, + ), + textAlign: TextAlign.center, + ), + const SizedBox(height: 16), + Text( + message, + style: const TextStyle( + fontSize: 14, + color: AppColors.softGrayText, + ), + textAlign: TextAlign.center, + ), + const SizedBox(height: 24), + Row( + children: [ + Expanded( + child: ElevatedButton( + onPressed: () => Navigator.pop(context, false), + style: ElevatedButton.styleFrom( + backgroundColor: Colors.white, + foregroundColor: AppColors.primaryBlue, + side: const BorderSide(color: AppColors.primaryBlue), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(12), + ), + padding: const EdgeInsets.symmetric(vertical: 14), + ), + child: Text(cancelText), + ), + ), + const SizedBox(width: 12), + Expanded( + child: ElevatedButton( + onPressed: () => Navigator.pop(context, true), + style: ElevatedButton.styleFrom( + backgroundColor: confirmColor, + foregroundColor: Colors.white, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(12), + ), + padding: const EdgeInsets.symmetric(vertical: 14), + ), + child: Text(confirmText), + ), + ), + ], + ) + ], + ), + ), + ); + }, + ); + } } diff --git a/lib/core/endpoint/api_endpoint.dart b/lib/core/endpoint/api_endpoint.dart index 9f01866..ab82f99 100644 --- a/lib/core/endpoint/api_endpoint.dart +++ b/lib/core/endpoint/api_endpoint.dart @@ -1,6 +1,6 @@ class APIEndpoint { - // static const String baseUrl = "http://172.16.106.19:5000"; - static const String baseUrl = "http://103.193.178.121:5000"; + static const String baseUrl = "http://192.168.1.18:5000"; + // static const String baseUrl = "http://103.193.178.121:5000"; static const String api = "$baseUrl/api"; static const String login = "/login"; diff --git a/lib/data/entity/user/user_entity.dart b/lib/data/entity/user/user_entity.dart index f98fb41..d147830 100644 --- a/lib/data/entity/user/user_entity.dart +++ b/lib/data/entity/user/user_entity.dart @@ -40,6 +40,7 @@ class UserEntity { 'pic_url': picUrl, 'birth_date': birthDate, 'locale': locale, + 'phone': phone, "create_at": createdAt, }; } diff --git a/lib/feature/login/controllers/login_controller.dart b/lib/feature/login/controllers/login_controller.dart index 584d6be..8dbcaad 100644 --- a/lib/feature/login/controllers/login_controller.dart +++ b/lib/feature/login/controllers/login_controller.dart @@ -148,7 +148,7 @@ class LoginController extends GetxController { void goToRegsPage() => Get.toNamed(AppRoutes.registerPage); UserEntity _convertLoginResponseToUserEntity(LoginResponseModel response) { - logC.i("user id : ${response.id}"); + logC.i("user data ${response.toJson()}"); return UserEntity( id: response.id ?? '', name: response.name, diff --git a/lib/feature/profile/controller/profile_controller.dart b/lib/feature/profile/controller/profile_controller.dart index a8cb198..d291820 100644 --- a/lib/feature/profile/controller/profile_controller.dart +++ b/lib/feature/profile/controller/profile_controller.dart @@ -3,6 +3,7 @@ import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:quiz_app/app/routes/app_pages.dart'; +import 'package:quiz_app/component/notification/pop_up_confirmation.dart'; import 'package:quiz_app/core/endpoint/api_endpoint.dart'; import 'package:quiz_app/core/utils/logger.dart'; import 'package:quiz_app/data/controllers/user_controller.dart'; @@ -83,16 +84,25 @@ class ProfileController extends GetxController { } } - void logout() async { - try { - await _googleAuthService.signOut(); - await _userStorageService.clearUser(); - _userController.clearUser(); - _userStorageService.isLogged = false; - Get.offAllNamed(AppRoutes.loginPage); - } catch (e, stackTrace) { - logC.e("Google Sign-Out Error: $e", stackTrace: stackTrace); - Get.snackbar("Error", "Gagal logout dari Google"); + void logout(BuildContext context) async { + final confirm = await AppDialog.showConfirmationDialog( + context, + title: "Keluar dari akun?", + message: "Apakah Anda yakin ingin logout dari akun ini?", + confirmText: "Logout", + ); + + if (confirm == true) { + try { + await _googleAuthService.signOut(); + await _userStorageService.clearUser(); + _userController.clearUser(); + _userStorageService.isLogged = false; + Get.offAllNamed(AppRoutes.loginPage); + } catch (e, stackTrace) { + logC.e("Google Sign-Out Error: $e", stackTrace: stackTrace); + Get.snackbar("Error", "Gagal logout dari Google"); + } } } diff --git a/lib/feature/profile/view/profile_view.dart b/lib/feature/profile/view/profile_view.dart index d05515c..3cf95f1 100644 --- a/lib/feature/profile/view/profile_view.dart +++ b/lib/feature/profile/view/profile_view.dart @@ -36,7 +36,7 @@ class ProfileView extends GetView { const SizedBox(height: 10), _profileDetails(cardRadius: cardRadius), const SizedBox(height: 10), - _settingsSection(cardRadius: cardRadius), + _settingsSection(context, cardRadius: cardRadius), const SizedBox(height: 10), _legalSection(cardRadius: cardRadius), const SizedBox(height: 20), @@ -161,7 +161,7 @@ class ProfileView extends GetView { ), ); - Widget _settingsSection({required BorderRadius cardRadius}) => Card( + Widget _settingsSection(BuildContext context, {required BorderRadius cardRadius}) => Card( color: Colors.white, elevation: 1, shadowColor: AppColors.shadowPrimary, @@ -177,7 +177,7 @@ class ProfileView extends GetView { const Divider(height: 1), _settingsTile(Get.context!, icon: LucideIcons.languages, title: tr('change_language'), onTap: () => _showLanguageDialog(Get.context!)), _settingsTile(Get.context!, - icon: LucideIcons.logOut, title: 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(context)), ], ), ), diff --git a/lib/feature/profile/view/update_profile_view.dart b/lib/feature/profile/view/update_profile_view.dart index 3bb4404..8d80650 100644 --- a/lib/feature/profile/view/update_profile_view.dart +++ b/lib/feature/profile/view/update_profile_view.dart @@ -1,5 +1,7 @@ +import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; +import 'package:quiz_app/app/const/colors/app_colors.dart'; import 'package:quiz_app/component/global_button.dart'; import 'package:quiz_app/component/global_dropdown_field.dart'; import 'package:quiz_app/component/global_text_field.dart'; @@ -10,7 +12,9 @@ class UpdateProfilePage extends GetView { @override Widget build(BuildContext context) { return Scaffold( + backgroundColor: AppColors.background2, appBar: AppBar( + backgroundColor: AppColors.background2, title: Text('Update Profile'), centerTitle: true, ), @@ -56,7 +60,7 @@ class UpdateProfilePage extends GetView { )), SizedBox(height: 32), Center( - child: GlobalButton(text: "save_changes", onPressed: controller.saveProfile), + child: GlobalButton(text: tr("save_changes"), onPressed: controller.saveProfile), ), ], ), diff --git a/lib/feature/quiz_result/view/quiz_result_view.dart b/lib/feature/quiz_result/view/quiz_result_view.dart index e72bf76..bbd02d4 100644 --- a/lib/feature/quiz_result/view/quiz_result_view.dart +++ b/lib/feature/quiz_result/view/quiz_result_view.dart @@ -95,7 +95,7 @@ class QuizResultView extends GetView { final parsed = _parseAnswer(question, answer.selectedAnswer); return QuizItemWAComponent( - index: question.index, + index: index + 1, isCorrect: answer.isCorrect, question: question.question, targetAnswer: parsed.targetAnswer,