diff --git a/assets/translations/am.json b/assets/translations/am.json index 119a1c3..2a704b6 100644 --- a/assets/translations/am.json +++ b/assets/translations/am.json @@ -187,6 +187,14 @@ "finish_all_practice_module": "የሞጁሉን ልምምድ ለመውሰድ የትምህርት ልምምዶችን ያጠናቅቁ", "finish_all_practice_course": "የኮርሱን ልምምድ ለመውሰድ የሞጁል ልምምዶችን ያጠናቅቁ", "finish_all_practice_previouse_module": "ይህን ልምምድ ለመውሰድ የቀድሞውን የሞጁል ልምምድ ያጠናቅቁ", - "finish_all_practice_previouse_course": "ይህን ለመውሰድ የቀድሞውን የኮርስ ልምምድ ያጠናቅቁ" + "finish_all_practice_previouse_course": "ይህን ለመውሰድ የቀድሞውን የኮርስ ልምምድ ያጠናቅቁ", + "track_journey": "የትምህርት ጉዞዎን ይከታተሉ እና በጊዜ ሂደት ያሳዩትን እድገት ይመልከቱ።", + "learn_english": "እንግሊዝኛ ይማሩ", + "keep_momentum":"በጣም ጥሩ ስራ! በዚሁ ብርታት ይቀጥሉ።", + "completed_practices": "የተጠናቀቁ ልምምዶች", + "total_practices": "ጠቅላላ ልምምዶች", + "progress_percentage": "የእድገት መቶኛ" + + } diff --git a/assets/translations/en.json b/assets/translations/en.json index 0ff6d30..52b7365 100644 --- a/assets/translations/en.json +++ b/assets/translations/en.json @@ -1,192 +1,197 @@ - - {"loading": "Loading", - "welcome_back": "Welcome back", - "checking_user_info": "Checking user info", - "dont_have_account": "Don't have an account?", - "email": "Email", - "password": "Password", - "forgot_password": "Forgot password?", - "cont": "Continue", - "register": "Register", - "login_with_google": "Login with Google", - "or": "Or", - "login_with_phone": "Login with phone number", - "create_account": "Create an account", - "already_have_account": "Already have an account?", - "login": "Login", - "register_with_google": "Register with Google", - "register_with_phone": "Register with phone number", - "enter_phone_number": "Enter your phone number. We will send you a confirmation code there.", - "login_with_email": "Login with email", - "create_password": "Create password", - "confirm_password": "Confirm password", - "eight_character_minimum": "8 characters minimum", - "password_match": "password match", - "sign_up_agreement": "By clicking ‘Sign Up’, you agree to our ‘Terms of Service’ and ‘Privacy Policy’", - "terms_of_services": "Terms of Service", - "and": "and", - "privacy_policy": "Privacy Policy", - "register_with_email": "Register with email", - "verification_code": "Verification Code", - "resend_code": "Resend Code", - "code_sent_to_phone": "Code sent to your number", - "code_sent_to_email": "Code sent to your email", - "resend_code_in": "Resend code in", - "reset_password": "Reset Password", - "enter_email_reset_code": "Enter your email. We will send you a reset code.", - "please_wait": "Please wait", - "reset_code_sent": "Reset code sent successfully", - "reset_code": "Reset code", - "new_password": "New password", - "logged_in_successfully": "Logged in successfully", - "continue_learning": "Continue Learning", - "start_learning": "Start Learning", - "completed": "Completed", - "view_course": "View course", - "take_practice": "Take practice", - "your_current_level": "Your current level", - "overall_progress": "Overall progress", - "great_work": "Keep up the great work! You're doing amazing", - "view_module": "View module", - "progress": "Progress", - "keep_going": "Let's keep going - you're more than half there", - "lessons_in_module": "Lessons in this module", - "practice": "Practice", - "start": "Start", - "in_progress": "In Progress", - "hello": "Hello", - "ready_to_learn": "Ready to keep learning English today", - "learn": "Learn", - "course": "Course", - "profile": "Profile", - "speaking_partner": "Speaking partner", - "practice_what_you_learned": "Let's practice what you just learnt", - "practice_questions": "I will ask you a few questions and you can respond", - "start_practice": "Start practice", - "almost_there": "You're almost there", - "finish_session": "Finish the session to see your progress", - "continue_practice": "Continue practice", - "end_session": "End session", - "tap_start_to_listen": "Tap the start button to listen", - "practice_speaking": "Practice speaking", - "tap_microphone": "Tap the microphone to speak", - "reply": "Reply", - "cancel": "Cancel", - "you_are_speaking": "You're speaking", - "practice_completed": "Practice completed!", - "great_improvement": "You sound more confident this time, great improvement", - "practice_again": "Practice again", - "conversation_review": "Conversation review", - "result": "Result", - "quick_tip": "Quick tip", - "retry": "Retry", - "completed_a1": "Yay, you've completed A1", - "analyzing_speaking": "We're now analyzing your speaking skill", - "view_profile": "View profile", - "hi": "Hi", - "edit_profile": "Edit profile", - "first_name": "First name", - "last_name": "Last name", - "gender": "Gender", - "male": "Male", - "female": "Female", - "phone_number": "Phone number", - "country": "Country", - "region": "Region", - "select_region": "Select region", - "enter_your_city": "Enter your city", - "occupation": "Occupation", - "select_occupation": "Select occupation", - "save_changes": "Save changes", - "my_progress": "My progress", - "track_your_achievement": "Track your achievements and learning streak", - "account_and_privacy": "Account & Privacy", - "manage_settings": "Manage settings and app preference", - "support": "Support", - "get_help": "Get help through phone or Telegram", - "logout": "Logout", - "app_settings": "App settings", - "legal_and_information": "Legal & Information", - "change_language": "Change language", - "terms_and_conditions":"Terms & Conditions", - "delete_account": "Delete account", - "language_preference": "Language preference", - "choose_your_language": "Choose your language", - "switch_language_anytime": "You can switch languages anytime", - "need_help": "Need help?", - "call_support": "Call support", - "talk_with_support": "Talk with our support team directly", - "telegram_support": "Telegram support", - "chat_via_telegram" :"Chat instantly via Telegram", - "call_our_support": "Call our support team between 9 AM - 6 PM", - "tap_to_call": "Tap to call", - "join_telegram": "Join Yimaru Academy on Telegram", - "connect_with_support_team": "Connect with our support team instantly on Telegram for quick assistance and community updates", - "open_in_telegram": "Open in Telegram", - "search_for": "Search for", - "current_level": "Current Level", - "keep_up_the_great_work": "Keep up the great work! You're doing amazing.", - "no_practice_available": "No practice available!", - "begin_module_practice": "Begin Module Practice", - "lets_practice_lesson": "Let’s Practice", - "lets_quickly_review": "Let’s quickly review what you’ve learned in this module!", - "lets_practice_module": "Let's practice what you just learnt!", - "ask_you_few_actions": "I’ll ask you a few questions, and you can respond naturally.", - "begin_level_practice": "Begin Level Practice", - "lets_practice_course": "Let’s Practice Course", - "lets_quick_review": "Let’s quickly review what you’ve learned in this level!", - "speaking": "is speaking...", - "you_have_finished_practice": "You have finished your practice", - "view_results": "View My Results", - "sample_answer": "Sample Answer", - "your_answer": "Your Answer", - "sound_confident": "You sound more confident this time - great improvement!", - "you_have_completed": "Yay, you’ve completed", - "yes": "Yes", - "no": "No", - "want_to_quit": "Are you sure you want to quit?", - "required_field": "The field is required", - "enter_full_name": "Enter your full name", - "invalid_email": "Invalid email format", - "phone_must_start_with": "Phone number must start with 251", - "phone_must_be": "Phone number must be 12 digits", - "what_should_we_call_you": "What should we call you?", - "name_for_personalization": "We’ll use your name to personalize your learning journey.", - "choose_your_gender": "Choose your gender?", - "gender_for_personalization": "We’ll personalize your learning experience based on your gender.", - "age_range": "Which age range are you in?", - "age_for_personalization": "We’ll personalize your learning experience based on your age.", - "educational_background": "What’s your current educational level?", - "education_for_personalization": "This helps us tailor your lessons to your experience.", - "your_occupation": "What’s your occupation?", - "occupation_for_personalization": "We’ll personalize your learning experience based on your occupation.", - "location": "Where are you from?", - "select_country_region": "Select your country and region from the dropdown", - "select_country": "Select country", - "learning_goal": "Choose your learning goal.", - "language_goal": "What’s your main goal for improving your English?", - "your_goal": "Your goal helps us tailor your learning journey.", - "write_your_goal": "Write your goal…", - "challenge_you_face": "What challenge do you face most with English?", - "evey_one_has_strugle": "Everyone has struggles, let’s start fixing yours", - "write_your_challenge": "Write your challenge…", - "topic_interest": "Which topics interest you most?", - "favourite_topic": "Your favorite topics help us create fun, relatable lessons.", - "your_interest": "Write your interest…", - "want_quick_assessment": "Want a quick assessment to know your English level?", - "answer_quick_questions": "Answer a few quick questions to help us understand your English proficiency.", - "skip": "Skip", - "finish_level": "Finish Level", - "likely_speaker": "You’re likely speaker of", - "great_job": "Great Job! Here’s your next step to keep improving.", - "lets_start_practice": "Let's start your practice", - "welcome_abroad": "Welcome aboard", - "ready_to_explore": "You’re ready to explore your personalized lessons.", - "finish": "Finish", - "finish_all_practice_lesson": "Finish the previous lesson practice to take this practice", - "finish_all_practice_module": "Finish the lesson practices to take the Module Practice", - "finish_all_practice_course": "Finish the Module practices to take the Course practice", - "finish_all_practice_previouse_module": "Finish the previous Module practice to take this practice", - "finish_all_practice_previouse_course": "Finish the previous course practice to take this" - - } +{ + "loading": "Loading", + "welcome_back": "Welcome back", + "checking_user_info": "Checking user info", + "dont_have_account": "Don't have an account?", + "email": "Email", + "password": "Password", + "forgot_password": "Forgot password?", + "cont": "Continue", + "register": "Register", + "login_with_google": "Login with Google", + "or": "Or", + "login_with_phone": "Login with phone number", + "create_account": "Create an account", + "already_have_account": "Already have an account?", + "login": "Login", + "register_with_google": "Register with Google", + "register_with_phone": "Register with phone number", + "enter_phone_number": "Enter your phone number. We will send you a confirmation code there.", + "login_with_email": "Login with email", + "create_password": "Create password", + "confirm_password": "Confirm password", + "eight_character_minimum": "8 characters minimum", + "password_match": "password match", + "sign_up_agreement": "By clicking ‘Sign Up’, you agree to our ‘Terms of Service’ and ‘Privacy Policy’", + "terms_of_services": "Terms of Service", + "and": "and", + "privacy_policy": "Privacy Policy", + "register_with_email": "Register with email", + "verification_code": "Verification Code", + "resend_code": "Resend Code", + "code_sent_to_phone": "Code sent to your number", + "code_sent_to_email": "Code sent to your email", + "resend_code_in": "Resend code in", + "reset_password": "Reset Password", + "enter_email_reset_code": "Enter your email. We will send you a reset code.", + "please_wait": "Please wait", + "reset_code_sent": "Reset code sent successfully", + "reset_code": "Reset code", + "new_password": "New password", + "logged_in_successfully": "Logged in successfully", + "continue_learning": "Continue Learning", + "start_learning": "Start Learning", + "completed": "Completed", + "view_course": "View course", + "take_practice": "Take practice", + "your_current_level": "Your current level", + "overall_progress": "Overall progress", + "great_work": "Keep up the great work! You're doing amazing", + "view_module": "View module", + "progress": "Progress", + "keep_going": "Let's keep going - you're more than half there", + "lessons_in_module": "Lessons in this module", + "practice": "Practice", + "start": "Start", + "in_progress": "In Progress", + "hello": "Hello", + "ready_to_learn": "Ready to keep learning English today", + "learn": "Learn", + "course": "Course", + "profile": "Profile", + "speaking_partner": "Speaking partner", + "practice_what_you_learned": "Let's practice what you just learnt", + "practice_questions": "I will ask you a few questions and you can respond", + "start_practice": "Start practice", + "almost_there": "You're almost there", + "finish_session": "Finish the session to see your progress", + "continue_practice": "Continue practice", + "end_session": "End session", + "tap_start_to_listen": "Tap the start button to listen", + "practice_speaking": "Practice speaking", + "tap_microphone": "Tap the microphone to speak", + "reply": "Reply", + "cancel": "Cancel", + "you_are_speaking": "You're speaking", + "practice_completed": "Practice completed!", + "great_improvement": "You sound more confident this time, great improvement", + "practice_again": "Practice again", + "conversation_review": "Conversation review", + "result": "Result", + "quick_tip": "Quick tip", + "retry": "Retry", + "completed_a1": "Yay, you've completed A1", + "analyzing_speaking": "We're now analyzing your speaking skill", + "view_profile": "View profile", + "hi": "Hi", + "edit_profile": "Edit profile", + "first_name": "First name", + "last_name": "Last name", + "gender": "Gender", + "male": "Male", + "female": "Female", + "phone_number": "Phone number", + "country": "Country", + "region": "Region", + "select_region": "Select region", + "enter_your_city": "Enter your city", + "occupation": "Occupation", + "select_occupation": "Select occupation", + "save_changes": "Save changes", + "my_progress": "My progress", + "track_your_achievement": "Track your achievements and learning streak", + "account_and_privacy": "Account & Privacy", + "manage_settings": "Manage settings and app preference", + "support": "Support", + "get_help": "Get help through phone or Telegram", + "logout": "Logout", + "app_settings": "App settings", + "legal_and_information": "Legal & Information", + "change_language": "Change language", + "terms_and_conditions": "Terms & Conditions", + "delete_account": "Delete account", + "language_preference": "Language preference", + "choose_your_language": "Choose your language", + "switch_language_anytime": "You can switch languages anytime", + "need_help": "Need help?", + "call_support": "Call support", + "talk_with_support": "Talk with our support team directly", + "telegram_support": "Telegram support", + "chat_via_telegram": "Chat instantly via Telegram", + "call_our_support": "Call our support team between 9 AM - 6 PM", + "tap_to_call": "Tap to call", + "join_telegram": "Join Yimaru Academy on Telegram", + "connect_with_support_team": "Connect with our support team instantly on Telegram for quick assistance and community updates", + "open_in_telegram": "Open in Telegram", + "search_for": "Search for", + "current_level": "Current Level", + "keep_up_the_great_work": "Keep up the great work! You're doing amazing.", + "no_practice_available": "No practice available!", + "begin_module_practice": "Begin Module Practice", + "lets_practice_lesson": "Let’s Practice", + "lets_quickly_review": "Let’s quickly review what you’ve learned in this module!", + "lets_practice_module": "Let's practice what you just learnt!", + "ask_you_few_actions": "I’ll ask you a few questions, and you can respond naturally.", + "begin_level_practice": "Begin Level Practice", + "lets_practice_course": "Let’s Practice Course", + "lets_quick_review": "Let’s quickly review what you’ve learned in this level!", + "speaking": "is speaking...", + "you_have_finished_practice": "You have finished your practice", + "view_results": "View My Results", + "sample_answer": "Sample Answer", + "your_answer": "Your Answer", + "sound_confident": "You sound more confident this time - great improvement!", + "you_have_completed": "Yay, you’ve completed", + "yes": "Yes", + "no": "No", + "want_to_quit": "Are you sure you want to quit?", + "required_field": "The field is required", + "enter_full_name": "Enter your full name", + "invalid_email": "Invalid email format", + "phone_must_start_with": "Phone number must start with 251", + "phone_must_be": "Phone number must be 12 digits", + "what_should_we_call_you": "What should we call you?", + "name_for_personalization": "We’ll use your name to personalize your learning journey.", + "choose_your_gender": "Choose your gender?", + "gender_for_personalization": "We’ll personalize your learning experience based on your gender.", + "age_range": "Which age range are you in?", + "age_for_personalization": "We’ll personalize your learning experience based on your age.", + "educational_background": "What’s your current educational level?", + "education_for_personalization": "This helps us tailor your lessons to your experience.", + "your_occupation": "What’s your occupation?", + "occupation_for_personalization": "We’ll personalize your learning experience based on your occupation.", + "location": "Where are you from?", + "select_country_region": "Select your country and region from the dropdown", + "select_country": "Select country", + "learning_goal": "Choose your learning goal.", + "language_goal": "What’s your main goal for improving your English?", + "your_goal": "Your goal helps us tailor your learning journey.", + "write_your_goal": "Write your goal…", + "challenge_you_face": "What challenge do you face most with English?", + "evey_one_has_strugle": "Everyone has struggles, let’s start fixing yours", + "write_your_challenge": "Write your challenge…", + "topic_interest": "Which topics interest you most?", + "favourite_topic": "Your favorite topics help us create fun, relatable lessons.", + "your_interest": "Write your interest…", + "want_quick_assessment": "Want a quick assessment to know your English level?", + "answer_quick_questions": "Answer a few quick questions to help us understand your English proficiency.", + "skip": "Skip", + "finish_level": "Finish Level", + "likely_speaker": "You’re likely speaker of", + "great_job": "Great Job! Here’s your next step to keep improving.", + "lets_start_practice": "Let's start your practice", + "welcome_abroad": "Welcome aboard", + "ready_to_explore": "You’re ready to explore your personalized lessons.", + "finish": "Finish", + "finish_all_practice_lesson": "Finish the previous lesson practice to take this practice", + "finish_all_practice_module": "Finish the lesson practices to take the Module Practice", + "finish_all_practice_course": "Finish the Module practices to take the Course practice", + "finish_all_practice_previouse_module": "Finish the previous Module practice to take this practice", + "finish_all_practice_previouse_course": "Finish the previous course practice to take this", + "track_journey": "Track your learning journey and see your growth over time.", + "learn_english": "Learn English", + "keep_momentum":"Great job! Keep the momentum.", + "completed_practices": "Completed Practices", + "total_practices": "Total Practices", + "progress_percentage": "Progress Percentage" +} diff --git a/lib/services/authentication_service.dart b/lib/services/authentication_service.dart index dd22536..e0ffc2f 100644 --- a/lib/services/authentication_service.dart +++ b/lib/services/authentication_service.dart @@ -2,13 +2,18 @@ import 'package:stacked/stacked.dart'; import 'package:yimaru_app/app/app.locator.dart'; import 'package:yimaru_app/models/user.dart'; import 'package:yimaru_app/services/secure_storage_service.dart'; +import 'package:yimaru_app/ui/common/enmus.dart'; +import 'google_auth_service.dart'; import 'localization_service.dart'; class AuthenticationService with ListenableServiceMixin { // Dependency injection + final _secureService = locator(); + final _googleAuthService = locator(); + final _localizationService = locator(); // User data @@ -18,9 +23,15 @@ class AuthenticationService with ListenableServiceMixin { // Initialization AuthenticationService() { - listenToReactiveValues([_user, _localizationService]); + listenToReactiveValues([_user,_state, _localizationService]); } + // Logout state + StateObjects _state = StateObjects.none; + + StateObjects get state => _state; + + // Check user logged in Future userLoggedIn() async { if (await _secureService.getString('userId') != null) { @@ -179,13 +190,20 @@ class AuthenticationService with ListenableServiceMixin { // Logout Future logout() async { + _state = StateObjects.logout; + notifyListeners(); + bool firstTimeInstall = await isFirstTimeInstall(); String language = await _localizationService.selectedLanguage['code']; _user = null; await _secureService.clear(); + await _googleAuthService.logout(); await setFirstTimeInstall(firstTimeInstall); await _secureService.setString('language', language); + + + _state = StateObjects.none; notifyListeners(); } } diff --git a/lib/services/google_auth_service.dart b/lib/services/google_auth_service.dart index 468406c..d97e083 100644 --- a/lib/services/google_auth_service.dart +++ b/lib/services/google_auth_service.dart @@ -19,7 +19,6 @@ class GoogleAuthService with ListenableServiceMixin { Future logout() async { await _signIn.signOut(); _googleUser = null; - notifyListeners(); } // Google authentication @@ -30,10 +29,7 @@ class GoogleAuthService with ListenableServiceMixin { _googleUser ??= await _signIn.authenticate(scopeHint: ['email', 'profile']); - print('GOOGLE AUTH'); - print(_googleUser?.email); - print(_googleUser?.displayName); - print(_googleUser?.authentication.idToken); + }); notifyListeners(); } catch (e) { diff --git a/lib/services/image_downloader_service.dart b/lib/services/image_downloader_service.dart index 92d8dcd..572ef3c 100644 --- a/lib/services/image_downloader_service.dart +++ b/lib/services/image_downloader_service.dart @@ -5,39 +5,53 @@ import 'package:path/path.dart'; import 'package:path_provider/path_provider.dart'; import '../app/app.locator.dart'; -import '../ui/common/app_constants.dart'; +import '../models/refresh_object.dart'; +import '../ui/common/enmus.dart'; +import 'api_service.dart'; import 'dio_service.dart'; class ImageDownloaderService { // Dependency injection final _service = locator(); + final _apiService = locator(); + + final Dio _dio = Dio(); + // Image downloader - Future downloader(String? networkImage) async { - late File image; + Future downloader(String? networkImage) async { + try { + File? image; - late String profileImage; + String? profileImage = networkImage; - final Directory appDir = await getApplicationDocumentsDirectory(); + final Directory appDir = await getApplicationDocumentsDirectory(); - if (networkImage != null) { - profileImage = networkImage.contains('https://lh3.googleusercontent.com') - ? networkImage - : '$kBaseUrl$networkImage'; + Map data = {'reference': profileImage}; + Map response = await _apiService.refreshObject(data); + + if (response['status'] == ResponseStatus.success) { + RefreshObject object = response['data'] as RefreshObject; + + profileImage = object.url; + } + + if (profileImage != null) { + final Response profileImageResponse = await _dio.get>( + profileImage, + options: Options( + responseType: ResponseType.bytes, + ), + ); + final localImagePath = join(appDir.path, 'profile.jpg'); + image = File(localImagePath); + image.writeAsBytes(profileImageResponse.data); + + return image.path; + } + return null; + } catch (e) { + return null; } - - final Response profileImageResponse = await _service.dio.get( - profileImage, - options: Options( - followRedirects: false, - responseType: ResponseType.bytes, - ), - ); - final imageName = basename(networkImage ?? ''); - final localImagePath = join(appDir.path, imageName); - image = File(localImagePath); - image.writeAsBytes(profileImageResponse.data); - - return image.path; } } diff --git a/lib/services/learn_service.dart b/lib/services/learn_service.dart index 557ab77..71f0597 100644 --- a/lib/services/learn_service.dart +++ b/lib/services/learn_service.dart @@ -1,4 +1,6 @@ import 'package:stacked/stacked.dart'; +import 'package:yimaru_app/models/course_progress.dart'; +import 'package:yimaru_app/models/module_progress.dart'; import 'package:yimaru_app/models/refresh_object.dart'; import 'package:yimaru_app/ui/common/enmus.dart'; @@ -17,9 +19,25 @@ class LearnService with ListenableServiceMixin { // Initialization learnService() { - listenToReactiveValues([_programs, _courses, _lessons, _modules]); + listenToReactiveValues( + [_programs, _courses, _lessons, _modules, _totalCount]); } + // Completed count + int _completedCount = 0; + + int get completedCount => _completedCount; + + // Total count + int _totalCount = 0; + + int get totalCount => _totalCount; + + // Total progress + int _totalProgress = 0; + + int get totalProgress => _totalProgress; + // Learn program List _programs = []; @@ -40,10 +58,7 @@ class LearnService with ListenableServiceMixin { List get lessons => _lessons; - // Learn progress - final List _summaries = []; - List get summaries => _summaries; // Learn programs Future refreshObject(String url) async { @@ -87,7 +102,7 @@ class LearnService with ListenableServiceMixin { } // Learn progress - Future getLearnProgressSummary() async { + Future getLearnProgress() async { final summaries = await _apiService.getProgressSummary(); /// PROGRAM ACCESS MAP @@ -148,10 +163,6 @@ class LearnService with ListenableServiceMixin { ); }).toList(); - print( - 'MY SUMMARIES - COMPLETED COUNT: ${_modules.first.access?.completedCount}'); - print('PROGRESS PERCENT: ${_modules.first.access?.progressPercent}'); - /// UPDATE LESSONS _lessons = _lessons.map((lesson) { return lesson.copyWith( @@ -177,4 +188,30 @@ class LearnService with ListenableServiceMixin { return null; } } + + Future getProgressSummary() async { + final summaries = await _apiService.getProgressSummary(); + + for (final ProgressSummary summary in summaries) { + _totalCount = _totalCount + (summary.access?.totalCount ?? 0); + _completedCount = _completedCount + (summary.access?.completedCount ?? 0); + + for (final CourseProgress course in summary.courses ?? []) { + _totalCount = _totalCount + (course.access?.totalCount ?? 0); + _completedCount = + _completedCount + (course.access?.completedCount ?? 0); + + for (final ModuleProgress module in course.modules ?? []) { + _totalCount = _totalCount + (module.access?.totalCount ?? 0); + _completedCount = + _completedCount + (module.access?.completedCount ?? 0); + } + } + } + + _totalProgress = summaries.fold( + 0, (sum, progress) => sum + (progress.access?.progressPercent ?? 0)); + + notifyListeners(); + } } diff --git a/lib/ui/common/app_constants.dart b/lib/ui/common/app_constants.dart index d03bd02..50bb114 100644 --- a/lib/ui/common/app_constants.dart +++ b/lib/ui/common/app_constants.dart @@ -122,7 +122,7 @@ String kTelegramSupport = '@yimaruacademy2026'; String kTelegramSupportLink = 'https://t.me/yimaruacademy2026'; -String kErrorUrl = 'https://yimaru.net/api/v1/payments/chapa/error'; +String kErrorUrl = 'https://api.yimaruacademy.com/payment/error'; String kSuccessUrl = - 'https://api.yimaruacademy.com/api/v1/payments/chapa/success'; + 'https://api.yimaruacademy.com/payment/success'; diff --git a/lib/ui/common/enmus.dart b/lib/ui/common/enmus.dart index 0edfb44..04bda1b 100644 --- a/lib/ui/common/enmus.dart +++ b/lib/ui/common/enmus.dart @@ -31,6 +31,7 @@ enum PracticeReason { course, module, lesson, previousModule, previousCourse } // State object enum StateObjects { none, + logout, courses, register, verifyOtp, @@ -55,6 +56,7 @@ enum StateObjects { loginWithGoogle, loadLessonVideo, loadCourseVideo, + progressSummary, requestResetCode, profileCompletion, learnSubscription, diff --git a/lib/ui/common/translations/codegen_loader.g.dart b/lib/ui/common/translations/codegen_loader.g.dart index a1254ed..83d4d43 100644 --- a/lib/ui/common/translations/codegen_loader.g.dart +++ b/lib/ui/common/translations/codegen_loader.g.dart @@ -6,7 +6,7 @@ import 'dart:ui'; import 'package:easy_localization/easy_localization.dart' show AssetLoader; -class CodegenLoader extends AssetLoader { +class CodegenLoader extends AssetLoader{ const CodegenLoader(); @override @@ -14,416 +14,399 @@ class CodegenLoader extends AssetLoader { return Future.value(mapLocales[locale.toString()]); } - static const Map _am = { - "loading": "በመጫን ላይ", - "welcome_back": "እንኳን በደህና ተመለሱ", - "checking_user_info": "የተጠቃሚ መረጃን በማረጋገጥ ላይ", - "dont_have_account": "መለያ የለዎትም?", - "email": "ኢሜይል", - "password": "የይለፍ ቃል", - "forgot_password": "የይለፍ ቃል ረሱ?", - "cont": "ቀጥል", - "register": "ይመዝገቡ", - "login_with_google": "በጉግል ይግቡ", - "or": "ወይም", - "login_with_phone": "በስልክ ቁጥር ይግቡ", - "create_account": "አዲስ መለያ ይፍጠሩ", - "already_have_account": "መለያ አለዎት?", - "login": " ይግቡ ", - "register_with_google": "በጉግል ይመዝገቡ", - "register_with_phone": "በስልክ ቁጥር ይመዝገቡ", - "enter_phone_number": "የስልክ ቁጥርዎን ያስገቡ። የማረጋገጫ ኮድ እንልክልዎታለን።", - "login_with_email": "በኢሜይል ይግቡ", - "create_password": "የይለፍ ቃል ይፍጠሩ", - "confirm_password": "የይለፍ ቃል ያረጋግጡ", - "eight_character_minimum": "ቢያንስ 8 ፊደላት", - "password_match": "የይለፍ ቃሉ ተመሳስሏል", - "sign_up_agreement": - "‘ይመዝገቡ’ የሚለውን ሲጫኑ በ‘አገልግሎት ውሎች’ እና ‘በግላዊነት ፖሊሲ’ ይስማማሉ።", - "terms_of_services": "የአገልግሎት ውሎች", - "and": "እና", - "privacy_policy": "የግላዊነት ፖሊሲ", - "register_with_email": "በኢሜል ይመዝገቡ", - "verification_code": "የማረጋገጫ ኮድ", - "resend_code": "ኮዱን እንደገና ላክ", - "code_sent_to_phone": "ኮዱ ወደ ስልክ ቁጥርዎ ተልኳል", - "code_sent_to_email": "ኮዱ ወደ ኢሜል ተልኳል", - "resend_code_in": "ኮዱን እንደገና ለመላክ የቀረው ጊዜ", - "reset_password": " የይለፍ ቃልን ይቀይሩ", - "enter_email_reset_code": "ኢሜይልዎን ያስገቡ። የይለፍ ቃል መለወጫ ኮድ እንልክልዎታለን።", - "please_wait": "እባክዎ ይጠብቁ", - "reset_code_sent": "የመቀየሪያ ኮድ በተሳካ ሁኔታ ተልኳል", - "reset_code": " የመቀየሪያ ኮድ ", - "new_password": "አዲስ የይለፍ ቃል", - "logged_in_successfully": "በተሳካ ሁኔታ ገብተዋል", - "view_course": " ኮርሱን ይመልከቱ", - "continue_learning": "መማርን ይቀጥሉ", - "start_learning": "ትምህርትን ይጀምሩ", - "completed": "ተጠናቋል", - "take_practice": "ልምምድ ያድርጉ", - "your_current_level": "የአሁኑ ደረጃዎ", - "overall_progress": "አጠቃላይ እድገት", - "great_work": "በርቱ! በጣም ጥሩ እየሰሩ ነው", - "view_module": "ሞጁሉን ይመልከቱ", - "progress": "እድገት", - "keep_going": "ይቀጥሉ - ከግማሽ በላይ ጨርሰዋል ", - "lessons_in_module": "በዚህ ሞጁል ውስጥ ያሉ ትምህርቶች ", - "practice": "ልምምድ", - "start": "ጀምር", - "in_progress": "በሂደት ላይ", - "hello": "ሰላም", - "ready_to_learn": " ዛሬ እንግሊዝኛ ለመማር ተዘጋጅተዋል? ", - "learn": "ይማሩ ", - "course": "ኮርስ", - "profile": " ፕሮፋይል ", - "speaking_partner": "የንግግር ጓደኛ", - "practice_what_you_learned": "አሁን የተማሩትን እንለማመድ", - "practice_questions": "ጥቂት ጥያቄዎችን እጠይቃለሁ እና መልስ መስጠት ይችላሉ", - "start_practice": "ልምምድ ጀምር", - "almost_there": "ሊጨርሱ ተቃርበዋል", - "finish_session": "እድገትዎን ለማየት ክፍለ ጊዜውን ያጠናቅቁ", - "continue_practice": "ልምምዱን ይቀጥሉ", - "end_session": "ክፍለ ጊዜውን ያብቁ ", - "tap_start_to_listen": "ለማዳመጥ የጀምር ቁልፉን ይጫኑ", - "practice_speaking": "ንግግርን ይለማመዱ", - "tap_microphone": "ለመናገር ማይክሮፎኑን ይጫኑ", - "reply": "እንደገና አዳምጥ", - "cancel": "ይቅር", - "you_are_speaking": "እየተናገሩ ነው", - "practice_completed": "ልምምዱ ተጠናቅቋል", - "great_improvement": "በዚህኛው በራስ መተማመንዎ ጨምሯል፤ ትልቅ መሻሻል ነው", - "practice_again": "እንደገና ይለማመዱ", - "conversation_review": "የንግግር ግምገማ", - "result": "ውጤት", - "quick_tip": "ጠቃሚ ምክር", - "retry": "እንደገና ይሞክሩ", - "completed_a1": "እንኳን ደስ አለዎት! A1 ደረጃን አጠናቅቀዋል", - "analyzing_speaking": "የንግግር ችሎታዎን እየገመገምን ነው", - "view_profile": "ፕሮፋይሎን ይመልከቱ ", - "hi": "ሰላም", - "edit_profile": "መገለጫ ያስተካክሉ", - "first_name": "የመጀመሪያ ስም", - "last_name": "የአባት ስም", - "gender": "ፆታ", - "male": "ወንድ", - "female": "ሴት", - "phone_number": "የስልክ ቁጥር", - "country": "ሀገር", - "region": "ክልል", - "select_region": "ክልል ይምረጡ", - "enter_your_city": "ከተማዎን ያስገቡ", - "occupation": "የስራ መስክ", - "select_occupation": "ሙያዎን ይምረጡ", - "save_changes": "ለውጦችን ያስቀምጡ", - "my_progress": "የእኔ እድገት", - "track_your_achievement": "ስኬቶችዎን እና ተከታታይ የትምህርት ጉዞዎን ይከታተሉ", - "account_and_privacy": "መለያ እና ግላዊነት", - "manage_settings": "ቅንብሮችን እና የመተግበሪያ ምርጫዎችን ያስተዳድሩ", - "support": "ድጋፍ", - "get_help": "በስልክ ወይም በቴሌግራም እገዛ ያግኙ", - "logout": "ውጣ", - "app_settings": "የመተግበሪያ ቅንብሮች", - "legal_and_information": "ሕጋዊ እና መረጃ", - "change_language": "ቋንቋ ቀይር", - "terms_and_conditions": "ውሎች እና ሁኔታዎች", - "delete_account": "መለያ ሰርዝ", - "language_preference": "የቋንቋ ምርጫ", - "choose_your_language": "ለውጦችን አስቀምጥ", - "switch_language_anytime": "ቋንቋዎችን በማንኛውም ጊዜ መቀየር ይችላሉ", - "need_help": "እገዛ ይፈልጋሉ?", - "call_support": "የስልክ ድጋፍ", - "talk_with_support": "በቀጥታ ከድጋፍ ቡድናችን ጋር ይነጋገሩ", - "telegram_support": "የቴሌግራም ድጋፍ", - "chat_via_telegram": "በቴሌግራም በፍጥነት ይወያዩ", - "call_our_support": "ከ3 ጠዋት እስከ 12 ማታ ድረስ የድጋፍ ቡድናችንን ይደውሉ", - "tap_to_call": "ለመደወል ይንኩ", - "join_telegram": "በቴሌግራም የይማሩ አካዳሚን ይቀላቀሉ", - "connect_with_support_team": - "ለፈጣን እርዳታ እና የማህበረሰብ ዝማኔዎች፣ በቴሌግራም ከድጋፍ ቡድናችን ጋር ወዲያውኑ ይገናኙ።", - "open_in_telegram": "በቴሌግራም ይክፈቱ", - "search_for": "ፈልጉት", - "current_level": "የአሁኑ ደረጃ", - "keep_up_the_great_work": "በጣም ጥሩ እየሰራህ ነው! ቀጥልበት፣ አስደናቂ ነህ።", - "no_practice_available": "ምንም ልምምድ አልተገኘም!", - "begin_module_practice": "የሞጁሉን ልምምድ ጀምር", - "lets_practice_lesson": "እንለማመድ", - "lets_quickly_review": "በዚህ ሞጁል ውስጥ የተማርከውን በፍጥነት እንከልስ!", - "lets_practice_module": "አሁን የተማርከውን እንለማመድ!", - "ask_you_few_actions": "ጥቂት ጥያቄዎችን እጠይቅሃለሁ፣ አንተም በተፈጥሮ መልስ ልትሰጥ ትችላለህ።", - "begin_level_practice": "የደረጃ ልምምድን ጀምር", - "lets_practice_course": "የኮርሱን ልምምድ እንለማመድ", - "lets_quick_review": "በዚህ ደረጃ የተማርከውን በፍጥነት እንከልስ!", - "speaking": "እየተናገረ ነው", - "you_have_finished_practice": "ልምምድህን አጠናቀቅህ", - "view_results": "ውጤቶቼን እይ", - "sample_answer": "ናሙና መልስ", - "your_answer": "መልስህ", - "sound_confident": "በዚህ ጊዜ የበለጠ እምነት ያለህ ይመስላል — በጣም ጥሩ መሻሻል ነው!", - "you_have_completed": "አያይ! አጠናቀቅህ", - "yes": "አዎ", - "no": "አይ", - "want_to_quit": "ለመውጣት እርግጠኛ ነህ?", - "required_field": "ይህ መስክ ያስፈልጋል", - "enter_full_name": "ሙሉ ስምህን አስገባ", - "invalid_email": "የማይሰራ የኢሜይል ቅርጸት", - "phone_must_start_with": "የስልክ ቁጥር በ251 መጀመር አለበት", - "phone_must_be": "የስልክ ቁጥር 12 አሃዞች መሆን አለበት", - "what_should_we_call_you": "ምን ብለን እንጠራህ?", - "name_for_personalization": "በመማር ጉዞህ ውስጥ ለግል ለማድረግ ስምህን እንጠቀማለን።", - "choose_your_gender": "ጾታህን ምረጥ", - "gender_for_personalization": "በጾታህ መሰረት የመማር ተሞክሮህን እናበጅለታለን።", - "age_range": "በየትኛው የእድሜ ክልል ውስጥ ነህ?", - "age_for_personalization": "በእድሜህ መሰረት የመማር ተሞክሮህን እናበጅለታለን።", - "educational_background": "አሁን ያለህ የትምህርት ደረጃ ምንድን ነው?", - "education_for_personalization": "ይህ ትምህርቶችን ከልምድህ ጋር እንዲስማሙ ለማድረግ ይረዳናል።", - "your_occupation": "ስራህ ምንድን ነው?", - "occupation_for_personalization": "በስራህ መሰረት የመማር ተሞክሮህን እናበጅለታለን።", - "location": "ከየት ነህ?", - "select_country_region": "አገርህን እና ክልልህን ከተቆልቋይ ዝርዝሩ ምረጥ", - "select_country": "አገር ምረጥ", - "learning_goal": "የመማር ዓላማህን ምረጥ", - "language_goal": "እንግሊዝኛህን ለማሻሻል ዋና ዓላማህ ምንድን ነው?", - "your_goal": "ዓላማህ የመማር ጉዞህን እንዲስማማ ለማድረግ ይረዳናል።", - "write_your_goal": "ዓላማህን ጻፍ…", - "challenge_you_face": "What challenge do you face most with English?", - "evey_one_has_strugle": "ሁሉም ሰው ችግሮች አሉት፣ የአንተን እንጀምር እንፍታ", - "write_your_challenge": "ችግርህን ጻፍ…", - "topic_interest": "በጣም የሚስቡህ ርዕሶች የትኞቹ ናቸው?", - "favourite_topic": - "የምትወዳቸው ርዕሶች አስደሳች እና ከሕይወትህ ጋር የተዛመዱ ትምህርቶችን ለመፍጠር ይረዱናል።", - "your_interest": "ፍላጎትህን ጻፍ…", - "want_quick_assessment": "የእንግሊዝኛ ደረጃህን ለማወቅ ፈጣን ግምገማ ትፈልጋለህ?", - "answer_quick_questions": "የእንግሊዝኛ ችሎታህን ለመረዳት ጥቂት ፈጣን ጥያቄዎችን መልስ።", - "skip": "ዝለል", - "finish_level": "ደረጃውን አጠናቅቅ", - "likely_speaker": "አንተ ምናልባት ተናጋሪ ነህ", - "great_job": "በጣም ጥሩ ስራ! ለመሻሻል ቀጣዩ ደረጃህ ይኸው ነው።", - "lets_start_practice": "ልምምድህን እንጀምር", - "welcome_abroad": "እንኳን ደህና መጣህ", - "ready_to_explore": "የግል ትምህርቶችህን ለማሰስ ዝግጁ ነህ።", - "finish": "አጠናቅቅ", - "finish_all_practice_lesson": "ይህን ልምምድ ለመውሰድ የቀድሞውን የትምህርት ልምምድ ያጠናቅቁ", - "finish_all_practice_module": "የሞጁሉን ልምምድ ለመውሰድ የትምህርት ልምምዶችን ያጠናቅቁ", - "finish_all_practice_course": "የኮርሱን ልምምድ ለመውሰድ የሞጁል ልምምዶችን ያጠናቅቁ", - "finish_all_practice_previouse_module": - "ይህን ልምምድ ለመውሰድ የቀድሞውን የሞጁል ልምምድ ያጠናቅቁ", - "finish_all_practice_previouse_course": "ይህን ለመውሰድ የቀድሞውን የኮርስ ልምምድ ያጠናቅቁ" - }; - static const Map _en = { - "loading": "Loading", - "welcome_back": "Welcome back", - "checking_user_info": "Checking user info", - "dont_have_account": "Don't have an account?", - "email": "Email", - "password": "Password", - "forgot_password": "Forgot password?", - "cont": "Continue", - "register": "Register", - "login_with_google": "Login with Google", - "or": "Or", - "login_with_phone": "Login with phone number", - "create_account": "Create an account", - "already_have_account": "Already have an account?", - "login": "Login", - "register_with_google": "Register with Google", - "register_with_phone": "Register with phone number", - "enter_phone_number": - "Enter your phone number. We will send you a confirmation code there.", - "login_with_email": "Login with email", - "create_password": "Create password", - "confirm_password": "Confirm password", - "eight_character_minimum": "8 characters minimum", - "password_match": "password match", - "sign_up_agreement": - "By clicking ‘Sign Up’, you agree to our ‘Terms of Service’ and ‘Privacy Policy’", - "terms_of_services": "Terms of Service", - "and": "and", - "privacy_policy": "Privacy Policy", - "register_with_email": "Register with email", - "verification_code": "Verification Code", - "resend_code": "Resend Code", - "code_sent_to_phone": "Code sent to your number", - "code_sent_to_email": "Code sent to your email", - "resend_code_in": "Resend code in", - "reset_password": "Reset Password", - "enter_email_reset_code": - "Enter your email. We will send you a reset code.", - "please_wait": "Please wait", - "reset_code_sent": "Reset code sent successfully", - "reset_code": "Reset code", - "new_password": "New password", - "logged_in_successfully": "Logged in successfully", - "continue_learning": "Continue Learning", - "start_learning": "Start Learning", - "completed": "Completed", - "view_course": "View course", - "take_practice": "Take practice", - "your_current_level": "Your current level", - "overall_progress": "Overall progress", - "great_work": "Keep up the great work! You're doing amazing", - "view_module": "View module", - "progress": "Progress", - "keep_going": "Let's keep going - you're more than half there", - "lessons_in_module": "Lessons in this module", - "practice": "Practice", - "start": "Start", - "in_progress": "In Progress", - "hello": "Hello", - "ready_to_learn": "Ready to keep learning English today", - "learn": "Learn", - "course": "Course", - "profile": "Profile", - "speaking_partner": "Speaking partner", - "practice_what_you_learned": "Let's practice what you just learnt", - "practice_questions": "I will ask you a few questions and you can respond", - "start_practice": "Start practice", - "almost_there": "You're almost there", - "finish_session": "Finish the session to see your progress", - "continue_practice": "Continue practice", - "end_session": "End session", - "tap_start_to_listen": "Tap the start button to listen", - "practice_speaking": "Practice speaking", - "tap_microphone": "Tap the microphone to speak", - "reply": "Reply", - "cancel": "Cancel", - "you_are_speaking": "You're speaking", - "practice_completed": "Practice completed!", - "great_improvement": - "You sound more confident this time, great improvement", - "practice_again": "Practice again", - "conversation_review": "Conversation review", - "result": "Result", - "quick_tip": "Quick tip", - "retry": "Retry", - "completed_a1": "Yay, you've completed A1", - "analyzing_speaking": "We're now analyzing your speaking skill", - "view_profile": "View profile", - "hi": "Hi", - "edit_profile": "Edit profile", - "first_name": "First name", - "last_name": "Last name", - "gender": "Gender", - "male": "Male", - "female": "Female", - "phone_number": "Phone number", - "country": "Country", - "region": "Region", - "select_region": "Select region", - "enter_your_city": "Enter your city", - "occupation": "Occupation", - "select_occupation": "Select occupation", - "save_changes": "Save changes", - "my_progress": "My progress", - "track_your_achievement": "Track your achievements and learning streak", - "account_and_privacy": "Account & Privacy", - "manage_settings": "Manage settings and app preference", - "support": "Support", - "get_help": "Get help through phone or Telegram", - "logout": "Logout", - "app_settings": "App settings", - "legal_and_information": "Legal & Information", - "change_language": "Change language", - "terms_and_conditions": "Terms & Conditions", - "delete_account": "Delete account", - "language_preference": "Language preference", - "choose_your_language": "Choose your language", - "switch_language_anytime": "You can switch languages anytime", - "need_help": "Need help?", - "call_support": "Call support", - "talk_with_support": "Talk with our support team directly", - "telegram_support": "Telegram support", - "chat_via_telegram": "Chat instantly via Telegram", - "call_our_support": "Call our support team between 9 AM - 6 PM", - "tap_to_call": "Tap to call", - "join_telegram": "Join Yimaru Academy on Telegram", - "connect_with_support_team": - "Connect with our support team instantly on Telegram for quick assistance and community updates", - "open_in_telegram": "Open in Telegram", - "search_for": "Search for", - "current_level": "Current Level", - "keep_up_the_great_work": "Keep up the great work! You're doing amazing.", - "no_practice_available": "No practice available!", - "begin_module_practice": "Begin Module Practice", - "lets_practice_lesson": "Let’s Practice", - "lets_quickly_review": - "Let’s quickly review what you’ve learned in this module!", - "lets_practice_module": "Let's practice what you just learnt!", - "ask_you_few_actions": - "I’ll ask you a few questions, and you can respond naturally.", - "begin_level_practice": "Begin Level Practice", - "lets_practice_course": "Let’s Practice Course", - "lets_quick_review": - "Let’s quickly review what you’ve learned in this level!", - "speaking": "is speaking...", - "you_have_finished_practice": "You have finished your practice", - "view_results": "View My Results", - "sample_answer": "Sample Answer", - "your_answer": "Your Answer", - "sound_confident": - "You sound more confident this time - great improvement!", - "you_have_completed": "Yay, you’ve completed", - "yes": "Yes", - "no": "No", - "want_to_quit": "Are you sure you want to quit?", - "required_field": "The field is required", - "enter_full_name": "Enter your full name", - "invalid_email": "Invalid email format", - "phone_must_start_with": "Phone number must start with 251", - "phone_must_be": "Phone number must be 12 digits", - "what_should_we_call_you": "What should we call you?", - "name_for_personalization": - "We’ll use your name to personalize your learning journey.", - "choose_your_gender": "Choose your gender?", - "gender_for_personalization": - "We’ll personalize your learning experience based on your gender.", - "age_range": "Which age range are you in?", - "age_for_personalization": - "We’ll personalize your learning experience based on your age.", - "educational_background": "What’s your current educational level?", - "education_for_personalization": - "This helps us tailor your lessons to your experience.", - "your_occupation": "What’s your occupation?", - "occupation_for_personalization": - "We’ll personalize your learning experience based on your occupation.", - "location": "Where are you from?", - "select_country_region": "Select your country and region from the dropdown", - "select_country": "Select country", - "learning_goal": "Choose your learning goal.", - "language_goal": "What’s your main goal for improving your English?", - "your_goal": "Your goal helps us tailor your learning journey.", - "write_your_goal": "Write your goal…", - "challenge_you_face": "What challenge do you face most with English?", - "evey_one_has_strugle": "Everyone has struggles, let’s start fixing yours", - "write_your_challenge": "Write your challenge…", - "topic_interest": "Which topics interest you most?", - "favourite_topic": - "Your favorite topics help us create fun, relatable lessons.", - "your_interest": "Write your interest…", - "want_quick_assessment": - "Want a quick assessment to know your English level?", - "answer_quick_questions": - "Answer a few quick questions to help us understand your English proficiency.", - "skip": "Skip", - "finish_level": "Finish Level", - "likely_speaker": "You’re likely speaker of", - "great_job": "Great Job! Here’s your next step to keep improving.", - "lets_start_practice": "Let's start your practice", - "welcome_abroad": "Welcome aboard", - "ready_to_explore": "You’re ready to explore your personalized lessons.", - "finish": "Finish", - "finish_all_practice_lesson": - "Finish the previous lesson practice to take this practice", - "finish_all_practice_module": - "Finish the lesson practices to take the Module Practice", - "finish_all_practice_course": - "Finish the Module practices to take the Course practice", - "finish_all_practice_previouse_module": - "Finish the previous Module practice to take this practice", - "finish_all_practice_previouse_course": - "Finish the previous course practice to take this" - }; - static const Map> mapLocales = { - "am": _am, - "en": _en - }; + static const Map _am = { + "loading": "በመጫን ላይ", + "welcome_back": "እንኳን በደህና ተመለሱ", + "checking_user_info": "የተጠቃሚ መረጃን በማረጋገጥ ላይ", + "dont_have_account": "መለያ የለዎትም?", + "email": "ኢሜይል", + "password": "የይለፍ ቃል", + "forgot_password": "የይለፍ ቃል ረሱ?", + "cont": "ቀጥል", + "register": "ይመዝገቡ", + "login_with_google": "በጉግል ይግቡ", + "or": "ወይም", + "login_with_phone": "በስልክ ቁጥር ይግቡ", + "create_account": "አዲስ መለያ ይፍጠሩ", + "already_have_account": "መለያ አለዎት?", + "login": " ይግቡ ", + "register_with_google": "በጉግል ይመዝገቡ", + "register_with_phone": "በስልክ ቁጥር ይመዝገቡ", + "enter_phone_number": "የስልክ ቁጥርዎን ያስገቡ። የማረጋገጫ ኮድ እንልክልዎታለን።", + "login_with_email": "በኢሜይል ይግቡ", + "create_password": "የይለፍ ቃል ይፍጠሩ", + "confirm_password": "የይለፍ ቃል ያረጋግጡ", + "eight_character_minimum": "ቢያንስ 8 ፊደላት", + "password_match": "የይለፍ ቃሉ ተመሳስሏል", + "sign_up_agreement": "‘ይመዝገቡ’ የሚለውን ሲጫኑ በ‘አገልግሎት ውሎች’ እና ‘በግላዊነት ፖሊሲ’ ይስማማሉ።", + "terms_of_services": "የአገልግሎት ውሎች", + "and": "እና", + "privacy_policy": "የግላዊነት ፖሊሲ", + "register_with_email": "በኢሜል ይመዝገቡ", + "verification_code": "የማረጋገጫ ኮድ", + "resend_code": "ኮዱን እንደገና ላክ", + "code_sent_to_phone": "ኮዱ ወደ ስልክ ቁጥርዎ ተልኳል", + "code_sent_to_email": "ኮዱ ወደ ኢሜል ተልኳል", + "resend_code_in": "ኮዱን እንደገና ለመላክ የቀረው ጊዜ", + "reset_password": " የይለፍ ቃልን ይቀይሩ", + "enter_email_reset_code": "ኢሜይልዎን ያስገቡ። የይለፍ ቃል መለወጫ ኮድ እንልክልዎታለን።", + "please_wait": "እባክዎ ይጠብቁ", + "reset_code_sent": "የመቀየሪያ ኮድ በተሳካ ሁኔታ ተልኳል", + "reset_code": " የመቀየሪያ ኮድ ", + "new_password": "አዲስ የይለፍ ቃል", + "logged_in_successfully": "በተሳካ ሁኔታ ገብተዋል", + "view_course": " ኮርሱን ይመልከቱ", + "continue_learning": "መማርን ይቀጥሉ", + "start_learning": "ትምህርትን ይጀምሩ", + "completed": "ተጠናቋል", + "take_practice": "ልምምድ ያድርጉ", + "your_current_level": "የአሁኑ ደረጃዎ", + "overall_progress": "አጠቃላይ እድገት", + "great_work": "በርቱ! በጣም ጥሩ እየሰሩ ነው", + "view_module": "ሞጁሉን ይመልከቱ", + "progress": "እድገት", + "keep_going": "ይቀጥሉ - ከግማሽ በላይ ጨርሰዋል ", + "lessons_in_module": "በዚህ ሞጁል ውስጥ ያሉ ትምህርቶች ", + "practice": "ልምምድ", + "start": "ጀምር", + "in_progress": "በሂደት ላይ", + "hello": "ሰላም", + "ready_to_learn": " ዛሬ እንግሊዝኛ ለመማር ተዘጋጅተዋል? ", + "learn": "ይማሩ ", + "course": "ኮርስ", + "profile": " ፕሮፋይል ", + "speaking_partner": "የንግግር ጓደኛ", + "practice_what_you_learned": "አሁን የተማሩትን እንለማመድ", + "practice_questions": "ጥቂት ጥያቄዎችን እጠይቃለሁ እና መልስ መስጠት ይችላሉ", + "start_practice": "ልምምድ ጀምር", + "almost_there": "ሊጨርሱ ተቃርበዋል", + "finish_session": "እድገትዎን ለማየት ክፍለ ጊዜውን ያጠናቅቁ", + "continue_practice": "ልምምዱን ይቀጥሉ", + "end_session": "ክፍለ ጊዜውን ያብቁ ", + "tap_start_to_listen": "ለማዳመጥ የጀምር ቁልፉን ይጫኑ", + "practice_speaking": "ንግግርን ይለማመዱ", + "tap_microphone": "ለመናገር ማይክሮፎኑን ይጫኑ", + "reply": "እንደገና አዳምጥ", + "cancel": "ይቅር", + "you_are_speaking": "እየተናገሩ ነው", + "practice_completed": "ልምምዱ ተጠናቅቋል", + "great_improvement": "በዚህኛው በራስ መተማመንዎ ጨምሯል፤ ትልቅ መሻሻል ነው", + "practice_again": "እንደገና ይለማመዱ", + "conversation_review": "የንግግር ግምገማ", + "result": "ውጤት", + "quick_tip": "ጠቃሚ ምክር", + "retry": "እንደገና ይሞክሩ", + "completed_a1": "እንኳን ደስ አለዎት! A1 ደረጃን አጠናቅቀዋል", + "analyzing_speaking": "የንግግር ችሎታዎን እየገመገምን ነው", + "view_profile": "ፕሮፋይሎን ይመልከቱ ", + "hi": "ሰላም", + "edit_profile": "መገለጫ ያስተካክሉ", + "first_name": "የመጀመሪያ ስም", + "last_name": "የአባት ስም", + "gender": "ፆታ", + "male": "ወንድ", + "female": "ሴት", + "phone_number": "የስልክ ቁጥር", + "country": "ሀገር", + "region": "ክልል", + "select_region": "ክልል ይምረጡ", + "enter_your_city": "ከተማዎን ያስገቡ", + "occupation": "የስራ መስክ", + "select_occupation": "ሙያዎን ይምረጡ", + "save_changes": "ለውጦችን ያስቀምጡ", + "my_progress": "የእኔ እድገት", + "track_your_achievement": "ስኬቶችዎን እና ተከታታይ የትምህርት ጉዞዎን ይከታተሉ", + "account_and_privacy": "መለያ እና ግላዊነት", + "manage_settings": "ቅንብሮችን እና የመተግበሪያ ምርጫዎችን ያስተዳድሩ", + "support": "ድጋፍ", + "get_help": "በስልክ ወይም በቴሌግራም እገዛ ያግኙ", + "logout": "ውጣ", + "app_settings": "የመተግበሪያ ቅንብሮች", + "legal_and_information": "ሕጋዊ እና መረጃ", + "change_language": "ቋንቋ ቀይር", + "terms_and_conditions": "ውሎች እና ሁኔታዎች", + "delete_account": "መለያ ሰርዝ", + "language_preference": "የቋንቋ ምርጫ", + "choose_your_language": "ለውጦችን አስቀምጥ", + "switch_language_anytime": "ቋንቋዎችን በማንኛውም ጊዜ መቀየር ይችላሉ", + "need_help": "እገዛ ይፈልጋሉ?", + "call_support": "የስልክ ድጋፍ", + "talk_with_support": "በቀጥታ ከድጋፍ ቡድናችን ጋር ይነጋገሩ", + "telegram_support": "የቴሌግራም ድጋፍ", + "chat_via_telegram": "በቴሌግራም በፍጥነት ይወያዩ", + "call_our_support": "ከ3 ጠዋት እስከ 12 ማታ ድረስ የድጋፍ ቡድናችንን ይደውሉ", + "tap_to_call": "ለመደወል ይንኩ", + "join_telegram": "በቴሌግራም የይማሩ አካዳሚን ይቀላቀሉ", + "connect_with_support_team": "ለፈጣን እርዳታ እና የማህበረሰብ ዝማኔዎች፣ በቴሌግራም ከድጋፍ ቡድናችን ጋር ወዲያውኑ ይገናኙ።", + "open_in_telegram": "በቴሌግራም ይክፈቱ", + "search_for": "ፈልጉት", + "current_level": "የአሁኑ ደረጃ", + "keep_up_the_great_work": "በጣም ጥሩ እየሰራህ ነው! ቀጥልበት፣ አስደናቂ ነህ።", + "no_practice_available": "ምንም ልምምድ አልተገኘም!", + "begin_module_practice": "የሞጁሉን ልምምድ ጀምር", + "lets_practice_lesson": "እንለማመድ", + "lets_quickly_review": "በዚህ ሞጁል ውስጥ የተማርከውን በፍጥነት እንከልስ!", + "lets_practice_module": "አሁን የተማርከውን እንለማመድ!", + "ask_you_few_actions": "ጥቂት ጥያቄዎችን እጠይቅሃለሁ፣ አንተም በተፈጥሮ መልስ ልትሰጥ ትችላለህ።", + "begin_level_practice": "የደረጃ ልምምድን ጀምር", + "lets_practice_course": "የኮርሱን ልምምድ እንለማመድ", + "lets_quick_review": "በዚህ ደረጃ የተማርከውን በፍጥነት እንከልስ!", + "speaking": "እየተናገረ ነው", + "you_have_finished_practice": "ልምምድህን አጠናቀቅህ", + "view_results": "ውጤቶቼን እይ", + "sample_answer": "ናሙና መልስ", + "your_answer": "መልስህ", + "sound_confident": "በዚህ ጊዜ የበለጠ እምነት ያለህ ይመስላል — በጣም ጥሩ መሻሻል ነው!", + "you_have_completed": "አያይ! አጠናቀቅህ", + "yes": "አዎ", + "no": "አይ", + "want_to_quit": "ለመውጣት እርግጠኛ ነህ?", + "required_field": "ይህ መስክ ያስፈልጋል", + "enter_full_name": "ሙሉ ስምህን አስገባ", + "invalid_email": "የማይሰራ የኢሜይል ቅርጸት", + "phone_must_start_with": "የስልክ ቁጥር በ251 መጀመር አለበት", + "phone_must_be": "የስልክ ቁጥር 12 አሃዞች መሆን አለበት", + "what_should_we_call_you": "ምን ብለን እንጠራህ?", + "name_for_personalization": "በመማር ጉዞህ ውስጥ ለግል ለማድረግ ስምህን እንጠቀማለን።", + "choose_your_gender": "ጾታህን ምረጥ", + "gender_for_personalization": "በጾታህ መሰረት የመማር ተሞክሮህን እናበጅለታለን።", + "age_range": "በየትኛው የእድሜ ክልል ውስጥ ነህ?", + "age_for_personalization": "በእድሜህ መሰረት የመማር ተሞክሮህን እናበጅለታለን።", + "educational_background": "አሁን ያለህ የትምህርት ደረጃ ምንድን ነው?", + "education_for_personalization": "ይህ ትምህርቶችን ከልምድህ ጋር እንዲስማሙ ለማድረግ ይረዳናል።", + "your_occupation": "ስራህ ምንድን ነው?", + "occupation_for_personalization": "በስራህ መሰረት የመማር ተሞክሮህን እናበጅለታለን።", + "location": "ከየት ነህ?", + "select_country_region": "አገርህን እና ክልልህን ከተቆልቋይ ዝርዝሩ ምረጥ", + "select_country": "አገር ምረጥ", + "learning_goal": "የመማር ዓላማህን ምረጥ", + "language_goal": "እንግሊዝኛህን ለማሻሻል ዋና ዓላማህ ምንድን ነው?", + "your_goal": "ዓላማህ የመማር ጉዞህን እንዲስማማ ለማድረግ ይረዳናል።", + "write_your_goal": "ዓላማህን ጻፍ…", + "challenge_you_face": "What challenge do you face most with English?", + "evey_one_has_strugle": "ሁሉም ሰው ችግሮች አሉት፣ የአንተን እንጀምር እንፍታ", + "write_your_challenge": "ችግርህን ጻፍ…", + "topic_interest": "በጣም የሚስቡህ ርዕሶች የትኞቹ ናቸው?", + "favourite_topic": "የምትወዳቸው ርዕሶች አስደሳች እና ከሕይወትህ ጋር የተዛመዱ ትምህርቶችን ለመፍጠር ይረዱናል።", + "your_interest": "ፍላጎትህን ጻፍ…", + "want_quick_assessment": "የእንግሊዝኛ ደረጃህን ለማወቅ ፈጣን ግምገማ ትፈልጋለህ?", + "answer_quick_questions": "የእንግሊዝኛ ችሎታህን ለመረዳት ጥቂት ፈጣን ጥያቄዎችን መልስ።", + "skip": "ዝለል", + "finish_level": "ደረጃውን አጠናቅቅ", + "likely_speaker": "አንተ ምናልባት ተናጋሪ ነህ", + "great_job": "በጣም ጥሩ ስራ! ለመሻሻል ቀጣዩ ደረጃህ ይኸው ነው።", + "lets_start_practice": "ልምምድህን እንጀምር", + "welcome_abroad": "እንኳን ደህና መጣህ", + "ready_to_explore": "የግል ትምህርቶችህን ለማሰስ ዝግጁ ነህ።", + "finish": "አጠናቅቅ", + "finish_all_practice_lesson": "ይህን ልምምድ ለመውሰድ የቀድሞውን የትምህርት ልምምድ ያጠናቅቁ", + "finish_all_practice_module": "የሞጁሉን ልምምድ ለመውሰድ የትምህርት ልምምዶችን ያጠናቅቁ", + "finish_all_practice_course": "የኮርሱን ልምምድ ለመውሰድ የሞጁል ልምምዶችን ያጠናቅቁ", + "finish_all_practice_previouse_module": "ይህን ልምምድ ለመውሰድ የቀድሞውን የሞጁል ልምምድ ያጠናቅቁ", + "finish_all_practice_previouse_course": "ይህን ለመውሰድ የቀድሞውን የኮርስ ልምምድ ያጠናቅቁ", + "track_journey": "የትምህርት ጉዞዎን ይከታተሉ እና በጊዜ ሂደት ያሳዩትን እድገት ይመልከቱ።", + "learn_english": "እንግሊዝኛ ይማሩ", + "keep_momentum": "በጣም ጥሩ ስራ! በዚሁ ብርታት ይቀጥሉ።", + "completed_practices": "የተጠናቀቁ ልምምዶች", + "total_practices": "ጠቅላላ ልምምዶች", + "progress_percentage": "የእድገት መቶኛ" +}; +static const Map _en = { + "loading": "Loading", + "welcome_back": "Welcome back", + "checking_user_info": "Checking user info", + "dont_have_account": "Don't have an account?", + "email": "Email", + "password": "Password", + "forgot_password": "Forgot password?", + "cont": "Continue", + "register": "Register", + "login_with_google": "Login with Google", + "or": "Or", + "login_with_phone": "Login with phone number", + "create_account": "Create an account", + "already_have_account": "Already have an account?", + "login": "Login", + "register_with_google": "Register with Google", + "register_with_phone": "Register with phone number", + "enter_phone_number": "Enter your phone number. We will send you a confirmation code there.", + "login_with_email": "Login with email", + "create_password": "Create password", + "confirm_password": "Confirm password", + "eight_character_minimum": "8 characters minimum", + "password_match": "password match", + "sign_up_agreement": "By clicking ‘Sign Up’, you agree to our ‘Terms of Service’ and ‘Privacy Policy’", + "terms_of_services": "Terms of Service", + "and": "and", + "privacy_policy": "Privacy Policy", + "register_with_email": "Register with email", + "verification_code": "Verification Code", + "resend_code": "Resend Code", + "code_sent_to_phone": "Code sent to your number", + "code_sent_to_email": "Code sent to your email", + "resend_code_in": "Resend code in", + "reset_password": "Reset Password", + "enter_email_reset_code": "Enter your email. We will send you a reset code.", + "please_wait": "Please wait", + "reset_code_sent": "Reset code sent successfully", + "reset_code": "Reset code", + "new_password": "New password", + "logged_in_successfully": "Logged in successfully", + "continue_learning": "Continue Learning", + "start_learning": "Start Learning", + "completed": "Completed", + "view_course": "View course", + "take_practice": "Take practice", + "your_current_level": "Your current level", + "overall_progress": "Overall progress", + "great_work": "Keep up the great work! You're doing amazing", + "view_module": "View module", + "progress": "Progress", + "keep_going": "Let's keep going - you're more than half there", + "lessons_in_module": "Lessons in this module", + "practice": "Practice", + "start": "Start", + "in_progress": "In Progress", + "hello": "Hello", + "ready_to_learn": "Ready to keep learning English today", + "learn": "Learn", + "course": "Course", + "profile": "Profile", + "speaking_partner": "Speaking partner", + "practice_what_you_learned": "Let's practice what you just learnt", + "practice_questions": "I will ask you a few questions and you can respond", + "start_practice": "Start practice", + "almost_there": "You're almost there", + "finish_session": "Finish the session to see your progress", + "continue_practice": "Continue practice", + "end_session": "End session", + "tap_start_to_listen": "Tap the start button to listen", + "practice_speaking": "Practice speaking", + "tap_microphone": "Tap the microphone to speak", + "reply": "Reply", + "cancel": "Cancel", + "you_are_speaking": "You're speaking", + "practice_completed": "Practice completed!", + "great_improvement": "You sound more confident this time, great improvement", + "practice_again": "Practice again", + "conversation_review": "Conversation review", + "result": "Result", + "quick_tip": "Quick tip", + "retry": "Retry", + "completed_a1": "Yay, you've completed A1", + "analyzing_speaking": "We're now analyzing your speaking skill", + "view_profile": "View profile", + "hi": "Hi", + "edit_profile": "Edit profile", + "first_name": "First name", + "last_name": "Last name", + "gender": "Gender", + "male": "Male", + "female": "Female", + "phone_number": "Phone number", + "country": "Country", + "region": "Region", + "select_region": "Select region", + "enter_your_city": "Enter your city", + "occupation": "Occupation", + "select_occupation": "Select occupation", + "save_changes": "Save changes", + "my_progress": "My progress", + "track_your_achievement": "Track your achievements and learning streak", + "account_and_privacy": "Account & Privacy", + "manage_settings": "Manage settings and app preference", + "support": "Support", + "get_help": "Get help through phone or Telegram", + "logout": "Logout", + "app_settings": "App settings", + "legal_and_information": "Legal & Information", + "change_language": "Change language", + "terms_and_conditions": "Terms & Conditions", + "delete_account": "Delete account", + "language_preference": "Language preference", + "choose_your_language": "Choose your language", + "switch_language_anytime": "You can switch languages anytime", + "need_help": "Need help?", + "call_support": "Call support", + "talk_with_support": "Talk with our support team directly", + "telegram_support": "Telegram support", + "chat_via_telegram": "Chat instantly via Telegram", + "call_our_support": "Call our support team between 9 AM - 6 PM", + "tap_to_call": "Tap to call", + "join_telegram": "Join Yimaru Academy on Telegram", + "connect_with_support_team": "Connect with our support team instantly on Telegram for quick assistance and community updates", + "open_in_telegram": "Open in Telegram", + "search_for": "Search for", + "current_level": "Current Level", + "keep_up_the_great_work": "Keep up the great work! You're doing amazing.", + "no_practice_available": "No practice available!", + "begin_module_practice": "Begin Module Practice", + "lets_practice_lesson": "Let’s Practice", + "lets_quickly_review": "Let’s quickly review what you’ve learned in this module!", + "lets_practice_module": "Let's practice what you just learnt!", + "ask_you_few_actions": "I’ll ask you a few questions, and you can respond naturally.", + "begin_level_practice": "Begin Level Practice", + "lets_practice_course": "Let’s Practice Course", + "lets_quick_review": "Let’s quickly review what you’ve learned in this level!", + "speaking": "is speaking...", + "you_have_finished_practice": "You have finished your practice", + "view_results": "View My Results", + "sample_answer": "Sample Answer", + "your_answer": "Your Answer", + "sound_confident": "You sound more confident this time - great improvement!", + "you_have_completed": "Yay, you’ve completed", + "yes": "Yes", + "no": "No", + "want_to_quit": "Are you sure you want to quit?", + "required_field": "The field is required", + "enter_full_name": "Enter your full name", + "invalid_email": "Invalid email format", + "phone_must_start_with": "Phone number must start with 251", + "phone_must_be": "Phone number must be 12 digits", + "what_should_we_call_you": "What should we call you?", + "name_for_personalization": "We’ll use your name to personalize your learning journey.", + "choose_your_gender": "Choose your gender?", + "gender_for_personalization": "We’ll personalize your learning experience based on your gender.", + "age_range": "Which age range are you in?", + "age_for_personalization": "We’ll personalize your learning experience based on your age.", + "educational_background": "What’s your current educational level?", + "education_for_personalization": "This helps us tailor your lessons to your experience.", + "your_occupation": "What’s your occupation?", + "occupation_for_personalization": "We’ll personalize your learning experience based on your occupation.", + "location": "Where are you from?", + "select_country_region": "Select your country and region from the dropdown", + "select_country": "Select country", + "learning_goal": "Choose your learning goal.", + "language_goal": "What’s your main goal for improving your English?", + "your_goal": "Your goal helps us tailor your learning journey.", + "write_your_goal": "Write your goal…", + "challenge_you_face": "What challenge do you face most with English?", + "evey_one_has_strugle": "Everyone has struggles, let’s start fixing yours", + "write_your_challenge": "Write your challenge…", + "topic_interest": "Which topics interest you most?", + "favourite_topic": "Your favorite topics help us create fun, relatable lessons.", + "your_interest": "Write your interest…", + "want_quick_assessment": "Want a quick assessment to know your English level?", + "answer_quick_questions": "Answer a few quick questions to help us understand your English proficiency.", + "skip": "Skip", + "finish_level": "Finish Level", + "likely_speaker": "You’re likely speaker of", + "great_job": "Great Job! Here’s your next step to keep improving.", + "lets_start_practice": "Let's start your practice", + "welcome_abroad": "Welcome aboard", + "ready_to_explore": "You’re ready to explore your personalized lessons.", + "finish": "Finish", + "finish_all_practice_lesson": "Finish the previous lesson practice to take this practice", + "finish_all_practice_module": "Finish the lesson practices to take the Module Practice", + "finish_all_practice_course": "Finish the Module practices to take the Course practice", + "finish_all_practice_previouse_module": "Finish the previous Module practice to take this practice", + "finish_all_practice_previouse_course": "Finish the previous course practice to take this", + "track_journey": "Track your learning journey and see your growth over time.", + "learn_english": "Learn English", + "keep_momentum": "Great job! Keep the momentum.", + "completed_practices": "Completed Practices", + "total_practices": "Total Practices", + "progress_percentage": "Progress Percentage" +}; +static const Map> mapLocales = {"am": _am, "en": _en}; } diff --git a/lib/ui/common/translations/locale_keys.g.dart b/lib/ui/common/translations/locale_keys.g.dart index 9db9a77..c6d4cbc 100644 --- a/lib/ui/common/translations/locale_keys.g.dart +++ b/lib/ui/common/translations/locale_keys.g.dart @@ -2,7 +2,7 @@ // ignore_for_file: constant_identifier_names -abstract class LocaleKeys { +abstract class LocaleKeys { static const loading = 'loading'; static const welcome_back = 'welcome_back'; static const checking_user_info = 'checking_user_info'; @@ -161,8 +161,7 @@ abstract class LocaleKeys { static const educational_background = 'educational_background'; static const education_for_personalization = 'education_for_personalization'; static const your_occupation = 'your_occupation'; - static const occupation_for_personalization = - 'occupation_for_personalization'; + static const occupation_for_personalization = 'occupation_for_personalization'; static const location = 'location'; static const select_country_region = 'select_country_region'; static const select_country = 'select_country'; @@ -189,8 +188,13 @@ abstract class LocaleKeys { static const finish_all_practice_lesson = 'finish_all_practice_lesson'; static const finish_all_practice_module = 'finish_all_practice_module'; static const finish_all_practice_course = 'finish_all_practice_course'; - static const finish_all_practice_previouse_module = - 'finish_all_practice_previouse_module'; - static const finish_all_practice_previouse_course = - 'finish_all_practice_previouse_course'; + static const finish_all_practice_previouse_module = 'finish_all_practice_previouse_module'; + static const finish_all_practice_previouse_course = 'finish_all_practice_previouse_course'; + static const track_journey = 'track_journey'; + static const learn_english = 'learn_english'; + static const keep_momentum = 'keep_momentum'; + static const completed_practices = 'completed_practices'; + static const total_practices = 'total_practices'; + static const progress_percentage = 'progress_percentage'; + } diff --git a/lib/ui/views/home/home_view.dart b/lib/ui/views/home/home_view.dart index 89b3327..9118869 100644 --- a/lib/ui/views/home/home_view.dart +++ b/lib/ui/views/home/home_view.dart @@ -2,15 +2,18 @@ import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:stacked/stacked.dart'; import 'package:yimaru_app/ui/common/app_colors.dart'; +import 'package:yimaru_app/ui/common/enmus.dart'; import 'package:yimaru_app/ui/common/translations/locale_keys.g.dart'; import 'package:yimaru_app/ui/views/learn_program/learn_program_view.dart'; import 'package:yimaru_app/ui/views/profile/profile_view.dart'; +import 'package:yimaru_app/ui/widgets/page_loading_indicator.dart'; import '../../widgets/coming_soon.dart'; import 'home_viewmodel.dart'; class HomeView extends StackedView { const HomeView({Key? key}) : super(key: key); + @override void onViewModelReady(HomeViewModel viewModel) async { await viewModel.inAppUpdate(); @@ -23,7 +26,13 @@ class HomeView extends StackedView { @override Widget builder( BuildContext context, HomeViewModel viewModel, Widget? child) => - _buildScaffold(viewModel); + KeyedSubtree( + key: ValueKey(context.locale.languageCode), + child: _buildScaffoldStack(viewModel)); + + Widget _buildScaffoldStack(HomeViewModel viewModel) => Stack( + children: [_buildScaffold(viewModel), _buildLogoutState(viewModel)], + ); Widget _buildScaffold(HomeViewModel viewModel) => Scaffold( body: getViewForIndex(viewModel.currentPage), @@ -77,4 +86,9 @@ class HomeView extends StackedView { return const ProfileView(); } } + + Widget _buildLogoutState(HomeViewModel viewModel) => + viewModel.state == StateObjects.logout + ? const PageLoadingIndicator() + : Container(); } diff --git a/lib/ui/views/home/home_viewmodel.dart b/lib/ui/views/home/home_viewmodel.dart index 1c35e92..597746e 100644 --- a/lib/ui/views/home/home_viewmodel.dart +++ b/lib/ui/views/home/home_viewmodel.dart @@ -5,6 +5,7 @@ import 'package:yimaru_app/services/status_checker_service.dart'; import 'package:yimaru_app/ui/common/app_strings.dart'; import 'package:stacked/stacked.dart'; import 'package:stacked_services/stacked_services.dart'; +import 'package:yimaru_app/ui/common/enmus.dart'; import '../../../services/authentication_service.dart'; import '../../../services/in_app_update_service.dart'; @@ -12,8 +13,13 @@ import '../../../services/in_app_update_service.dart'; class HomeViewModel extends ReactiveViewModel { // Dependency injection final _statusChecker = locator(); + + final _navigationService = locator(); + final _bottomSheetService = locator(); + final _inAppUpdateService = locator(); + final _authenticationService = locator(); @override @@ -25,6 +31,11 @@ class HomeViewModel extends ReactiveViewModel { User? get user => _user; + // Logout state + StateObjects get _state => _authenticationService.state; + + StateObjects get state => _state; + // Bottom navigation int _currentPage = 0; @@ -44,6 +55,8 @@ class HomeViewModel extends ReactiveViewModel { rebuildUi(); } + + // Remote api calls // In-app update diff --git a/lib/ui/views/language/language_viewmodel.dart b/lib/ui/views/language/language_viewmodel.dart index 8070b22..21d6613 100644 --- a/lib/ui/views/language/language_viewmodel.dart +++ b/lib/ui/views/language/language_viewmodel.dart @@ -29,9 +29,12 @@ class LanguageViewModel extends ReactiveViewModel { Future setSelectedLanguage( {required BuildContext context, - required Map title}) async => - await _localizationService.setSelectedLanguage( - context: context, title: title); + required Map title}) async { + await _localizationService.setSelectedLanguage( + context: context, title: title); + rebuildUi(); + } + // Navigation void pop() => _navigationService.back(); diff --git a/lib/ui/views/learn_lesson/learn_lesson_view.dart b/lib/ui/views/learn_lesson/learn_lesson_view.dart index 25d3c8f..9f9fe50 100644 --- a/lib/ui/views/learn_lesson/learn_lesson_view.dart +++ b/lib/ui/views/learn_lesson/learn_lesson_view.dart @@ -26,12 +26,12 @@ class LearnLessonView extends StackedView { required LearnLesson lesson, required BuildContext context, required LearnLessonViewModel viewModel}) async { - if (lesson.access?.isAccessible ?? false) { +/* if (lesson.access?.isAccessible ?? false) { await viewModel.navigateToLearnPractice(lesson.id ?? 0); } else { await _showSheet(context: context, viewModel: viewModel); - } -/* if (index > 1) { + }*/ + if (index > 1) { if (viewModel.user?.subscriptionStatus?.toLowerCase() == 'subscribed') { if (lesson.access?.isAccessible ?? false) { await viewModel.navigateToLearnPractice(lesson.id ?? 0); @@ -47,7 +47,7 @@ class LearnLessonView extends StackedView { } else { await _showSheet(context: context, viewModel: viewModel); } - }*/ + } } Future _showSheet( diff --git a/lib/ui/views/learn_lesson_detail/learn_lesson_detail_view.dart b/lib/ui/views/learn_lesson_detail/learn_lesson_detail_view.dart index f2708ae..dddfa52 100644 --- a/lib/ui/views/learn_lesson_detail/learn_lesson_detail_view.dart +++ b/lib/ui/views/learn_lesson_detail/learn_lesson_detail_view.dart @@ -31,10 +31,10 @@ class LearnLessonDetailView extends StackedView { Future _onPractice( {required LearnLesson lesson, required LearnLessonDetailViewModel viewModel}) async { - await viewModel.pause(); + /* await viewModel.pause(); await viewModel.navigateToLearnPractice(lesson.id ?? 0); - -/* if (index > 1) { +*/ + if (index > 1) { if (viewModel.user?.subscriptionStatus?.toLowerCase() == 'subscribed') { await viewModel.pause(); await viewModel.navigateToLearnPractice(lesson.id ?? 0); @@ -45,7 +45,7 @@ class LearnLessonDetailView extends StackedView { } else { await viewModel.pause(); await viewModel.navigateToLearnPractice(lesson.id ?? 0); - }*/ + } } @override diff --git a/lib/ui/views/learn_practice/learn_practice_viewmodel.dart b/lib/ui/views/learn_practice/learn_practice_viewmodel.dart index b35fbfb..6ca8a5a 100644 --- a/lib/ui/views/learn_practice/learn_practice_viewmodel.dart +++ b/lib/ui/views/learn_practice/learn_practice_viewmodel.dart @@ -306,7 +306,7 @@ class LearnPracticeViewModel extends ReactiveViewModel { Future _completeLearnPractices() async { if (await _statusChecker.checkConnection()) { await _apiService.completeLearnPractice(_practices.first.id ?? 0); - await _learnService.getLearnProgressSummary(); + await _learnService.getLearnProgress(); } } diff --git a/lib/ui/views/onboarding/onboarding_viewmodel.dart b/lib/ui/views/onboarding/onboarding_viewmodel.dart index ef06bb9..8844c75 100644 --- a/lib/ui/views/onboarding/onboarding_viewmodel.dart +++ b/lib/ui/views/onboarding/onboarding_viewmodel.dart @@ -203,10 +203,10 @@ class OnboardingViewModel extends ReactiveViewModel void setSelectedCountry(FieldOption? value) { _selectedCountry = value; - if (value?.label?.toLowerCase().trim() == 'ethiopia') { + if (value?.code?.toLowerCase().trim() == 'et') { _dropdownRegion = true; _selectedRegion = _regions - .firstWhere((e) => e.label?.toLowerCase().trim() == 'addis ababa'); + .firstWhere((e) => e.code?.toLowerCase().trim().contains('addis_ababa') ?? false); } else { _dropdownRegion = false; } diff --git a/lib/ui/views/profile/profile_view.dart b/lib/ui/views/profile/profile_view.dart index 3a01f65..a1a236e 100644 --- a/lib/ui/views/profile/profile_view.dart +++ b/lib/ui/views/profile/profile_view.dart @@ -166,7 +166,7 @@ class ProfileView extends StackedView { List _buildSettingsChildren(ProfileViewModel viewModel) => [ // _buildDownloadsCard(viewModel), - // _buildProgressCard(viewModel), + _buildProgressCard(viewModel), _buildAccountCard(viewModel), _buildSupportCard(viewModel) ]; diff --git a/lib/ui/views/profile/profile_viewmodel.dart b/lib/ui/views/profile/profile_viewmodel.dart index 6b68fc4..6715fec 100644 --- a/lib/ui/views/profile/profile_viewmodel.dart +++ b/lib/ui/views/profile/profile_viewmodel.dart @@ -68,10 +68,10 @@ class ProfileViewModel extends ReactiveViewModel { DialogResponse? response = await _dialogService.showDialog( barrierDismissible: true, cancelTitleColor: kcDarkGrey, - buttonTitleColor: kcPrimaryColor, title: LocaleKeys.logout.tr(), cancelTitle: LocaleKeys.no.tr(), buttonTitle: LocaleKeys.yes.tr(), + buttonTitleColor: kcPrimaryColor, description: LocaleKeys.want_to_quit.tr(), ); return response?.confirmed; @@ -119,7 +119,6 @@ class ProfileViewModel extends ReactiveViewModel { } Future _logout() async { - await _googleAuthService.logout(); await _authenticationService.logout(); await navigateToLogin(); } diff --git a/lib/ui/views/profile_detail/profile_detail_view.dart b/lib/ui/views/profile_detail/profile_detail_view.dart index b2548b4..daf4d4e 100644 --- a/lib/ui/views/profile_detail/profile_detail_view.dart +++ b/lib/ui/views/profile_detail/profile_detail_view.dart @@ -93,6 +93,7 @@ class ProfileDetailView extends StackedView } void _onModelReady(ProfileDetailViewModel viewModel) { + print('MY RESPONSE: ${viewModel.user?.region}'); phoneNumberController.text = '251900000000'; emailController.text = viewModel.user?.email ?? ''; lastNameController.text = viewModel.user?.lastName ?? ''; @@ -103,9 +104,14 @@ class ProfileDetailView extends StackedView viewModel.setSelectedOccupation(viewModel.occupations .where((e) => (e.code ?? '') == viewModel.user?.occupation) .first); - viewModel.setSelectedCountry(viewModel.countries + viewModel.setSelectedCountry(viewModel.countries .where((e) => (e.code ?? '') == viewModel.user?.country) .first); + if (viewModel.user?.country?.toLowerCase() == 'et') { + viewModel.setEthiopianRegion(viewModel.user?.region ?? ''); + } else { + regionController.text = viewModel.user?.region ?? ''; + } } @override @@ -665,6 +671,7 @@ class ProfileDetailView extends StackedView Icons.search, color: kcPrimaryColor, ); + Widget _buildLowerColumn(ProfileDetailViewModel viewModel) => Column( mainAxisSize: MainAxisSize.min, children: _buildLowerColumnChildren(viewModel), diff --git a/lib/ui/views/profile_detail/profile_detail_viewmodel.dart b/lib/ui/views/profile_detail/profile_detail_viewmodel.dart index 164e8d6..d27b85c 100644 --- a/lib/ui/views/profile_detail/profile_detail_viewmodel.dart +++ b/lib/ui/views/profile_detail/profile_detail_viewmodel.dart @@ -134,12 +134,20 @@ class ProfileDetailViewModel extends ReactiveViewModel List get countries => _countries; + void setEthiopianRegion(String region) { + _dropdownRegion = true; + _selectedRegion = + _regions.firstWhere((r) => r.code?.toLowerCase() == region.toLowerCase()); + + rebuildUi(); + } + void setSelectedCountry(FieldOption? value) { _selectedCountry = value; - if (value?.label?.toLowerCase().trim() == 'ethiopia') { + if (value?.code?.toLowerCase().trim().contains('et') ?? false) { _dropdownRegion = true; - _selectedRegion = _regions - .firstWhere((e) => e.label?.toLowerCase().trim() == 'addis ababa'); + _selectedRegion = _regions.firstWhere( + (e) => e.code?.toLowerCase().trim().contains('addis_ababa') ?? false); } else { _dropdownRegion = false; } diff --git a/lib/ui/views/progress/progress_view.dart b/lib/ui/views/progress/progress_view.dart index df7578e..746033b 100644 --- a/lib/ui/views/progress/progress_view.dart +++ b/lib/ui/views/progress/progress_view.dart @@ -1,5 +1,7 @@ +import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:stacked/stacked.dart'; +import 'package:yimaru_app/ui/common/translations/locale_keys.g.dart'; import '../../common/app_colors.dart'; import '../../common/ui_helpers.dart'; @@ -11,6 +13,12 @@ import 'progress_viewmodel.dart'; class ProgressView extends StackedView { const ProgressView({Key? key}) : super(key: key); + @override + void onViewModelReady(ProgressViewModel viewModel) async { + await viewModel.getProgressSummary(); + super.onViewModelReady(viewModel); + } + @override ProgressViewModel viewModelBuilder(BuildContext context) => ProgressViewModel(); @@ -54,9 +62,9 @@ class ProgressView extends StackedView { ); Widget _buildAppbar(ProgressViewModel viewModel) => SmallAppBar( - title: 'My Progress', showBackButton: true, onPop: viewModel.pop, + title: LocaleKeys.my_progress.tr(), ); Widget _buildContentScrollViewWrapper(ProgressViewModel viewModel) => @@ -81,12 +89,12 @@ class ProgressView extends StackedView { verticalSpaceMedium, _buildLearningProgressCard(), verticalSpaceMedium, - _buildCourseProgressSection() + // _buildCourseProgressSection() ]; - Widget _buildText() => const Text( - 'Track your learning journey and see your growth over time.', - style: TextStyle(color: kcDarkGrey), + Widget _buildText() => Text( + LocaleKeys.track_journey.tr(), + style: style14DG400, ); Widget _buildLearningProgressCard() => const LearningProgressCard(); diff --git a/lib/ui/views/progress/progress_viewmodel.dart b/lib/ui/views/progress/progress_viewmodel.dart index 46dfcad..69022f3 100644 --- a/lib/ui/views/progress/progress_viewmodel.dart +++ b/lib/ui/views/progress/progress_viewmodel.dart @@ -1,12 +1,40 @@ import 'package:stacked/stacked.dart'; import 'package:stacked_services/stacked_services.dart'; +import 'package:yimaru_app/services/learn_service.dart'; +import 'package:yimaru_app/services/status_checker_service.dart'; +import 'package:yimaru_app/ui/common/enmus.dart'; import '../../../app/app.locator.dart'; +import '../../../models/progress_summary.dart'; -class ProgressViewModel extends BaseViewModel { +class ProgressViewModel extends ReactiveViewModel { // Dependency injection + final _learnService = locator(); + final _navigationService = locator(); + final _statusCheckerService = locator(); + + @override + List get listenableServices => [_learnService]; + + + // Total practice count + int get _totalCount => _learnService.totalCount; + + int get totalCount => _totalCount; + + // Completed practice count + int get _completedCount => _learnService.completedCount; + + int get completedCount => _completedCount; + + // Total progress + int get _totalProgress => _learnService.totalProgress; + + int get totalProgress => _totalProgress; + + // Courses final List> _courses = [ { @@ -21,4 +49,17 @@ class ProgressViewModel extends BaseViewModel { // Navigation void pop() => _navigationService.back(); + + // Remote api + + // Learning progress + + Future getProgressSummary() async => runBusyFuture(_getProgressSummary(), + busyObject: StateObjects.progressSummary); + + Future _getProgressSummary() async { + if (await _statusCheckerService.checkConnection()) { + await _learnService.getProgressSummary(); + } + } } diff --git a/lib/ui/views/startup/startup_viewmodel.dart b/lib/ui/views/startup/startup_viewmodel.dart index b1b59bb..58bf30d 100644 --- a/lib/ui/views/startup/startup_viewmodel.dart +++ b/lib/ui/views/startup/startup_viewmodel.dart @@ -122,10 +122,12 @@ class StartupViewModel extends ReactiveViewModel { await _authenticationService.saveUserData(user); - String image = + String? image = await _imageDownloaderService.downloader(user.profilePicture); - await _authenticationService.saveProfilePicture(image); + if (image != null) { + await _authenticationService.saveProfilePicture(image); + } } } } diff --git a/lib/ui/widgets/learn_module_tile.dart b/lib/ui/widgets/learn_module_tile.dart index 24b6dd7..e1ecc91 100644 --- a/lib/ui/widgets/learn_module_tile.dart +++ b/lib/ui/widgets/learn_module_tile.dart @@ -7,7 +7,6 @@ import 'package:yimaru_app/ui/common/translations/locale_keys.g.dart'; import 'package:yimaru_app/ui/views/learn_module/learn_module_viewmodel.dart'; import 'package:yimaru_app/ui/widgets/custom_container_shader.dart'; import 'package:yimaru_app/ui/widgets/custom_linear_progress_indicator.dart'; -import 'package:yimaru_app/ui/widgets/finish_practice_sheet.dart'; import '../common/app_colors.dart'; import '../common/ui_helpers.dart'; diff --git a/lib/ui/widgets/learning_progress_card.dart b/lib/ui/widgets/learning_progress_card.dart index f00fcdc..6afaa38 100644 --- a/lib/ui/widgets/learning_progress_card.dart +++ b/lib/ui/widgets/learning_progress_card.dart @@ -1,4 +1,9 @@ +import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; +import 'package:stacked/stacked.dart'; +import 'package:yimaru_app/ui/common/enmus.dart'; +import 'package:yimaru_app/ui/common/translations/locale_keys.g.dart'; +import 'package:yimaru_app/ui/views/progress/progress_viewmodel.dart'; import 'package:yimaru_app/ui/widgets/custom_column.dart'; import '../common/app_colors.dart'; @@ -6,45 +11,46 @@ import '../common/ui_helpers.dart'; import 'custom_elevated_button.dart'; import 'custom_linear_progress_indicator.dart'; -class LearningProgressCard extends StatelessWidget { +class LearningProgressCard extends ViewModelWidget { final GestureTapCallback? onTap; const LearningProgressCard({super.key, this.onTap}); @override - Widget build(BuildContext context) => _buildContainerWrapper(); + Widget build(BuildContext context, ProgressViewModel viewModel) => + _buildContainerWrapper(viewModel); - Widget _buildContainerWrapper() => GestureDetector( + Widget _buildContainerWrapper(ProgressViewModel viewModel) => GestureDetector( onTap: onTap, - child: _buildContainer(), + child: _buildContainer(viewModel), ); - Widget _buildContainer() => Container( + Widget _buildContainer(ProgressViewModel viewModel) => Container( height: 320, padding: const EdgeInsets.all(15), decoration: BoxDecoration( borderRadius: BorderRadius.circular(5), color: kcPrimaryColor.withOpacity(0.1), ), - child: _buildColumn(), + child: _buildColumn(viewModel), ); - Widget _buildColumn() => Column( + Widget _buildColumn(ProgressViewModel viewModel) => Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, - children: _buildColumnChildren(), + children: _buildColumnChildren(viewModel), ); - List _buildColumnChildren() => [ + List _buildColumnChildren(ProgressViewModel viewModel) => [ _buildIcon(), verticalSpaceSmall, _buildTitle(), verticalSpaceTiny, _buildSubtitle(), verticalSpaceSmall, - _buildProgressIndicator(), + _buildProgressIndicator(viewModel), verticalSpaceSmall, - _buildLearningStatus(), + _buildLearningStatus(viewModel), verticalSpaceMedium, _buildActionButton(), ]; @@ -56,47 +62,64 @@ class LearningProgressCard extends StatelessWidget { ); Widget _buildTitle() => Text( - 'Learn English', + LocaleKeys.learn_english.tr(), style: style16DG600, ); - Widget _buildSubtitle() => const Text( - 'Great job! Keep the momentum.', + Widget _buildSubtitle() => Text( + LocaleKeys.keep_momentum.tr(), maxLines: 2, - style: TextStyle(color: kcMediumGrey), + style: style14MG400, ); - Widget _buildProgressIndicator() => const CustomLinearProgressIndicator( - progress: 0, + Widget _buildProgressIndicator(ProgressViewModel viewModel) => + CustomLinearProgressIndicator( activeColor: kcPrimaryColor, backgroundColor: kcVeryLightGrey, + progress: viewModel.busy(StateObjects.progressSummary) + ? 0 + : viewModel.totalProgress / 100, ); - Widget _buildLearningStatus() => Row( - children: _buildLearningStatusChildren(), + Widget _buildLearningStatus(ProgressViewModel viewModel) => Row( + children: _buildLearningStatusChildren(viewModel), ); - List _buildLearningStatusChildren() => [ - _buildWatchedVideos(), + List _buildLearningStatusChildren(ProgressViewModel viewModel) => [ + _buildCompletedPractices(viewModel), horizontalSpaceSmall, - _buildCompletedPractices(), + _buildTotalPractices(viewModel), horizontalSpaceSmall, - _buildTakenQuizzes() + _buildProgressPercentage(viewModel), ]; - Widget _buildWatchedVideos() => const Expanded( - child: CustomColumn(title: '0', subtitle: 'Videos Watched')); - Widget _buildCompletedPractices() => const Expanded( - child: CustomColumn(title: '0', subtitle: 'Practices Completed')); - Widget _buildTakenQuizzes() => const Expanded( - child: CustomColumn(title: '0', subtitle: 'Quizzes Taken')); + Widget _buildCompletedPractices(ProgressViewModel viewModel) => Expanded( + child: CustomColumn( + title: viewModel.busy(StateObjects.progressSummary) + ? '-' + : viewModel.completedCount.toString(), + subtitle: LocaleKeys.completed_practices.tr())); - Widget _buildActionButton() => const CustomElevatedButton( + Widget _buildTotalPractices(ProgressViewModel viewModel) => Expanded( + child: CustomColumn( + title: viewModel.busy(StateObjects.progressSummary) + ? '-' + : viewModel.totalCount.toString(), + subtitle: LocaleKeys.total_practices.tr())); + + Widget _buildProgressPercentage(ProgressViewModel viewModel) => Expanded( + child: CustomColumn( + title: viewModel.busy(StateObjects.progressSummary) + ? '-' + : '${viewModel.totalProgress.toString()}%', + subtitle: LocaleKeys.progress_percentage.tr())); + + Widget _buildActionButton() => CustomElevatedButton( height: 15, width: 200, borderRadius: 12, - text: 'Continue Learning', foregroundColor: kcWhite, backgroundColor: kcPrimaryColor, + text: LocaleKeys.continue_learning.tr(), ); } diff --git a/pubspec.yaml b/pubspec.yaml index d56ad63..dde6e73 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,5 +1,5 @@ name: yimaru_app -version: 0.1.30+32 +version: 0.1.32+34 publish_to: 'none' description: A new Flutter project.