diff --git a/assets/translations/am.json b/assets/translations/am.json index b002ba2..229e41a 100644 --- a/assets/translations/am.json +++ b/assets/translations/am.json @@ -1,6 +1,7 @@ { - + "loading": "በመጫን ላይ", "welcome_back": "እንኳን በደህና ተመለሱ", + "checking_user_info": "የተጠቃሚ መረጃን በማረጋገጥ ላይ", "dont_have_account": "መለያ የለዎትም? ይመዝገቡ", "email": "ኢሜይል", "password": "የይለፍ ቃል", @@ -19,7 +20,18 @@ "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": "እባክዎ ይጠብቁ", diff --git a/assets/translations/en.json b/assets/translations/en.json index c71689d..09e141c 100644 --- a/assets/translations/en.json +++ b/assets/translations/en.json @@ -1,6 +1,7 @@ - { + {"loading": "Loading", "welcome_back": "Welcome back", + "checking_user_info": "Checking user info", "dont_have_account": "Don't have an account? Register", "email": "Email", "password": "Password", @@ -19,7 +20,18 @@ "login_with_email": "Login with email", "create_password": "Create password", "confirm_password": "Confirm password", + "eight_character_minimum": "8 characters minimum", + "password_math": "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", diff --git a/lib/app/app.dart b/lib/app/app.dart index 49530dc..0367f95 100644 --- a/lib/app/app.dart +++ b/lib/app/app.dart @@ -59,6 +59,7 @@ import 'package:yimaru_app/services/learn_service.dart'; import 'package:yimaru_app/ui/views/course_catalog/course_catalog_view.dart'; import 'package:yimaru_app/ui/views/course_unit/course_unit_view.dart'; import 'package:yimaru_app/services/localization_service.dart'; +import 'package:yimaru_app/ui/views/landing/landing_view.dart'; // @stacked-import @StackedApp( @@ -100,6 +101,7 @@ import 'package:yimaru_app/services/localization_service.dart'; MaterialRoute(page: ArifPayView), MaterialRoute(page: CourseCatalogView), MaterialRoute(page: CourseUnitView), + MaterialRoute(page: LandingView), // @stacked-route ], dependencies: [ diff --git a/lib/app/app.router.dart b/lib/app/app.router.dart index 913371d..960110d 100644 --- a/lib/app/app.router.dart +++ b/lib/app/app.router.dart @@ -7,16 +7,16 @@ // ignore_for_file: no_leading_underscores_for_library_prefixes import 'package:flutter/material.dart'; -import 'package:flutter/material.dart' as _i39; +import 'package:flutter/material.dart' as _i40; import 'package:stacked/stacked.dart' as _i1; -import 'package:stacked_services/stacked_services.dart' as _i47; -import 'package:yimaru_app/models/course.dart' as _i44; -import 'package:yimaru_app/models/course_catalog.dart' as _i46; -import 'package:yimaru_app/models/course_lesson.dart' as _i45; -import 'package:yimaru_app/models/learn_course.dart' as _i40; -import 'package:yimaru_app/models/learn_lesson.dart' as _i42; -import 'package:yimaru_app/models/learn_module.dart' as _i41; -import 'package:yimaru_app/ui/common/enmus.dart' as _i43; +import 'package:stacked_services/stacked_services.dart' as _i48; +import 'package:yimaru_app/models/course.dart' as _i45; +import 'package:yimaru_app/models/course_catalog.dart' as _i47; +import 'package:yimaru_app/models/course_lesson.dart' as _i46; +import 'package:yimaru_app/models/learn_course.dart' as _i41; +import 'package:yimaru_app/models/learn_lesson.dart' as _i43; +import 'package:yimaru_app/models/learn_module.dart' as _i42; +import 'package:yimaru_app/ui/common/enmus.dart' as _i44; import 'package:yimaru_app/ui/views/account_privacy/account_privacy_view.dart' as _i9; import 'package:yimaru_app/ui/views/arif_pay/arif_pay_view.dart' as _i36; @@ -43,6 +43,7 @@ import 'package:yimaru_app/ui/views/failure/failure_view.dart' as _i26; import 'package:yimaru_app/ui/views/forget_password/forget_password_view.dart' as _i21; import 'package:yimaru_app/ui/views/home/home_view.dart' as _i2; +import 'package:yimaru_app/ui/views/landing/landing_view.dart' as _i39; import 'package:yimaru_app/ui/views/language/language_view.dart' as _i13; import 'package:yimaru_app/ui/views/learn_course/learn_course_view.dart' as _i33; @@ -150,6 +151,8 @@ class Routes { static const courseUnitView = '/course-unit-view'; + static const landingView = '/landing-view'; + static const all = { homeView, onboardingView, @@ -188,6 +191,7 @@ class Routes { arifPayView, courseCatalogView, courseUnitView, + landingView, }; } @@ -341,6 +345,10 @@ class StackedRouter extends _i1.RouterBase { Routes.courseUnitView, page: _i38.CourseUnitView, ), + _i1.RouteDef( + Routes.landingView, + page: _i39.LandingView, + ), ]; final _pagesMap = { @@ -348,7 +356,7 @@ class StackedRouter extends _i1.RouterBase { final args = data.getArgs( orElse: () => const HomeViewArguments(), ); - return _i39.MaterialPageRoute( + return _i40.MaterialPageRoute( builder: (context) => _i2.HomeView(key: args.key), settings: data, ); @@ -357,7 +365,7 @@ class StackedRouter extends _i1.RouterBase { final args = data.getArgs( orElse: () => const OnboardingViewArguments(), ); - return _i39.MaterialPageRoute( + return _i40.MaterialPageRoute( builder: (context) => _i3.OnboardingView(key: args.key), settings: data, ); @@ -366,7 +374,7 @@ class StackedRouter extends _i1.RouterBase { final args = data.getArgs( orElse: () => const StartupViewArguments(), ); - return _i39.MaterialPageRoute( + return _i40.MaterialPageRoute( builder: (context) => _i4.StartupView(key: args.key, label: args.label), settings: data, ); @@ -375,7 +383,7 @@ class StackedRouter extends _i1.RouterBase { final args = data.getArgs( orElse: () => const ProfileViewArguments(), ); - return _i39.MaterialPageRoute( + return _i40.MaterialPageRoute( builder: (context) => _i5.ProfileView(key: args.key), settings: data, ); @@ -384,7 +392,7 @@ class StackedRouter extends _i1.RouterBase { final args = data.getArgs( orElse: () => const ProfileDetailViewArguments(), ); - return _i39.MaterialPageRoute( + return _i40.MaterialPageRoute( builder: (context) => _i6.ProfileDetailView(key: args.key), settings: data, ); @@ -393,7 +401,7 @@ class StackedRouter extends _i1.RouterBase { final args = data.getArgs( orElse: () => const DownloadsViewArguments(), ); - return _i39.MaterialPageRoute( + return _i40.MaterialPageRoute( builder: (context) => _i7.DownloadsView(key: args.key), settings: data, ); @@ -402,7 +410,7 @@ class StackedRouter extends _i1.RouterBase { final args = data.getArgs( orElse: () => const ProgressViewArguments(), ); - return _i39.MaterialPageRoute( + return _i40.MaterialPageRoute( builder: (context) => _i8.ProgressView(key: args.key), settings: data, ); @@ -411,7 +419,7 @@ class StackedRouter extends _i1.RouterBase { final args = data.getArgs( orElse: () => const AccountPrivacyViewArguments(), ); - return _i39.MaterialPageRoute( + return _i40.MaterialPageRoute( builder: (context) => _i9.AccountPrivacyView(key: args.key), settings: data, ); @@ -420,7 +428,7 @@ class StackedRouter extends _i1.RouterBase { final args = data.getArgs( orElse: () => const SupportViewArguments(), ); - return _i39.MaterialPageRoute( + return _i40.MaterialPageRoute( builder: (context) => _i10.SupportView(key: args.key), settings: data, ); @@ -429,7 +437,7 @@ class StackedRouter extends _i1.RouterBase { final args = data.getArgs( orElse: () => const TelegramSupportViewArguments(), ); - return _i39.MaterialPageRoute( + return _i40.MaterialPageRoute( builder: (context) => _i11.TelegramSupportView(key: args.key), settings: data, ); @@ -438,7 +446,7 @@ class StackedRouter extends _i1.RouterBase { final args = data.getArgs( orElse: () => const CallSupportViewArguments(), ); - return _i39.MaterialPageRoute( + return _i40.MaterialPageRoute( builder: (context) => _i12.CallSupportView(key: args.key), settings: data, ); @@ -447,7 +455,7 @@ class StackedRouter extends _i1.RouterBase { final args = data.getArgs( orElse: () => const LanguageViewArguments(), ); - return _i39.MaterialPageRoute( + return _i40.MaterialPageRoute( builder: (context) => _i13.LanguageView(key: args.key), settings: data, ); @@ -456,7 +464,7 @@ class StackedRouter extends _i1.RouterBase { final args = data.getArgs( orElse: () => const PrivacyPolicyViewArguments(), ); - return _i39.MaterialPageRoute( + return _i40.MaterialPageRoute( builder: (context) => _i14.PrivacyPolicyView(key: args.key), settings: data, ); @@ -465,7 +473,7 @@ class StackedRouter extends _i1.RouterBase { final args = data.getArgs( orElse: () => const TermsAndConditionsViewArguments(), ); - return _i39.MaterialPageRoute( + return _i40.MaterialPageRoute( builder: (context) => _i15.TermsAndConditionsView(key: args.key), settings: data, ); @@ -474,7 +482,7 @@ class StackedRouter extends _i1.RouterBase { final args = data.getArgs( orElse: () => const RegisterViewArguments(), ); - return _i39.MaterialPageRoute( + return _i40.MaterialPageRoute( builder: (context) => _i16.RegisterView(key: args.key), settings: data, ); @@ -483,14 +491,14 @@ class StackedRouter extends _i1.RouterBase { final args = data.getArgs( orElse: () => const LoginViewArguments(), ); - return _i39.MaterialPageRoute( + return _i40.MaterialPageRoute( builder: (context) => _i17.LoginView(key: args.key), settings: data, ); }, _i18.LearnModuleView: (data) { final args = data.getArgs(nullOk: false); - return _i39.MaterialPageRoute( + return _i40.MaterialPageRoute( builder: (context) => _i18.LearnModuleView(key: args.key, course: args.course), settings: data, @@ -500,14 +508,14 @@ class StackedRouter extends _i1.RouterBase { final args = data.getArgs( orElse: () => const WelcomeViewArguments(), ); - return _i39.MaterialPageRoute( + return _i40.MaterialPageRoute( builder: (context) => _i19.WelcomeView(key: args.key), settings: data, ); }, _i20.LearnLessonView: (data) { final args = data.getArgs(nullOk: false); - return _i39.MaterialPageRoute( + return _i40.MaterialPageRoute( builder: (context) => _i20.LearnLessonView(key: args.key, module: args.module), settings: data, @@ -517,14 +525,14 @@ class StackedRouter extends _i1.RouterBase { final args = data.getArgs( orElse: () => const ForgetPasswordViewArguments(), ); - return _i39.MaterialPageRoute( + return _i40.MaterialPageRoute( builder: (context) => _i21.ForgetPasswordView(key: args.key), settings: data, ); }, _i22.LearnLessonDetailView: (data) { final args = data.getArgs(nullOk: false); - return _i39.MaterialPageRoute( + return _i40.MaterialPageRoute( builder: (context) => _i22.LearnLessonDetailView( key: args.key, lesson: args.lesson, @@ -535,7 +543,7 @@ class StackedRouter extends _i1.RouterBase { }, _i23.LearnPracticeView: (data) { final args = data.getArgs(nullOk: false); - return _i39.MaterialPageRoute( + return _i40.MaterialPageRoute( builder: (context) => _i23.LearnPracticeView( key: args.key, level: args.level, @@ -549,7 +557,7 @@ class StackedRouter extends _i1.RouterBase { }, _i24.CoursePracticeView: (data) { final args = data.getArgs(nullOk: false); - return _i39.MaterialPageRoute( + return _i40.MaterialPageRoute( builder: (context) => _i24.CoursePracticeView(key: args.key, id: args.id), settings: data, @@ -557,7 +565,7 @@ class StackedRouter extends _i1.RouterBase { }, _i25.CoursePaymentView: (data) { final args = data.getArgs(nullOk: false); - return _i39.MaterialPageRoute( + return _i40.MaterialPageRoute( builder: (context) => _i25.CoursePaymentView(key: args.key, course: args.course), settings: data, @@ -565,7 +573,7 @@ class StackedRouter extends _i1.RouterBase { }, _i26.FailureView: (data) { final args = data.getArgs(nullOk: false); - return _i39.MaterialPageRoute( + return _i40.MaterialPageRoute( builder: (context) => _i26.FailureView( key: args.key, onTap: args.onTap, label: args.label), settings: data, @@ -573,7 +581,7 @@ class StackedRouter extends _i1.RouterBase { }, _i27.CourseLessonView: (data) { final args = data.getArgs(nullOk: false); - return _i39.MaterialPageRoute( + return _i40.MaterialPageRoute( builder: (context) => _i27.CourseLessonView(key: args.key, course: args.course), settings: data, @@ -581,7 +589,7 @@ class StackedRouter extends _i1.RouterBase { }, _i28.CourseLessonDetailView: (data) { final args = data.getArgs(nullOk: false); - return _i39.MaterialPageRoute( + return _i40.MaterialPageRoute( builder: (context) => _i28.CourseLessonDetailView(key: args.key, lesson: args.lesson), settings: data, @@ -591,7 +599,7 @@ class StackedRouter extends _i1.RouterBase { final args = data.getArgs( orElse: () => const DuolingoViewArguments(), ); - return _i39.MaterialPageRoute( + return _i40.MaterialPageRoute( builder: (context) => _i29.DuolingoView(key: args.key), settings: data, ); @@ -600,7 +608,7 @@ class StackedRouter extends _i1.RouterBase { final args = data.getArgs( orElse: () => const CourseViewArguments(), ); - return _i39.MaterialPageRoute( + return _i40.MaterialPageRoute( builder: (context) => _i30.CourseView(key: args.key), settings: data, ); @@ -608,7 +616,7 @@ class StackedRouter extends _i1.RouterBase { _i31.CoursePracticeQuestionView: (data) { final args = data.getArgs(nullOk: false); - return _i39.MaterialPageRoute( + return _i40.MaterialPageRoute( builder: (context) => _i31.CoursePracticeQuestionView(key: args.key, id: args.id), settings: data, @@ -618,21 +626,21 @@ class StackedRouter extends _i1.RouterBase { final args = data.getArgs( orElse: () => const LearnProgramViewArguments(), ); - return _i39.MaterialPageRoute( + return _i40.MaterialPageRoute( builder: (context) => _i32.LearnProgramView(key: args.key), settings: data, ); }, _i33.LearnCourseView: (data) { final args = data.getArgs(nullOk: false); - return _i39.MaterialPageRoute( + return _i40.MaterialPageRoute( builder: (context) => _i33.LearnCourseView(key: args.key, id: args.id), settings: data, ); }, _i34.AssessmentView: (data) { final args = data.getArgs(nullOk: false); - return _i39.MaterialPageRoute( + return _i40.MaterialPageRoute( builder: (context) => _i34.AssessmentView(key: args.key, data: args.data), settings: data, @@ -642,14 +650,14 @@ class StackedRouter extends _i1.RouterBase { final args = data.getArgs( orElse: () => const LearnSubscriptionViewArguments(), ); - return _i39.MaterialPageRoute( + return _i40.MaterialPageRoute( builder: (context) => _i35.LearnSubscriptionView(key: args.key), settings: data, ); }, _i36.ArifPayView: (data) { final args = data.getArgs(nullOk: false); - return _i39.MaterialPageRoute( + return _i40.MaterialPageRoute( builder: (context) => _i36.ArifPayView(key: args.key, phone: args.phone), settings: data, @@ -659,19 +667,28 @@ class StackedRouter extends _i1.RouterBase { final args = data.getArgs( orElse: () => const CourseCatalogViewArguments(), ); - return _i39.MaterialPageRoute( + return _i40.MaterialPageRoute( builder: (context) => _i37.CourseCatalogView(key: args.key), settings: data, ); }, _i38.CourseUnitView: (data) { final args = data.getArgs(nullOk: false); - return _i39.MaterialPageRoute( + return _i40.MaterialPageRoute( builder: (context) => _i38.CourseUnitView(key: args.key, catalog: args.catalog), settings: data, ); }, + _i39.LandingView: (data) { + final args = data.getArgs( + orElse: () => const LandingViewArguments(), + ); + return _i40.MaterialPageRoute( + builder: (context) => _i39.LandingView(key: args.key), + settings: data, + ); + }, }; @override @@ -684,7 +701,7 @@ class StackedRouter extends _i1.RouterBase { class HomeViewArguments { const HomeViewArguments({this.key}); - final _i39.Key? key; + final _i40.Key? key; @override String toString() { @@ -706,7 +723,7 @@ class HomeViewArguments { class OnboardingViewArguments { const OnboardingViewArguments({this.key}); - final _i39.Key? key; + final _i40.Key? key; @override String toString() { @@ -728,12 +745,12 @@ class OnboardingViewArguments { class StartupViewArguments { const StartupViewArguments({ this.key, - this.label = 'Loading', + this.label, }); - final _i39.Key? key; + final _i40.Key? key; - final String label; + final String? label; @override String toString() { @@ -755,7 +772,7 @@ class StartupViewArguments { class ProfileViewArguments { const ProfileViewArguments({this.key}); - final _i39.Key? key; + final _i40.Key? key; @override String toString() { @@ -777,7 +794,7 @@ class ProfileViewArguments { class ProfileDetailViewArguments { const ProfileDetailViewArguments({this.key}); - final _i39.Key? key; + final _i40.Key? key; @override String toString() { @@ -799,7 +816,7 @@ class ProfileDetailViewArguments { class DownloadsViewArguments { const DownloadsViewArguments({this.key}); - final _i39.Key? key; + final _i40.Key? key; @override String toString() { @@ -821,7 +838,7 @@ class DownloadsViewArguments { class ProgressViewArguments { const ProgressViewArguments({this.key}); - final _i39.Key? key; + final _i40.Key? key; @override String toString() { @@ -843,7 +860,7 @@ class ProgressViewArguments { class AccountPrivacyViewArguments { const AccountPrivacyViewArguments({this.key}); - final _i39.Key? key; + final _i40.Key? key; @override String toString() { @@ -865,7 +882,7 @@ class AccountPrivacyViewArguments { class SupportViewArguments { const SupportViewArguments({this.key}); - final _i39.Key? key; + final _i40.Key? key; @override String toString() { @@ -887,7 +904,7 @@ class SupportViewArguments { class TelegramSupportViewArguments { const TelegramSupportViewArguments({this.key}); - final _i39.Key? key; + final _i40.Key? key; @override String toString() { @@ -909,7 +926,7 @@ class TelegramSupportViewArguments { class CallSupportViewArguments { const CallSupportViewArguments({this.key}); - final _i39.Key? key; + final _i40.Key? key; @override String toString() { @@ -931,7 +948,7 @@ class CallSupportViewArguments { class LanguageViewArguments { const LanguageViewArguments({this.key}); - final _i39.Key? key; + final _i40.Key? key; @override String toString() { @@ -953,7 +970,7 @@ class LanguageViewArguments { class PrivacyPolicyViewArguments { const PrivacyPolicyViewArguments({this.key}); - final _i39.Key? key; + final _i40.Key? key; @override String toString() { @@ -975,7 +992,7 @@ class PrivacyPolicyViewArguments { class TermsAndConditionsViewArguments { const TermsAndConditionsViewArguments({this.key}); - final _i39.Key? key; + final _i40.Key? key; @override String toString() { @@ -997,7 +1014,7 @@ class TermsAndConditionsViewArguments { class RegisterViewArguments { const RegisterViewArguments({this.key}); - final _i39.Key? key; + final _i40.Key? key; @override String toString() { @@ -1019,7 +1036,7 @@ class RegisterViewArguments { class LoginViewArguments { const LoginViewArguments({this.key}); - final _i39.Key? key; + final _i40.Key? key; @override String toString() { @@ -1044,9 +1061,9 @@ class LearnModuleViewArguments { required this.course, }); - final _i39.Key? key; + final _i40.Key? key; - final _i40.LearnCourse course; + final _i41.LearnCourse course; @override String toString() { @@ -1068,7 +1085,7 @@ class LearnModuleViewArguments { class WelcomeViewArguments { const WelcomeViewArguments({this.key}); - final _i39.Key? key; + final _i40.Key? key; @override String toString() { @@ -1093,9 +1110,9 @@ class LearnLessonViewArguments { required this.module, }); - final _i39.Key? key; + final _i40.Key? key; - final _i41.LearnModule module; + final _i42.LearnModule module; @override String toString() { @@ -1117,7 +1134,7 @@ class LearnLessonViewArguments { class ForgetPasswordViewArguments { const ForgetPasswordViewArguments({this.key}); - final _i39.Key? key; + final _i40.Key? key; @override String toString() { @@ -1144,11 +1161,11 @@ class LearnLessonDetailViewArguments { required this.hasPractice, }); - final _i39.Key? key; + final _i40.Key? key; - final _i42.LearnLesson lesson; + final _i43.LearnLesson lesson; - final _i41.LearnModule module; + final _i42.LearnModule module; final bool hasPractice; @@ -1186,7 +1203,7 @@ class LearnPracticeViewArguments { required this.subtitle, }); - final _i39.Key? key; + final _i40.Key? key; final String? level; @@ -1196,7 +1213,7 @@ class LearnPracticeViewArguments { final String title; - final _i43.LearnPractices practice; + final _i44.LearnPractices practice; final String subtitle; @@ -1235,7 +1252,7 @@ class CoursePracticeViewArguments { required this.id, }); - final _i39.Key? key; + final _i40.Key? key; final int id; @@ -1262,9 +1279,9 @@ class CoursePaymentViewArguments { required this.course, }); - final _i39.Key? key; + final _i40.Key? key; - final _i44.Course course; + final _i45.Course course; @override String toString() { @@ -1290,7 +1307,7 @@ class FailureViewArguments { required this.label, }); - final _i39.Key? key; + final _i40.Key? key; final void Function() onTap; @@ -1319,9 +1336,9 @@ class CourseLessonViewArguments { required this.course, }); - final _i39.Key? key; + final _i40.Key? key; - final _i44.Course course; + final _i45.Course course; @override String toString() { @@ -1346,9 +1363,9 @@ class CourseLessonDetailViewArguments { required this.lesson, }); - final _i39.Key? key; + final _i40.Key? key; - final _i45.CourseLesson lesson; + final _i46.CourseLesson lesson; @override String toString() { @@ -1370,7 +1387,7 @@ class CourseLessonDetailViewArguments { class DuolingoViewArguments { const DuolingoViewArguments({this.key}); - final _i39.Key? key; + final _i40.Key? key; @override String toString() { @@ -1392,7 +1409,7 @@ class DuolingoViewArguments { class CourseViewArguments { const CourseViewArguments({this.key}); - final _i39.Key? key; + final _i40.Key? key; @override String toString() { @@ -1417,7 +1434,7 @@ class CoursePracticeQuestionViewArguments { required this.id, }); - final _i39.Key? key; + final _i40.Key? key; final int id; @@ -1441,7 +1458,7 @@ class CoursePracticeQuestionViewArguments { class LearnProgramViewArguments { const LearnProgramViewArguments({this.key}); - final _i39.Key? key; + final _i40.Key? key; @override String toString() { @@ -1466,7 +1483,7 @@ class LearnCourseViewArguments { required this.id, }); - final _i39.Key? key; + final _i40.Key? key; final int id; @@ -1493,7 +1510,7 @@ class AssessmentViewArguments { required this.data, }); - final _i39.Key? key; + final _i40.Key? key; final Map data; @@ -1517,7 +1534,7 @@ class AssessmentViewArguments { class LearnSubscriptionViewArguments { const LearnSubscriptionViewArguments({this.key}); - final _i39.Key? key; + final _i40.Key? key; @override String toString() { @@ -1542,7 +1559,7 @@ class ArifPayViewArguments { required this.phone, }); - final _i39.Key? key; + final _i40.Key? key; final String phone; @@ -1566,7 +1583,7 @@ class ArifPayViewArguments { class CourseCatalogViewArguments { const CourseCatalogViewArguments({this.key}); - final _i39.Key? key; + final _i40.Key? key; @override String toString() { @@ -1591,9 +1608,9 @@ class CourseUnitViewArguments { required this.catalog, }); - final _i39.Key? key; + final _i40.Key? key; - final _i46.CourseCatalog catalog; + final _i47.CourseCatalog catalog; @override String toString() { @@ -1612,9 +1629,31 @@ class CourseUnitViewArguments { } } -extension NavigatorStateExtension on _i47.NavigationService { +class LandingViewArguments { + const LandingViewArguments({this.key}); + + final _i40.Key? key; + + @override + String toString() { + return '{"key": "$key"}'; + } + + @override + bool operator ==(covariant LandingViewArguments other) { + if (identical(this, other)) return true; + return other.key == key; + } + + @override + int get hashCode { + return key.hashCode; + } +} + +extension NavigatorStateExtension on _i48.NavigationService { Future navigateToHomeView({ - _i39.Key? key, + _i40.Key? key, int? routerId, bool preventDuplicates = true, Map? parameters, @@ -1630,7 +1669,7 @@ extension NavigatorStateExtension on _i47.NavigationService { } Future navigateToOnboardingView({ - _i39.Key? key, + _i40.Key? key, int? routerId, bool preventDuplicates = true, Map? parameters, @@ -1646,8 +1685,8 @@ extension NavigatorStateExtension on _i47.NavigationService { } Future navigateToStartupView({ - _i39.Key? key, - String label = 'Loading', + _i40.Key? key, + String? label, int? routerId, bool preventDuplicates = true, Map? parameters, @@ -1663,7 +1702,7 @@ extension NavigatorStateExtension on _i47.NavigationService { } Future navigateToProfileView({ - _i39.Key? key, + _i40.Key? key, int? routerId, bool preventDuplicates = true, Map? parameters, @@ -1679,7 +1718,7 @@ extension NavigatorStateExtension on _i47.NavigationService { } Future navigateToProfileDetailView({ - _i39.Key? key, + _i40.Key? key, int? routerId, bool preventDuplicates = true, Map? parameters, @@ -1695,7 +1734,7 @@ extension NavigatorStateExtension on _i47.NavigationService { } Future navigateToDownloadsView({ - _i39.Key? key, + _i40.Key? key, int? routerId, bool preventDuplicates = true, Map? parameters, @@ -1711,7 +1750,7 @@ extension NavigatorStateExtension on _i47.NavigationService { } Future navigateToProgressView({ - _i39.Key? key, + _i40.Key? key, int? routerId, bool preventDuplicates = true, Map? parameters, @@ -1727,7 +1766,7 @@ extension NavigatorStateExtension on _i47.NavigationService { } Future navigateToAccountPrivacyView({ - _i39.Key? key, + _i40.Key? key, int? routerId, bool preventDuplicates = true, Map? parameters, @@ -1743,7 +1782,7 @@ extension NavigatorStateExtension on _i47.NavigationService { } Future navigateToSupportView({ - _i39.Key? key, + _i40.Key? key, int? routerId, bool preventDuplicates = true, Map? parameters, @@ -1759,7 +1798,7 @@ extension NavigatorStateExtension on _i47.NavigationService { } Future navigateToTelegramSupportView({ - _i39.Key? key, + _i40.Key? key, int? routerId, bool preventDuplicates = true, Map? parameters, @@ -1775,7 +1814,7 @@ extension NavigatorStateExtension on _i47.NavigationService { } Future navigateToCallSupportView({ - _i39.Key? key, + _i40.Key? key, int? routerId, bool preventDuplicates = true, Map? parameters, @@ -1791,7 +1830,7 @@ extension NavigatorStateExtension on _i47.NavigationService { } Future navigateToLanguageView({ - _i39.Key? key, + _i40.Key? key, int? routerId, bool preventDuplicates = true, Map? parameters, @@ -1807,7 +1846,7 @@ extension NavigatorStateExtension on _i47.NavigationService { } Future navigateToPrivacyPolicyView({ - _i39.Key? key, + _i40.Key? key, int? routerId, bool preventDuplicates = true, Map? parameters, @@ -1823,7 +1862,7 @@ extension NavigatorStateExtension on _i47.NavigationService { } Future navigateToTermsAndConditionsView({ - _i39.Key? key, + _i40.Key? key, int? routerId, bool preventDuplicates = true, Map? parameters, @@ -1839,7 +1878,7 @@ extension NavigatorStateExtension on _i47.NavigationService { } Future navigateToRegisterView({ - _i39.Key? key, + _i40.Key? key, int? routerId, bool preventDuplicates = true, Map? parameters, @@ -1855,7 +1894,7 @@ extension NavigatorStateExtension on _i47.NavigationService { } Future navigateToLoginView({ - _i39.Key? key, + _i40.Key? key, int? routerId, bool preventDuplicates = true, Map? parameters, @@ -1871,8 +1910,8 @@ extension NavigatorStateExtension on _i47.NavigationService { } Future navigateToLearnModuleView({ - _i39.Key? key, - required _i40.LearnCourse course, + _i40.Key? key, + required _i41.LearnCourse course, int? routerId, bool preventDuplicates = true, Map? parameters, @@ -1888,7 +1927,7 @@ extension NavigatorStateExtension on _i47.NavigationService { } Future navigateToWelcomeView({ - _i39.Key? key, + _i40.Key? key, int? routerId, bool preventDuplicates = true, Map? parameters, @@ -1904,8 +1943,8 @@ extension NavigatorStateExtension on _i47.NavigationService { } Future navigateToLearnLessonView({ - _i39.Key? key, - required _i41.LearnModule module, + _i40.Key? key, + required _i42.LearnModule module, int? routerId, bool preventDuplicates = true, Map? parameters, @@ -1921,7 +1960,7 @@ extension NavigatorStateExtension on _i47.NavigationService { } Future navigateToForgetPasswordView({ - _i39.Key? key, + _i40.Key? key, int? routerId, bool preventDuplicates = true, Map? parameters, @@ -1937,9 +1976,9 @@ extension NavigatorStateExtension on _i47.NavigationService { } Future navigateToLearnLessonDetailView({ - _i39.Key? key, - required _i42.LearnLesson lesson, - required _i41.LearnModule module, + _i40.Key? key, + required _i43.LearnLesson lesson, + required _i42.LearnModule module, required bool hasPractice, int? routerId, bool preventDuplicates = true, @@ -1957,12 +1996,12 @@ extension NavigatorStateExtension on _i47.NavigationService { } Future navigateToLearnPracticeView({ - _i39.Key? key, + _i40.Key? key, String? level, required int id, required String label, required String title, - required _i43.LearnPractices practice, + required _i44.LearnPractices practice, required String subtitle, int? routerId, bool preventDuplicates = true, @@ -1986,7 +2025,7 @@ extension NavigatorStateExtension on _i47.NavigationService { } Future navigateToCoursePracticeView({ - _i39.Key? key, + _i40.Key? key, required int id, int? routerId, bool preventDuplicates = true, @@ -2003,8 +2042,8 @@ extension NavigatorStateExtension on _i47.NavigationService { } Future navigateToCoursePaymentView({ - _i39.Key? key, - required _i44.Course course, + _i40.Key? key, + required _i45.Course course, int? routerId, bool preventDuplicates = true, Map? parameters, @@ -2020,7 +2059,7 @@ extension NavigatorStateExtension on _i47.NavigationService { } Future navigateToFailureView({ - _i39.Key? key, + _i40.Key? key, required void Function() onTap, required String label, int? routerId, @@ -2038,8 +2077,8 @@ extension NavigatorStateExtension on _i47.NavigationService { } Future navigateToCourseLessonView({ - _i39.Key? key, - required _i44.Course course, + _i40.Key? key, + required _i45.Course course, int? routerId, bool preventDuplicates = true, Map? parameters, @@ -2055,8 +2094,8 @@ extension NavigatorStateExtension on _i47.NavigationService { } Future navigateToCourseLessonDetailView({ - _i39.Key? key, - required _i45.CourseLesson lesson, + _i40.Key? key, + required _i46.CourseLesson lesson, int? routerId, bool preventDuplicates = true, Map? parameters, @@ -2072,7 +2111,7 @@ extension NavigatorStateExtension on _i47.NavigationService { } Future navigateToDuolingoView({ - _i39.Key? key, + _i40.Key? key, int? routerId, bool preventDuplicates = true, Map? parameters, @@ -2088,7 +2127,7 @@ extension NavigatorStateExtension on _i47.NavigationService { } Future navigateToCourseView({ - _i39.Key? key, + _i40.Key? key, int? routerId, bool preventDuplicates = true, Map? parameters, @@ -2104,7 +2143,7 @@ extension NavigatorStateExtension on _i47.NavigationService { } Future navigateToCoursePracticeQuestionView({ - _i39.Key? key, + _i40.Key? key, required int id, int? routerId, bool preventDuplicates = true, @@ -2121,7 +2160,7 @@ extension NavigatorStateExtension on _i47.NavigationService { } Future navigateToLearnProgramView({ - _i39.Key? key, + _i40.Key? key, int? routerId, bool preventDuplicates = true, Map? parameters, @@ -2137,7 +2176,7 @@ extension NavigatorStateExtension on _i47.NavigationService { } Future navigateToLearnCourseView({ - _i39.Key? key, + _i40.Key? key, required int id, int? routerId, bool preventDuplicates = true, @@ -2154,7 +2193,7 @@ extension NavigatorStateExtension on _i47.NavigationService { } Future navigateToAssessmentView({ - _i39.Key? key, + _i40.Key? key, required Map data, int? routerId, bool preventDuplicates = true, @@ -2171,7 +2210,7 @@ extension NavigatorStateExtension on _i47.NavigationService { } Future navigateToLearnSubscriptionView({ - _i39.Key? key, + _i40.Key? key, int? routerId, bool preventDuplicates = true, Map? parameters, @@ -2187,7 +2226,7 @@ extension NavigatorStateExtension on _i47.NavigationService { } Future navigateToArifPayView({ - _i39.Key? key, + _i40.Key? key, required String phone, int? routerId, bool preventDuplicates = true, @@ -2204,7 +2243,7 @@ extension NavigatorStateExtension on _i47.NavigationService { } Future navigateToCourseCatalogView({ - _i39.Key? key, + _i40.Key? key, int? routerId, bool preventDuplicates = true, Map? parameters, @@ -2220,8 +2259,8 @@ extension NavigatorStateExtension on _i47.NavigationService { } Future navigateToCourseUnitView({ - _i39.Key? key, - required _i46.CourseCatalog catalog, + _i40.Key? key, + required _i47.CourseCatalog catalog, int? routerId, bool preventDuplicates = true, Map? parameters, @@ -2236,8 +2275,24 @@ extension NavigatorStateExtension on _i47.NavigationService { transition: transition); } + Future navigateToLandingView({ + _i40.Key? key, + int? routerId, + bool preventDuplicates = true, + Map? parameters, + Widget Function(BuildContext, Animation, Animation, Widget)? + transition, + }) async { + return navigateTo(Routes.landingView, + arguments: LandingViewArguments(key: key), + id: routerId, + preventDuplicates: preventDuplicates, + parameters: parameters, + transition: transition); + } + Future replaceWithHomeView({ - _i39.Key? key, + _i40.Key? key, int? routerId, bool preventDuplicates = true, Map? parameters, @@ -2253,7 +2308,7 @@ extension NavigatorStateExtension on _i47.NavigationService { } Future replaceWithOnboardingView({ - _i39.Key? key, + _i40.Key? key, int? routerId, bool preventDuplicates = true, Map? parameters, @@ -2269,8 +2324,8 @@ extension NavigatorStateExtension on _i47.NavigationService { } Future replaceWithStartupView({ - _i39.Key? key, - String label = 'Loading', + _i40.Key? key, + String? label, int? routerId, bool preventDuplicates = true, Map? parameters, @@ -2286,7 +2341,7 @@ extension NavigatorStateExtension on _i47.NavigationService { } Future replaceWithProfileView({ - _i39.Key? key, + _i40.Key? key, int? routerId, bool preventDuplicates = true, Map? parameters, @@ -2302,7 +2357,7 @@ extension NavigatorStateExtension on _i47.NavigationService { } Future replaceWithProfileDetailView({ - _i39.Key? key, + _i40.Key? key, int? routerId, bool preventDuplicates = true, Map? parameters, @@ -2318,7 +2373,7 @@ extension NavigatorStateExtension on _i47.NavigationService { } Future replaceWithDownloadsView({ - _i39.Key? key, + _i40.Key? key, int? routerId, bool preventDuplicates = true, Map? parameters, @@ -2334,7 +2389,7 @@ extension NavigatorStateExtension on _i47.NavigationService { } Future replaceWithProgressView({ - _i39.Key? key, + _i40.Key? key, int? routerId, bool preventDuplicates = true, Map? parameters, @@ -2350,7 +2405,7 @@ extension NavigatorStateExtension on _i47.NavigationService { } Future replaceWithAccountPrivacyView({ - _i39.Key? key, + _i40.Key? key, int? routerId, bool preventDuplicates = true, Map? parameters, @@ -2366,7 +2421,7 @@ extension NavigatorStateExtension on _i47.NavigationService { } Future replaceWithSupportView({ - _i39.Key? key, + _i40.Key? key, int? routerId, bool preventDuplicates = true, Map? parameters, @@ -2382,7 +2437,7 @@ extension NavigatorStateExtension on _i47.NavigationService { } Future replaceWithTelegramSupportView({ - _i39.Key? key, + _i40.Key? key, int? routerId, bool preventDuplicates = true, Map? parameters, @@ -2398,7 +2453,7 @@ extension NavigatorStateExtension on _i47.NavigationService { } Future replaceWithCallSupportView({ - _i39.Key? key, + _i40.Key? key, int? routerId, bool preventDuplicates = true, Map? parameters, @@ -2414,7 +2469,7 @@ extension NavigatorStateExtension on _i47.NavigationService { } Future replaceWithLanguageView({ - _i39.Key? key, + _i40.Key? key, int? routerId, bool preventDuplicates = true, Map? parameters, @@ -2430,7 +2485,7 @@ extension NavigatorStateExtension on _i47.NavigationService { } Future replaceWithPrivacyPolicyView({ - _i39.Key? key, + _i40.Key? key, int? routerId, bool preventDuplicates = true, Map? parameters, @@ -2446,7 +2501,7 @@ extension NavigatorStateExtension on _i47.NavigationService { } Future replaceWithTermsAndConditionsView({ - _i39.Key? key, + _i40.Key? key, int? routerId, bool preventDuplicates = true, Map? parameters, @@ -2462,7 +2517,7 @@ extension NavigatorStateExtension on _i47.NavigationService { } Future replaceWithRegisterView({ - _i39.Key? key, + _i40.Key? key, int? routerId, bool preventDuplicates = true, Map? parameters, @@ -2478,7 +2533,7 @@ extension NavigatorStateExtension on _i47.NavigationService { } Future replaceWithLoginView({ - _i39.Key? key, + _i40.Key? key, int? routerId, bool preventDuplicates = true, Map? parameters, @@ -2494,8 +2549,8 @@ extension NavigatorStateExtension on _i47.NavigationService { } Future replaceWithLearnModuleView({ - _i39.Key? key, - required _i40.LearnCourse course, + _i40.Key? key, + required _i41.LearnCourse course, int? routerId, bool preventDuplicates = true, Map? parameters, @@ -2511,7 +2566,7 @@ extension NavigatorStateExtension on _i47.NavigationService { } Future replaceWithWelcomeView({ - _i39.Key? key, + _i40.Key? key, int? routerId, bool preventDuplicates = true, Map? parameters, @@ -2527,8 +2582,8 @@ extension NavigatorStateExtension on _i47.NavigationService { } Future replaceWithLearnLessonView({ - _i39.Key? key, - required _i41.LearnModule module, + _i40.Key? key, + required _i42.LearnModule module, int? routerId, bool preventDuplicates = true, Map? parameters, @@ -2544,7 +2599,7 @@ extension NavigatorStateExtension on _i47.NavigationService { } Future replaceWithForgetPasswordView({ - _i39.Key? key, + _i40.Key? key, int? routerId, bool preventDuplicates = true, Map? parameters, @@ -2560,9 +2615,9 @@ extension NavigatorStateExtension on _i47.NavigationService { } Future replaceWithLearnLessonDetailView({ - _i39.Key? key, - required _i42.LearnLesson lesson, - required _i41.LearnModule module, + _i40.Key? key, + required _i43.LearnLesson lesson, + required _i42.LearnModule module, required bool hasPractice, int? routerId, bool preventDuplicates = true, @@ -2580,12 +2635,12 @@ extension NavigatorStateExtension on _i47.NavigationService { } Future replaceWithLearnPracticeView({ - _i39.Key? key, + _i40.Key? key, String? level, required int id, required String label, required String title, - required _i43.LearnPractices practice, + required _i44.LearnPractices practice, required String subtitle, int? routerId, bool preventDuplicates = true, @@ -2609,7 +2664,7 @@ extension NavigatorStateExtension on _i47.NavigationService { } Future replaceWithCoursePracticeView({ - _i39.Key? key, + _i40.Key? key, required int id, int? routerId, bool preventDuplicates = true, @@ -2626,8 +2681,8 @@ extension NavigatorStateExtension on _i47.NavigationService { } Future replaceWithCoursePaymentView({ - _i39.Key? key, - required _i44.Course course, + _i40.Key? key, + required _i45.Course course, int? routerId, bool preventDuplicates = true, Map? parameters, @@ -2643,7 +2698,7 @@ extension NavigatorStateExtension on _i47.NavigationService { } Future replaceWithFailureView({ - _i39.Key? key, + _i40.Key? key, required void Function() onTap, required String label, int? routerId, @@ -2661,8 +2716,8 @@ extension NavigatorStateExtension on _i47.NavigationService { } Future replaceWithCourseLessonView({ - _i39.Key? key, - required _i44.Course course, + _i40.Key? key, + required _i45.Course course, int? routerId, bool preventDuplicates = true, Map? parameters, @@ -2678,8 +2733,8 @@ extension NavigatorStateExtension on _i47.NavigationService { } Future replaceWithCourseLessonDetailView({ - _i39.Key? key, - required _i45.CourseLesson lesson, + _i40.Key? key, + required _i46.CourseLesson lesson, int? routerId, bool preventDuplicates = true, Map? parameters, @@ -2695,7 +2750,7 @@ extension NavigatorStateExtension on _i47.NavigationService { } Future replaceWithDuolingoView({ - _i39.Key? key, + _i40.Key? key, int? routerId, bool preventDuplicates = true, Map? parameters, @@ -2711,7 +2766,7 @@ extension NavigatorStateExtension on _i47.NavigationService { } Future replaceWithCourseView({ - _i39.Key? key, + _i40.Key? key, int? routerId, bool preventDuplicates = true, Map? parameters, @@ -2727,7 +2782,7 @@ extension NavigatorStateExtension on _i47.NavigationService { } Future replaceWithCoursePracticeQuestionView({ - _i39.Key? key, + _i40.Key? key, required int id, int? routerId, bool preventDuplicates = true, @@ -2744,7 +2799,7 @@ extension NavigatorStateExtension on _i47.NavigationService { } Future replaceWithLearnProgramView({ - _i39.Key? key, + _i40.Key? key, int? routerId, bool preventDuplicates = true, Map? parameters, @@ -2760,7 +2815,7 @@ extension NavigatorStateExtension on _i47.NavigationService { } Future replaceWithLearnCourseView({ - _i39.Key? key, + _i40.Key? key, required int id, int? routerId, bool preventDuplicates = true, @@ -2777,7 +2832,7 @@ extension NavigatorStateExtension on _i47.NavigationService { } Future replaceWithAssessmentView({ - _i39.Key? key, + _i40.Key? key, required Map data, int? routerId, bool preventDuplicates = true, @@ -2794,7 +2849,7 @@ extension NavigatorStateExtension on _i47.NavigationService { } Future replaceWithLearnSubscriptionView({ - _i39.Key? key, + _i40.Key? key, int? routerId, bool preventDuplicates = true, Map? parameters, @@ -2810,7 +2865,7 @@ extension NavigatorStateExtension on _i47.NavigationService { } Future replaceWithArifPayView({ - _i39.Key? key, + _i40.Key? key, required String phone, int? routerId, bool preventDuplicates = true, @@ -2827,7 +2882,7 @@ extension NavigatorStateExtension on _i47.NavigationService { } Future replaceWithCourseCatalogView({ - _i39.Key? key, + _i40.Key? key, int? routerId, bool preventDuplicates = true, Map? parameters, @@ -2843,8 +2898,8 @@ extension NavigatorStateExtension on _i47.NavigationService { } Future replaceWithCourseUnitView({ - _i39.Key? key, - required _i46.CourseCatalog catalog, + _i40.Key? key, + required _i47.CourseCatalog catalog, int? routerId, bool preventDuplicates = true, Map? parameters, @@ -2858,4 +2913,20 @@ extension NavigatorStateExtension on _i47.NavigationService { parameters: parameters, transition: transition); } + + Future replaceWithLandingView({ + _i40.Key? key, + int? routerId, + bool preventDuplicates = true, + Map? parameters, + Widget Function(BuildContext, Animation, Animation, Widget)? + transition, + }) async { + return replaceWith(Routes.landingView, + arguments: LandingViewArguments(key: key), + id: routerId, + preventDuplicates: preventDuplicates, + parameters: parameters, + transition: transition); + } } diff --git a/lib/services/course_service.dart b/lib/services/course_service.dart index 242dd2e..173832d 100644 --- a/lib/services/course_service.dart +++ b/lib/services/course_service.dart @@ -1,4 +1,3 @@ -import 'package:flutter_html/flutter_html.dart'; import 'package:stacked/stacked.dart'; import 'package:yimaru_app/app/app.locator.dart'; import 'package:yimaru_app/models/course_progress.dart'; diff --git a/lib/ui/common/app_strings.dart b/lib/ui/common/app_strings.dart index 0aee3bb..0105fbb 100644 --- a/lib/ui/common/app_strings.dart +++ b/lib/ui/common/app_strings.dart @@ -9,52 +9,299 @@ const String ksCategorySubtitle = const String ksHomeBottomSheetDescription = 'Stacked is built to help you build better apps. Give us a chance and we\'ll prove it to you. Check out stacked.filledstacks.com to learn more'; -const String ksPrivacyPolicy = - 'A brief, simple overview of Yimaru’s commitment to user privacy. Our goal is to be transparent about the data we collect and how we use it to enhance your learning experience.'; - -const String ksTerms = """ +const String ksPrivacyPolicy = """

-Last updated: October 26, 2025 +Last updated: May 12, 2026 +

+ +

Privacy Policy

+ +

+Yimaru Academy App• May 12, 2026

Introduction

-Welcome to Yimaru! These terms and conditions outline the rules and regulations -for the use of our application. By accessing this app, we assume you accept -these terms and conditions. +Welcome to Yimaru Academy (“we,” “our,” “us”). Your privacy is very important to us. This Privacy Policy explains how we collect, use, store, and protect your personal data when you use our mobile application, website, and related services (collectively, the “Platform”).

-

User Accounts

+

Contact Details

-When you create an account with us, you must provide us with information that is -accurate, complete, and current at all times. Failure to do so constitutes a -breach of the Terms, which may result in immediate termination of your account -on our Service. +If you have any questions about this Privacy Policy, please contact us:

-

Content & Services

-Our Service allows you to access learning materials. You are granted a limited -license to access and use the app content for personal, non-commercial purposes. -You agree not to: +Yimaru Academy
+22 Djibouti St, Addis Ababa, Ethiopia
++251 946396655
+Email: yimaruacademy@gmail.com +

+ +

Consent

+

+By using our Platform, you consent to the collection and processing of your personal information as described in this Privacy Policy. Where required by law (e.g., for minors or sensitive data), we will request explicit consent. +

+ +

Information We Collect

+ +

+When you interact with Yimaru Academy, we may collect the following types of information:

    -
  • Reproduce, duplicate, copy, or sell any material from the app.
  • -
  • Redistribute content from Yimaru.
  • -
  • Use the app in any way that is damaging or harmful.
  • +
  • Identity Data: Full name, username, date of birth, and profile information.
  • +
  • Contact Data: Email address, phone number, and billing information.
  • +
  • Account & Learning Data: Lessons accessed, progress, scores, achievements, streaks, and certificates.
  • +
  • Voice & AI Interaction Data: Voice recordings, pronunciation samples, AI chat messages, prompts, and feedback.
  • +
  • Usage Data: App activity, feature usage, and interaction history.
  • +
  • Technical Data: Device type, IP address, OS, app version, language, crash logs, and identifiers.
  • +
  • Payment Data: Subscription and transaction details processed via third-party payment providers.
-

Privacy Policy

-Your privacy is important to us. Please read our -Privacy Policy -to understand how we collect, use, and share information about you. +We do not intentionally collect sensitive personal data such as health, biometric, religious, or political information unless required by law and with proper consent. +

+ +

How We Use Your Data

+ +

+We use your personal data for the following purposes: +

+ +
    +
  • To create and manage your account
  • +
  • To deliver personalized learning experiences and AI features
  • +
  • To communicate updates, alerts, and support messages
  • +
  • To process payments and subscriptions
  • +
  • To improve app performance and services
  • +
  • To detect fraud or misuse
  • +
  • To comply with legal obligations
  • +
+ +

Third-Party Links

+

+Our Platform may contain links to third-party websites or services. We are not responsible for their privacy practices and encourage you to review their policies. +

+ +

Cookies

+

+We may use cookies or similar technologies to improve user experience, analyze usage, and enhance functionality. You can disable cookies in your browser, but some features may not work properly. +

+ +

User Profiles

+

+Users may create learning profiles. You can update or delete your profile information at any time. For minors, parents or guardians may request account deletion. +

+ +

Data Security

+

+We use appropriate technical and organizational measures such as encryption, secure servers, and access controls to protect your data. +

+ +

+In the event of a data breach that affects user rights or freedoms, we will notify affected users and relevant authorities where required by law. +

+ +

Data Retention

+

+We retain personal data only as long as necessary to fulfill the purposes described in this Privacy Policy or as required by Ethiopian law. After that, data is securely deleted or anonymized. +

+ +

Your Rights

+ +

+Under applicable law, you may have the right to: +

+ +
    +
  • Access your personal data
  • +
  • Correct inaccurate information
  • +
  • Request deletion of your data
  • +
  • Restrict or object to processing
  • +
  • Request data portability
  • +
  • Withdraw consent (via parent/guardian if under 16)
  • +
+ +

+To exercise these rights, contact us using the details above. You may also contact the relevant authority if you believe your rights are violated. +

+ +

Cross-Border Data Transfers

+

+Your data is primarily stored within Ethiopia. If data is transferred outside Ethiopia, it will only occur when adequate protection is ensured, with your consent, or for legal/contractual reasons. +

+ +

Changes to This Privacy Policy

+

+We may update this Privacy Policy from time to time. Significant changes will be communicated through the app, website, or email. We encourage you to review this page regularly. +

+ +

Disclaimer

+

+We take reasonable steps to protect your data and process it lawfully. However, no system is completely secure, and you acknowledge these inherent risks when using our Platform. +

+"""; + +const String ksTerms = """ +

+Last updated: May 12, 2026 +

+ +

Terms of Service

+

+Yimaru Academy App +

+ +

Introduction

+

+Welcome to Yimaru Academy (“we,” “our,” “us”), a service operated by :contentReference[oaicite:0]{index=0}. These Terms & Conditions (“Terms”) govern your use of our website, mobile application, and online learning services (collectively, the “Platform”). +

+ +

+By accessing or using our Platform, you agree to comply with and be bound by these Terms. If you do not agree, please do not use our services. +

+ +

Definitions

+

+“Platform” refers to the Yimaru Academy mobile app, website, and related services.
+“Content” refers to all lessons, videos, quizzes, exams, AI feedback, and learning materials.
+“Subscription” refers to paid access plans for premium content and services. +

+ +

Eligibility

+

+Our services are intended for users who are at least 8 years old. +

+ +

+Users under the age of 16 may require parental or guardian consent under applicable law. +

+ +

+By using the Platform, you confirm that you meet these eligibility requirements. +

+ +

Acceptance of Terms

+

+By creating an account, subscribing, or accessing our content, you accept these Terms and our Privacy Policy. +

+ +

+We may update these Terms from time to time. Continued use of the Platform means you accept the updated version. +

+ +

Subscription & Fees

+

+Certain features, courses, and English proficiency exam preparation materials require a paid subscription. +

+ +

+Subscription pricing, billing periods, and available plans are displayed on the Platform and may be updated from time to time. +

+ +

+By purchasing a subscription, you authorize us to charge the applicable fees through your selected payment method. +

+ +

No Refund Policy

+

+We do not offer refunds once a subscription has been purchased. Please review available content carefully before subscribing. +

+ +

Use of Service

+

+You agree to use the Platform only for lawful, personal, and educational purposes. +

+ +

You must not:

+
    +
  • Share your account credentials with others.
  • +
  • Copy, reproduce, or distribute our content without written permission.
  • +
  • Use the Platform for harmful, abusive, or fraudulent activities.
  • +
  • Attempt to access or modify the system in any unauthorized way.
  • +
+ +

Intellectual Property

+

+All content, including lessons, videos, exams, quizzes, AI-generated feedback, and learning materials, is the intellectual property of Yimaru Academy. +

+ +

+You are granted a limited, non-exclusive, non-transferable license to use the content for personal learning only. +

+ +

+Unauthorized use, resale, or redistribution of our materials is strictly prohibited. +

+ +

AI-Generated Content Disclaimer

+

+Some features of the Platform may provide AI-generated feedback, recommendations, or learning assistance. +

+ +

+While we strive for accuracy, AI-generated content may contain errors and should not be considered professional or guaranteed academic advice. +

+ +

Privacy

+

+Your use of the Platform is also governed by our Privacy Policy, which explains how we collect, use, and protect your information. +

+ +

Account Security

+

+You are responsible for maintaining the confidentiality of your account credentials. +

+ +

+If you suspect unauthorized access, contact us immediately at yimaruacademy@gmail.com. +

+ +

+We are not responsible for losses caused by failure to secure your account. +

+ +

Termination

+

+We reserve the right to suspend or terminate your account if you violate these Terms, misuse the Platform, or engage in harmful or fraudulent behavior. +

+ +

+After termination, access to the Platform and content may be removed. +

+ +

Limitation of Liability

+

+We aim to provide high-quality learning content but do not guarantee uninterrupted access, error-free performance, or specific learning outcomes (including exam results or fluency improvement). +

+ +

+To the fullest extent permitted by law, Yimaru Academy is not liable for any indirect or consequential damages resulting from your use of the Platform. +

+ +

Governing Law & Jurisdiction

+

+These Terms are governed by the laws of the Federal Democratic Republic of Ethiopia. Any disputes shall be handled under Ethiopian jurisdiction. +

+ +

Changes to Terms

+

+We may update these Terms from time to time. Users will be notified of major changes through the Platform or email. +

+ +

+Continued use of the Platform means acceptance of the updated Terms.

Contact Us

-If you have any questions about these Terms, please contact us at -support@yimaru.et. +If you have any questions about these Terms & Conditions, contact us: +

+ +

+Yimaru Academy
+22 Djibouti St, Addis Ababa, Ethiopia
++251 946396655
+yimaruacademy@gmail.com

"""; diff --git a/lib/ui/common/translations/codegen_loader.g.dart b/lib/ui/common/translations/codegen_loader.g.dart index b555b87..0afd60c 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,169 +14,203 @@ class CodegenLoader extends AssetLoader{ return Future.value(mapLocales[locale.toString()]); } - static const Map _am = { - "welcome_back": "እንኳን በደህና ተመለሱ", - "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": "የይለፍ ቃል ያረጋግጡ", - "sign_up_agreement": "‘ይመዝገቡ’ የሚለውን ሲጫኑ በ‘አገልግሎት ውሎች’ እና ‘በግላዊነት ፖሊሲ’ ይስማማሉ።", - "reset_password": " የይለፍ ቃልን ይቀይሩ ", - "enter_email_reset_code": "ኢሜይልዎን ያስገቡ። የይለፍ ቃል መለወጫ ኮድ እንልክልዎታለን።", - "please_wait": "እባክዎ ይጠብቁ", - "reset_code_sent": "የመቀየሪያ ኮድ በተሳካ ሁኔታ ተልኳል", - "reset_code": " የመቀየሪያ ኮድ ", - "new_password": "አዲስ የይለፍ ቃል", - "logged_in_successfully": "በተሳካ ሁኔታ ገብተዋል", - "view_course": " ኮርሱን ይመልከቱ ", - "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": "ክልል", - "occupation": "የስራ መስክ ", - "save_changes": "ለውጦችን ያስቀምጡ" -}; -static const Map _en = { - "welcome_back": "Welcome back", - "dont_have_account": "Don't have an account? Register", - "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", - "sign_up_agreement": "By clicking ‘Sign Up’, you agree to our ‘Terms of Service’ and ‘Privacy Policy’", - "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", - "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", - "occupation": "Occupation", - "save_changes": "Save changes" -}; -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": " ኮርሱን ይመልከቱ ", + "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": "ክልል", + "occupation": "የስራ መስክ ", + "save_changes": "ለውጦችን ያስቀምጡ" + }; + static const Map _en = { + "loading": "Loading", + "welcome_back": "Welcome back", + "checking_user_info": "Checking user info", + "dont_have_account": "Don't have an account? Register", + "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_math": "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", + "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", + "occupation": "Occupation", + "save_changes": "Save changes" + }; + 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 be77d58..870487b 100644 --- a/lib/ui/common/translations/locale_keys.g.dart +++ b/lib/ui/common/translations/locale_keys.g.dart @@ -2,8 +2,10 @@ // 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'; static const dont_have_account = 'dont_have_account'; static const email = 'email'; static const password = 'password'; @@ -22,7 +24,18 @@ abstract class LocaleKeys { static const login_with_email = 'login_with_email'; static const create_password = 'create_password'; static const confirm_password = 'confirm_password'; + static const eight_character_minimum = 'eight_character_minimum'; + static const password_match = 'password_match'; static const sign_up_agreement = 'sign_up_agreement'; + static const terms_of_services = 'terms_of_services'; + static const and = 'and'; + static const privacy_policy = 'privacy_policy'; + static const register_with_email = 'register_with_email'; + static const verification_code = 'verification_code'; + static const resend_code = 'resend_code'; + static const code_sent_to_phone = 'code_sent_to_phone'; + static const code_sent_to_email = 'code_sent_to_email'; + static const resend_code_in = 'resend_code_in'; static const reset_password = 'reset_password'; static const enter_email_reset_code = 'enter_email_reset_code'; static const please_wait = 'please_wait'; @@ -81,5 +94,4 @@ abstract class LocaleKeys { static const region = 'region'; static const occupation = 'occupation'; static const save_changes = 'save_changes'; - } diff --git a/lib/ui/common/ui_helpers.dart b/lib/ui/common/ui_helpers.dart index ff851cd..fbfa7ad 100644 --- a/lib/ui/common/ui_helpers.dart +++ b/lib/ui/common/ui_helpers.dart @@ -100,6 +100,12 @@ double getResponsiveFontSize( return responsiveSize; } +BoxDecoration bgDecoration = const BoxDecoration( + image: DecorationImage( + image: AssetImage('assets/images/pattern.png'), + ), +); + InputDecoration inputDecoration( {String? hint, Widget? suffix, @@ -191,6 +197,13 @@ TextStyle style18W600 = const TextStyle( fontWeight: FontWeight.w600, ); +TextStyle style25W400 = const TextStyle( + fontSize: 25, + color: kcWhite, + fontWeight: FontWeight.w400 +); + + TextStyle style25W600 = const TextStyle( fontSize: 25, color: kcWhite, @@ -238,6 +251,12 @@ TextStyle style25P600 = const TextStyle( fontWeight: FontWeight.w600, ); +TextStyle style25P400 = const TextStyle( + fontSize: 25, + color: kcPrimaryColor, + fontWeight: FontWeight.w400, +); + TextStyle style40P900 = const TextStyle( fontSize: 40, color: kcPrimaryColor, diff --git a/lib/ui/views/arif_pay/arif_pay_view.dart b/lib/ui/views/arif_pay/arif_pay_view.dart index 565f5d6..5cbbe4c 100644 --- a/lib/ui/views/arif_pay/arif_pay_view.dart +++ b/lib/ui/views/arif_pay/arif_pay_view.dart @@ -1,13 +1,11 @@ import 'package:flutter/material.dart'; import 'package:flutter_inappwebview/flutter_inappwebview.dart'; import 'package:stacked/stacked.dart'; -import 'package:yimaru_app/models/learn_subscription.dart'; import 'package:yimaru_app/ui/common/app_constants.dart'; import 'package:yimaru_app/ui/common/enmus.dart'; import 'package:yimaru_app/ui/common/ui_helpers.dart'; import 'package:yimaru_app/ui/widgets/page_loading_indicator.dart'; -import '../../../models/learn_subscription_request.dart'; import 'arif_pay_viewmodel.dart'; class ArifPayView extends StackedView { diff --git a/lib/ui/views/assessment/assessment_viewmodel.dart b/lib/ui/views/assessment/assessment_viewmodel.dart index 46ccf56..dd5bcf2 100644 --- a/lib/ui/views/assessment/assessment_viewmodel.dart +++ b/lib/ui/views/assessment/assessment_viewmodel.dart @@ -26,7 +26,8 @@ class AssessmentViewModel extends ReactiveViewModel { List get listenableServices => [_localizationService]; // Languages - Map get _selectedLanguage => _localizationService.selectedLanguage; + Map get _selectedLanguage => + _localizationService.selectedLanguage; Map get selectedLanguage => _selectedLanguage; diff --git a/lib/ui/views/assessment/screens/assessment_intro_screen.dart b/lib/ui/views/assessment/screens/assessment_intro_screen.dart index 5a0f906..5602549 100644 --- a/lib/ui/views/assessment/screens/assessment_intro_screen.dart +++ b/lib/ui/views/assessment/screens/assessment_intro_screen.dart @@ -67,8 +67,8 @@ class AssessmentIntroScreen extends ViewModelWidget { showBackButton: true, onPop: viewModel.goBack, showLanguageSelection: true, - language: viewModel.selectedLanguage['code'], - onLanguage: () async => await viewModel.navigateToLanguage(), + language: viewModel.selectedLanguage['code'], + onLanguage: () async => await viewModel.navigateToLanguage(), ); Widget _buildTitle() => Text( diff --git a/lib/ui/views/assessment/screens/assessment_result_screen.dart b/lib/ui/views/assessment/screens/assessment_result_screen.dart index 14e277d..0a93b88 100644 --- a/lib/ui/views/assessment/screens/assessment_result_screen.dart +++ b/lib/ui/views/assessment/screens/assessment_result_screen.dart @@ -35,9 +35,8 @@ class AssessmentResultScreen extends ViewModelWidget { showBackButton: true, onPop: viewModel.goBack, showLanguageSelection: true, - language: viewModel.selectedLanguage['code'], - - onLanguage: () async => await viewModel.navigateToLanguage(), + language: viewModel.selectedLanguage['code'], + onLanguage: () async => await viewModel.navigateToLanguage(), ); Widget _buildExpandedBody(AssessmentViewModel viewModel) => diff --git a/lib/ui/views/course/course_view.dart b/lib/ui/views/course/course_view.dart index a955610..1aaad41 100644 --- a/lib/ui/views/course/course_view.dart +++ b/lib/ui/views/course/course_view.dart @@ -1,16 +1,10 @@ import 'package:flutter/material.dart'; import 'package:stacked/stacked.dart'; -import '../../../models/course_detail.dart'; -import '../../../models/course_catalog.dart'; import '../../common/app_colors.dart'; -import '../../common/enmus.dart'; import '../../common/ui_helpers.dart'; import '../../widgets/course_category_card.dart'; -import '../../widgets/course_tile.dart'; -import '../../widgets/custom_circular_progress_indicator.dart'; import '../../widgets/profile_app_bar.dart'; -import '../../widgets/small_app_bar.dart'; import 'course_viewmodel.dart'; class CourseView extends StackedView { diff --git a/lib/ui/views/course/course_viewmodel.dart b/lib/ui/views/course/course_viewmodel.dart index 4ee3806..5b15267 100644 --- a/lib/ui/views/course/course_viewmodel.dart +++ b/lib/ui/views/course/course_viewmodel.dart @@ -3,13 +3,8 @@ import 'package:stacked_services/stacked_services.dart'; import '../../../app/app.locator.dart'; import '../../../app/app.router.dart'; -import '../../../models/course.dart'; -import '../../../models/course_detail.dart'; import '../../../models/user.dart'; import '../../../services/authentication_service.dart'; -import '../../../services/course_service.dart'; -import '../../../services/status_checker_service.dart'; -import '../../common/enmus.dart'; class CourseViewModel extends ReactiveViewModel { // Dependency injection diff --git a/lib/ui/views/course_catalog/course_catalog_viewmodel.dart b/lib/ui/views/course_catalog/course_catalog_viewmodel.dart index ea61e14..a448903 100644 --- a/lib/ui/views/course_catalog/course_catalog_viewmodel.dart +++ b/lib/ui/views/course_catalog/course_catalog_viewmodel.dart @@ -4,7 +4,6 @@ import 'package:yimaru_app/models/course_catalog.dart'; import '../../../app/app.locator.dart'; import '../../../app/app.router.dart'; -import '../../../services/api_service.dart'; import '../../../services/course_service.dart'; import '../../../services/status_checker_service.dart'; import '../../common/enmus.dart'; diff --git a/lib/ui/views/course_practice_question/course_practice_question_viewmodel.dart b/lib/ui/views/course_practice_question/course_practice_question_viewmodel.dart index d3eb88e..2b243de 100644 --- a/lib/ui/views/course_practice_question/course_practice_question_viewmodel.dart +++ b/lib/ui/views/course_practice_question/course_practice_question_viewmodel.dart @@ -3,7 +3,6 @@ import 'package:stacked/stacked.dart'; import 'package:stacked_services/stacked_services.dart'; import '../../../app/app.locator.dart'; -import '../../../app/app.router.dart'; import '../../../models/option.dart'; import '../../../models/assessment_question.dart'; import '../../../services/api_service.dart'; @@ -154,8 +153,6 @@ class CoursePracticeQuestionViewModel extends FormViewModel { // Navigation void pop() => _navigationService.back(); - - // Remote api call // Question navigation diff --git a/lib/ui/views/course_practice_question/screens/question_loading_screen.dart b/lib/ui/views/course_practice_question/screens/question_loading_screen.dart index dee4931..49264cf 100644 --- a/lib/ui/views/course_practice_question/screens/question_loading_screen.dart +++ b/lib/ui/views/course_practice_question/screens/question_loading_screen.dart @@ -44,8 +44,7 @@ class QuestionLoadingScreen extends StatelessWidget { onPop: onPop, showBackButton: true, showLanguageSelection: false, - - ); + ); Widget _buildBody() => Expanded(child: Container()); diff --git a/lib/ui/views/course_unit/course_unit_viewmodel.dart b/lib/ui/views/course_unit/course_unit_viewmodel.dart index 3495727..4fabcfb 100644 --- a/lib/ui/views/course_unit/course_unit_viewmodel.dart +++ b/lib/ui/views/course_unit/course_unit_viewmodel.dart @@ -1,10 +1,8 @@ import 'package:stacked/stacked.dart'; import 'package:stacked_services/stacked_services.dart'; -import 'package:yimaru_app/models/course_module.dart'; import '../../../app/app.locator.dart'; import '../../../models/course_unit.dart'; -import '../../../services/api_service.dart'; import '../../../services/course_service.dart'; import '../../../services/status_checker_service.dart'; import '../../common/enmus.dart'; diff --git a/lib/ui/views/forget_password/forget_password_viewmodel.dart b/lib/ui/views/forget_password/forget_password_viewmodel.dart index 0dd11cf..bde1093 100644 --- a/lib/ui/views/forget_password/forget_password_viewmodel.dart +++ b/lib/ui/views/forget_password/forget_password_viewmodel.dart @@ -24,7 +24,8 @@ class ForgetPasswordViewModel extends ReactiveViewModel List get listenableServices => [_localizationService]; // Languages - Map get _selectedLanguage => _localizationService.selectedLanguage; + Map get _selectedLanguage => + _localizationService.selectedLanguage; Map get selectedLanguage => _selectedLanguage; @@ -181,7 +182,6 @@ class ForgetPasswordViewModel extends ReactiveViewModel Future navigateToLanguage() async => await _navigationService.navigateToLanguageView(); - Future replaceWithLogin() async => await _navigationService.clearStackAndShow(Routes.loginView); diff --git a/lib/ui/views/forget_password/screens/request_reset_code_screen.dart b/lib/ui/views/forget_password/screens/request_reset_code_screen.dart index 5f4f00b..e0de93b 100644 --- a/lib/ui/views/forget_password/screens/request_reset_code_screen.dart +++ b/lib/ui/views/forget_password/screens/request_reset_code_screen.dart @@ -53,7 +53,15 @@ class RequestCodeScreen extends ViewModelWidget { required ForgetPasswordViewModel viewModel}) => Scaffold( backgroundColor: kcBackgroundColor, - body: _buildScaffoldStack(context: context, viewModel: viewModel), + body: _buildScaffoldContainer(context: context, viewModel: viewModel), + ); + + Widget _buildScaffoldContainer( + {required BuildContext context, + required ForgetPasswordViewModel viewModel}) => + Container( + decoration: bgDecoration, + child: _buildScaffoldStack(context: context, viewModel: viewModel), ); Widget _buildScaffoldStack( @@ -88,11 +96,9 @@ class RequestCodeScreen extends ViewModelWidget { showBackButton: true, showLanguageSelection: true, onPop: () => _inAppPop(viewModel), - language: viewModel.selectedLanguage['code'], - - onLanguage: ()async => await viewModel.navigateToLanguage(), - - ); + language: viewModel.selectedLanguage['code'], + onLanguage: () async => await viewModel.navigateToLanguage(), + ); Widget _buildExpandedBody( {required BuildContext context, diff --git a/lib/ui/views/forget_password/screens/reset_password_screen.dart b/lib/ui/views/forget_password/screens/reset_password_screen.dart index 4868df6..8d5807e 100644 --- a/lib/ui/views/forget_password/screens/reset_password_screen.dart +++ b/lib/ui/views/forget_password/screens/reset_password_screen.dart @@ -1,8 +1,10 @@ +import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:stacked/stacked.dart'; import '../../../common/app_colors.dart'; import '../../../common/enmus.dart'; +import '../../../common/translations/locale_keys.g.dart'; import '../../../common/ui_helpers.dart'; import '../../../widgets/custom_elevated_button.dart'; import '../../../widgets/custom_form_label.dart'; @@ -58,7 +60,15 @@ class ResetPasswordScreen extends ViewModelWidget { required ForgetPasswordViewModel viewModel}) => Scaffold( backgroundColor: kcBackgroundColor, - body: _buildScaffoldStack(context: context, viewModel: viewModel), + body: _buildScaffoldContainer(context: context, viewModel: viewModel), + ); + + Widget _buildScaffoldContainer( + {required BuildContext context, + required ForgetPasswordViewModel viewModel}) => + Container( + decoration: bgDecoration, + child: _buildScaffoldStack(context: context, viewModel: viewModel), ); Widget _buildScaffoldStack( @@ -86,11 +96,9 @@ class ResetPasswordScreen extends ViewModelWidget { showBackButton: true, showLanguageSelection: true, onPop: () => _inAppPop(viewModel), - language: viewModel.selectedLanguage['code'], - - onLanguage: ()async => await viewModel.navigateToLanguage(), - - ); + language: viewModel.selectedLanguage['code'], + onLanguage: () async => await viewModel.navigateToLanguage(), + ); Widget _buildExpandedBody(ForgetPasswordViewModel viewModel) => Expanded(child: _buildColumnScroller(viewModel)); @@ -115,7 +123,7 @@ class ResetPasswordScreen extends ViewModelWidget { verticalSpaceMedium, _buildTitle(), verticalSpaceMedium, - _buildFormLabel('Reset code'), + _buildFormLabel(LocaleKeys.reset_code.tr()), verticalSpaceSmall, _buildResetCodeFormField(viewModel), if (viewModel.hasResetCodeValidationMessage && viewModel.focusResetCode) @@ -123,7 +131,7 @@ class ResetPasswordScreen extends ViewModelWidget { if (viewModel.hasResetCodeValidationMessage && viewModel.focusResetCode) _buildResetCodeValidationWrapper(viewModel), verticalSpaceMedium, - _buildFormLabel('New Password'), + _buildFormLabel(LocaleKeys.new_password.tr()), verticalSpaceSmall, _buildPasswordFormField(viewModel), if (viewModel.hasPasswordValidationMessage && viewModel.focusPassword) @@ -131,7 +139,7 @@ class ResetPasswordScreen extends ViewModelWidget { if (viewModel.hasPasswordValidationMessage && viewModel.focusPassword) _buildPasswordValidationWrapper(viewModel), verticalSpaceMedium, - _buildFormLabel('Confirm Password'), + _buildFormLabel(LocaleKeys.confirm_password.tr()), verticalSpaceSmall, _buildConfirmPasswordFormField(viewModel), if (viewModel.hasConfirmPasswordValidationMessage && @@ -151,7 +159,7 @@ class ResetPasswordScreen extends ViewModelWidget { ]; Widget _buildTitle() => Text( - 'Reset password', + LocaleKeys.reset_password.tr(), style: style25DG600, ); @@ -165,7 +173,7 @@ class ResetPasswordScreen extends ViewModelWidget { controller: resetCodeController, onTap: viewModel.setResetCodeFocus, decoration: inputDecoration( - hint: 'Reset code', + hint: LocaleKeys.reset_code.tr(), focus: viewModel.focusResetCode, filled: passwordController.text.isNotEmpty), ); @@ -186,7 +194,7 @@ class ResetPasswordScreen extends ViewModelWidget { onTap: viewModel.setPasswordFocus, obscureText: viewModel.obscurePassword, decoration: inputDecoration( - hint: 'Password', + hint: LocaleKeys.password.tr(), focus: viewModel.focusPassword, suffix: _buildObscurePassword(viewModel), filled: passwordController.text.isNotEmpty), @@ -221,7 +229,7 @@ class ResetPasswordScreen extends ViewModelWidget { password: passwordController.text, confirmPassword: confirmPasswordController.text), decoration: inputDecoration( - hint: 'Confirm Password', + hint: LocaleKeys.confirm_password.tr(), focus: viewModel.focusConfirmPassword, suffix: _buildObscureConfirmPassword(viewModel), filled: confirmPasswordController.text.isNotEmpty), @@ -255,21 +263,22 @@ class ResetPasswordScreen extends ViewModelWidget { Widget _buildCharLengthValidator(ForgetPasswordViewModel viewModel) => ValidatorListTile( - backgroundColor: viewModel.length ? kcPrimaryColor : kcLightGrey, - label: '8 characters minimum'); + label: LocaleKeys.eight_character_minimum.tr(), + backgroundColor: viewModel.length ? kcPrimaryColor : kcLightGrey, + ); Widget _buildPasswordMatchValidator(ForgetPasswordViewModel viewModel) => ValidatorListTile( - backgroundColor: - viewModel.passwordMatch ? kcPrimaryColor : kcLightGrey, - label: 'password match'); + label: LocaleKeys.password_match.tr(), + backgroundColor: viewModel.passwordMatch ? kcPrimaryColor : kcLightGrey, + ); Widget _buildSignUpButton(ForgetPasswordViewModel viewModel) => CustomElevatedButton( height: 55, - text: 'Continue', borderRadius: 12, foregroundColor: kcWhite, + text: LocaleKeys.cont.tr(), onTap: passwordController.text.isNotEmpty && confirmPasswordController.text.isNotEmpty && resetCodeController.text.isNotEmpty && diff --git a/lib/ui/views/home/home_view.dart b/lib/ui/views/home/home_view.dart index 6848e8e..afc87cc 100644 --- a/lib/ui/views/home/home_view.dart +++ b/lib/ui/views/home/home_view.dart @@ -3,7 +3,6 @@ import 'package:stacked/stacked.dart'; import 'package:yimaru_app/ui/common/app_colors.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/coming_soon.dart'; import '../course/course_view.dart'; import 'home_viewmodel.dart'; diff --git a/lib/ui/views/landing/landing_view.dart b/lib/ui/views/landing/landing_view.dart new file mode 100644 index 0000000..25554ef --- /dev/null +++ b/lib/ui/views/landing/landing_view.dart @@ -0,0 +1,52 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_carousel_widget/flutter_carousel_widget.dart'; +import 'package:stacked/stacked.dart'; +import 'package:yimaru_app/ui/views/landing/screens/first_landing_screen.dart'; +import 'package:yimaru_app/ui/views/landing/screens/second_landing_screen.dart'; +import 'package:yimaru_app/ui/views/landing/screens/third_landing_screen.dart'; + +import 'landing_viewmodel.dart'; + +class LandingView extends StackedView { + const LandingView({Key? key}) : super(key: key); + + + @override + LandingViewModel viewModelBuilder( + BuildContext context, + ) => + LandingViewModel(); + + @override + Widget builder( + BuildContext context, + LandingViewModel viewModel, + Widget? child, + )=> _buildLandingScreens(viewModel); + + Widget _buildLandingScreens(LandingViewModel viewModel) => FlutterCarousel( + options: FlutterCarouselOptions( + autoPlay: true, + viewportFraction: 1, + showIndicator: true, + indicatorMargin: 40, + height: double.maxFinite, + slideIndicator: CircularSlideIndicator( + slideIndicatorOptions: + const SlideIndicatorOptions(indicatorRadius: 2.5), + ), + ), + items: _buildScreens(), + ); + + List _buildScreens() => + [_buildFirstWelcome(), _buildSecondWelcome(), _buildThirdWelcome()]; + + Widget _buildFirstWelcome() => const FirstLandingScreen(); + + Widget _buildSecondWelcome() => const SecondLandingScreen(); + + Widget _buildThirdWelcome() => const ThirdLandingScreen(); + + +} diff --git a/lib/ui/views/landing/landing_viewmodel.dart b/lib/ui/views/landing/landing_viewmodel.dart new file mode 100644 index 0000000..9e755f4 --- /dev/null +++ b/lib/ui/views/landing/landing_viewmodel.dart @@ -0,0 +1,29 @@ +import 'package:stacked/stacked.dart'; +import 'package:stacked_services/stacked_services.dart'; + +import '../../../app/app.locator.dart'; +import '../../../app/app.router.dart'; +import '../../../services/authentication_service.dart'; + +class LandingViewModel extends BaseViewModel { + // Dependency Injection + final _navigationService = locator(); + + final _authenticationService = locator(); + + // Navigation + Future navigateToLogin() async => + await _navigationService.replaceWithLoginView(); + + // Remote api call + + // First time install + Future setFirstTimeInstall() async { + await runBusyFuture(_setFirstTimeInstall()); + } + + Future _setFirstTimeInstall() async { + await _authenticationService.setFirstTimeInstall(false); + await navigateToLogin(); + } +} diff --git a/lib/ui/views/landing/screens/first_landing_screen.dart b/lib/ui/views/landing/screens/first_landing_screen.dart new file mode 100644 index 0000000..8e0ab9b --- /dev/null +++ b/lib/ui/views/landing/screens/first_landing_screen.dart @@ -0,0 +1,145 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_svg/svg.dart'; +import 'package:stacked/stacked.dart'; +import 'package:yimaru_app/ui/common/app_colors.dart'; +import 'package:yimaru_app/ui/common/ui_helpers.dart'; +import 'package:yimaru_app/ui/widgets/custom_elevated_button.dart'; + +import '../../../widgets/custom_circular_progress_indicator.dart'; +import '../landing_viewmodel.dart'; + +class FirstLandingScreen extends ViewModelWidget { + const FirstLandingScreen({super.key}); + + @override + Widget build(BuildContext context, LandingViewModel viewModel) => + _buildScaffoldWrapper(viewModel); + + Widget _buildScaffoldWrapper(LandingViewModel viewModel) => Scaffold( + backgroundColor: kcPrimaryColor, + body: _buildScaffoldPadding(viewModel), + ); + Widget _buildScaffoldPadding(LandingViewModel viewModel)=> Padding( + padding: const EdgeInsets.symmetric(horizontal: 15), + child: _buildScaffold(viewModel),); + + Widget _buildScaffold(LandingViewModel viewModel) => Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.stretch, + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: _buildScaffoldChildren(viewModel), + ); + + List _buildScaffoldChildren(LandingViewModel viewModel) => + [ _buildUpperColumn(),_buildLowerColumnWrapper(viewModel)]; + + + + + Widget _buildUpperColumn() => Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.stretch, + children: _buildUpperColumnChildren(), + ); + + List _buildUpperColumnChildren() => [ + verticalSpaceLarge, + _buildIconWrapper(), + verticalSpaceLarge + + ]; + + Widget _buildIconWrapper()=> Align(alignment: Alignment.topLeft,child: _buildIcon(),); + + Widget _buildIcon() => SvgPicture.asset( + 'assets/icons/logo.svg', + height: 25, + ); + + + + Widget _buildLowerColumnWrapper(LandingViewModel viewModel) => Expanded( + child: _buildLowerColumn(viewModel), + ); + + Widget _buildLowerColumn(LandingViewModel viewModel) => Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.stretch, + children: _buildLowerColumnChildren(viewModel), + ); + + List _buildLowerColumnChildren(LandingViewModel viewModel) => [ + _buildTitle(), + verticalSpaceMedium, + _buildImageWrapper(), + verticalSpaceMedium, + _buildSafeWrapper(viewModel) + ]; + + Widget _buildTitle() => + + Text.rich( + TextSpan( + text: 'እንግሊዝኛ\n', + style: style25W600, + children: [ + TextSpan( + text: 'በማንኛውም', + style: style25W400, + ), + TextSpan( + text: ' ሰዓት ', + style: style25W600, + + ), + + TextSpan( + text: 'ይማሩ!', + style: style25W400, + + ), + ], + ), + ); + + Widget _buildImageWrapper()=> Expanded(child: _buildImageClipper()); + + Widget _buildImageClipper()=> ClipRRect( + borderRadius: BorderRadius.circular(25), + child: _buildImage(), + ); + + + + Widget _buildImage()=> Image.asset('assets/images/profile.png',fit: BoxFit.cover,); + + + Widget _buildSafeWrapper(LandingViewModel viewModel) => + SafeArea(child: _buildContinueButtonWrapper(viewModel)); + + Widget _buildContinueButtonWrapper(LandingViewModel viewModel) => Align( + alignment: Alignment.bottomCenter, + child: _buildButtonContainer(viewModel), + ); + + Widget _buildButtonContainer(LandingViewModel viewModel) => Padding( + padding: const EdgeInsets.only(bottom: 50), + child: _buildContinueButtonState(viewModel), + ); + + Widget _buildContinueButtonState(LandingViewModel viewModel) => + viewModel.isBusy ? _buildIndicator() : _buildContinueButton(viewModel); + + Widget _buildIndicator() => + const CustomCircularProgressIndicator(color: kcWhite); + + Widget _buildContinueButton(LandingViewModel viewModel) => + CustomElevatedButton( + height: 55, + borderRadius: 25, + text: 'Get Started', + backgroundColor: kcWhite, + foregroundColor: kcPrimaryColor, + onTap: () async => await viewModel.setFirstTimeInstall(), + ); +} diff --git a/lib/ui/views/landing/screens/second_landing_screen.dart b/lib/ui/views/landing/screens/second_landing_screen.dart new file mode 100644 index 0000000..be5a8e6 --- /dev/null +++ b/lib/ui/views/landing/screens/second_landing_screen.dart @@ -0,0 +1,146 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_svg/svg.dart'; +import 'package:stacked/stacked.dart'; +import 'package:yimaru_app/ui/common/app_colors.dart'; +import 'package:yimaru_app/ui/common/ui_helpers.dart'; +import 'package:yimaru_app/ui/widgets/custom_elevated_button.dart'; + +import '../../../widgets/custom_circular_progress_indicator.dart'; +import '../landing_viewmodel.dart'; + +class SecondLandingScreen extends ViewModelWidget { + const SecondLandingScreen({super.key}); + + @override + Widget build(BuildContext context, LandingViewModel viewModel) => + _buildScaffoldWrapper(viewModel); + + Widget _buildScaffoldWrapper(LandingViewModel viewModel) => Scaffold( + backgroundColor: Colors.amber, + body: _buildScaffoldPadding(viewModel), + ); + Widget _buildScaffoldPadding(LandingViewModel viewModel)=> Padding( + padding: const EdgeInsets.symmetric(horizontal: 15), + child: _buildScaffold(viewModel),); + + Widget _buildScaffold(LandingViewModel viewModel) => Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.stretch, + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: _buildScaffoldChildren(viewModel), + ); + + List _buildScaffoldChildren(LandingViewModel viewModel) => + [ _buildUpperColumn(),_buildLowerColumnWrapper(viewModel)]; + + + + + Widget _buildUpperColumn() => Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.stretch, + children: _buildUpperColumnChildren(), + ); + + List _buildUpperColumnChildren() => [ + verticalSpaceLarge, + _buildIconWrapper(), + verticalSpaceLarge + + ]; + + Widget _buildIconWrapper()=> Align(alignment: Alignment.topLeft,child: _buildIcon(),); + + Widget _buildIcon() => SvgPicture.asset( + 'assets/icons/logo.svg', + color: kcPrimaryColor, + height: 25, + ); + + + + Widget _buildLowerColumnWrapper(LandingViewModel viewModel) => Expanded( + child: _buildLowerColumn(viewModel), + ); + + Widget _buildLowerColumn(LandingViewModel viewModel) => Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.stretch, + children: _buildLowerColumnChildren(viewModel), + ); + + List _buildLowerColumnChildren(LandingViewModel viewModel) => [ + _buildTitle(), + verticalSpaceMedium, + _buildImageWrapper(), + verticalSpaceMedium, + _buildSafeWrapper(viewModel) + ]; + + Widget _buildTitle() => + + Text.rich( + TextSpan( + text: 'እንግሊዝኛ\n', + style: style25P600, + children: [ + TextSpan( + text: 'በማንኛውም', + style: style25P400, + ), + TextSpan( + text: ' እድሜ ', + style: style25P600, + + ), + + TextSpan( + text: 'ይማሩ!', + style: style25P400, + + ), + ], + ), + ); + + Widget _buildImageWrapper()=> Expanded(child: _buildImageClipper()); + + Widget _buildImageClipper()=> ClipRRect( + borderRadius: BorderRadius.circular(25), + child: _buildImage(), + ); + + + + Widget _buildImage()=> Image.asset('assets/images/profile.png',fit: BoxFit.cover,); + + + Widget _buildSafeWrapper(LandingViewModel viewModel) => + SafeArea(child: _buildContinueButtonWrapper(viewModel)); + + Widget _buildContinueButtonWrapper(LandingViewModel viewModel) => Align( + alignment: Alignment.bottomCenter, + child: _buildButtonContainer(viewModel), + ); + + Widget _buildButtonContainer(LandingViewModel viewModel) => Padding( + padding: const EdgeInsets.only(bottom: 50), + child: _buildContinueButtonState(viewModel), + ); + + Widget _buildContinueButtonState(LandingViewModel viewModel) => + viewModel.isBusy ? _buildIndicator() : _buildContinueButton(viewModel); + + Widget _buildIndicator() => + const CustomCircularProgressIndicator(color: kcWhite); + + Widget _buildContinueButton(LandingViewModel viewModel) => + CustomElevatedButton( + height: 55, + borderRadius: 25, + text: 'Get Started', + foregroundColor: kcWhite, + backgroundColor: kcPrimaryColor, + onTap: () async => await viewModel.setFirstTimeInstall(), + ); +} diff --git a/lib/ui/views/landing/screens/third_landing_screen.dart b/lib/ui/views/landing/screens/third_landing_screen.dart new file mode 100644 index 0000000..eeb4717 --- /dev/null +++ b/lib/ui/views/landing/screens/third_landing_screen.dart @@ -0,0 +1,146 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_svg/svg.dart'; +import 'package:stacked/stacked.dart'; +import 'package:yimaru_app/ui/common/app_colors.dart'; +import 'package:yimaru_app/ui/common/ui_helpers.dart'; +import 'package:yimaru_app/ui/widgets/custom_elevated_button.dart'; + +import '../../../widgets/custom_circular_progress_indicator.dart'; +import '../landing_viewmodel.dart'; + +class ThirdLandingScreen extends ViewModelWidget { + const ThirdLandingScreen({super.key}); + + @override + Widget build(BuildContext context, LandingViewModel viewModel) => + _buildScaffoldWrapper(viewModel); + + Widget _buildScaffoldWrapper(LandingViewModel viewModel) => Scaffold( + backgroundColor: kcWhite, + body: _buildScaffoldPadding(viewModel), + ); + Widget _buildScaffoldPadding(LandingViewModel viewModel)=> Padding( + padding: const EdgeInsets.symmetric(horizontal: 15), + child: _buildScaffold(viewModel),); + + Widget _buildScaffold(LandingViewModel viewModel) => Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.stretch, + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: _buildScaffoldChildren(viewModel), + ); + + List _buildScaffoldChildren(LandingViewModel viewModel) => + [ _buildUpperColumn(),_buildLowerColumnWrapper(viewModel)]; + + + + + Widget _buildUpperColumn() => Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.stretch, + children: _buildUpperColumnChildren(), + ); + + List _buildUpperColumnChildren() => [ + verticalSpaceLarge, + _buildIconWrapper(), + verticalSpaceLarge + + ]; + + Widget _buildIconWrapper()=> Align(alignment: Alignment.topLeft,child: _buildIcon(),); + + Widget _buildIcon() => SvgPicture.asset( + 'assets/icons/logo.svg', + color: kcPrimaryColor, + height: 25, + ); + + + + Widget _buildLowerColumnWrapper(LandingViewModel viewModel) => Expanded( + child: _buildLowerColumn(viewModel), + ); + + Widget _buildLowerColumn(LandingViewModel viewModel) => Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.stretch, + children: _buildLowerColumnChildren(viewModel), + ); + + List _buildLowerColumnChildren(LandingViewModel viewModel) => [ + _buildTitle(), + verticalSpaceMedium, + _buildImageWrapper(), + verticalSpaceMedium, + _buildSafeWrapper(viewModel) + ]; + + Widget _buildTitle() => + + Text.rich( + TextSpan( + text: 'እንግሊዝኛ\n', + style: style25P600, + children: [ + TextSpan( + text: 'በማንኛውም', + style: style25P400, + ), + TextSpan( + text: ' እድሜ ', + style: style25P600, + + ), + + TextSpan( + text: 'ይማሩ!', + style: style25P400, + + ), + ], + ), + ); + + Widget _buildImageWrapper()=> Expanded(child: _buildImageClipper()); + + Widget _buildImageClipper()=> ClipRRect( + borderRadius: BorderRadius.circular(25), + child: _buildImage(), + ); + + + + Widget _buildImage()=> Image.asset('assets/images/profile.png',fit: BoxFit.cover,); + + + Widget _buildSafeWrapper(LandingViewModel viewModel) => + SafeArea(child: _buildContinueButtonWrapper(viewModel)); + + Widget _buildContinueButtonWrapper(LandingViewModel viewModel) => Align( + alignment: Alignment.bottomCenter, + child: _buildButtonContainer(viewModel), + ); + + Widget _buildButtonContainer(LandingViewModel viewModel) => Padding( + padding: const EdgeInsets.only(bottom: 50), + child: _buildContinueButtonState(viewModel), + ); + + Widget _buildContinueButtonState(LandingViewModel viewModel) => + viewModel.isBusy ? _buildIndicator() : _buildContinueButton(viewModel); + + Widget _buildIndicator() => + const CustomCircularProgressIndicator(color: kcWhite); + + Widget _buildContinueButton(LandingViewModel viewModel) => + CustomElevatedButton( + height: 55, + borderRadius: 25, + text: 'Get Started', + foregroundColor: kcWhite, + backgroundColor: kcPrimaryColor, + onTap: () async => await viewModel.setFirstTimeInstall(), + ); +} diff --git a/lib/ui/views/language/language_view.dart b/lib/ui/views/language/language_view.dart index 6e2b150..4449508 100644 --- a/lib/ui/views/language/language_view.dart +++ b/lib/ui/views/language/language_view.dart @@ -29,7 +29,15 @@ class LanguageView extends StackedView { required LanguageViewModel viewModel}) => Scaffold( backgroundColor: kcBackgroundColor, - body: _buildScaffold(context: context, viewModel: viewModel), + body: _buildScaffoldContainer(context: context, viewModel: viewModel), + ); + + Widget _buildScaffoldContainer( + {required BuildContext context, + required LanguageViewModel viewModel}) => + Container( + decoration: bgDecoration, + child: _buildScaffold(context: context, viewModel: viewModel), ); Widget _buildScaffold( diff --git a/lib/ui/views/language/language_viewmodel.dart b/lib/ui/views/language/language_viewmodel.dart index dfbad13..8070b22 100644 --- a/lib/ui/views/language/language_viewmodel.dart +++ b/lib/ui/views/language/language_viewmodel.dart @@ -14,14 +14,13 @@ class LanguageViewModel extends ReactiveViewModel { @override List get listenableServices => [_localizationService]; - - // Languages List> get _languages => _localizationService.languages; List> get languages => _languages; - Map get _selectedLanguage => _localizationService.selectedLanguage; + Map get _selectedLanguage => + _localizationService.selectedLanguage; Map get selectedLanguage => _selectedLanguage; // Languages diff --git a/lib/ui/views/learn_course/learn_course_view.dart b/lib/ui/views/learn_course/learn_course_view.dart index 40fa591..ad0e978 100644 --- a/lib/ui/views/learn_course/learn_course_view.dart +++ b/lib/ui/views/learn_course/learn_course_view.dart @@ -34,7 +34,12 @@ class LearnCourseView extends StackedView { Widget _buildScaffoldWrapper(LearnCourseViewModel viewModel) => Scaffold( backgroundColor: kcBackgroundColor, - body: _buildScaffold(viewModel), + body: _buildScaffoldContainer(viewModel), + ); + + Widget _buildScaffoldContainer(LearnCourseViewModel viewModel) => Container( + decoration: bgDecoration, + child: _buildScaffold(viewModel), ); Widget _buildScaffold(LearnCourseViewModel viewModel) => diff --git a/lib/ui/views/learn_course/learn_course_viewmodel.dart b/lib/ui/views/learn_course/learn_course_viewmodel.dart index eda1fe6..0f7b978 100644 --- a/lib/ui/views/learn_course/learn_course_viewmodel.dart +++ b/lib/ui/views/learn_course/learn_course_viewmodel.dart @@ -4,7 +4,6 @@ import 'package:yimaru_app/app/app.router.dart'; import '../../../app/app.locator.dart'; import '../../../models/learn_course.dart'; -import '../../../services/api_service.dart'; import '../../../services/learn_service.dart'; import '../../../services/status_checker_service.dart'; import '../../common/enmus.dart'; diff --git a/lib/ui/views/learn_lesson/learn_lesson_view.dart b/lib/ui/views/learn_lesson/learn_lesson_view.dart index e707403..fb68d7c 100644 --- a/lib/ui/views/learn_lesson/learn_lesson_view.dart +++ b/lib/ui/views/learn_lesson/learn_lesson_view.dart @@ -48,7 +48,15 @@ class LearnLessonView extends StackedView { required LearnLessonViewModel viewModel}) => Scaffold( backgroundColor: kcBackgroundColor, - body: _buildScaffold(context: context, viewModel: viewModel), + body: _buildScaffoldContainer(context: context, viewModel: viewModel), + ); + + Widget _buildScaffoldContainer( + {required BuildContext context, + required LearnLessonViewModel viewModel}) => + Container( + decoration: bgDecoration, + child: _buildScaffold(context: context, viewModel: viewModel), ); Widget _buildScaffold( 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 371ec46..182afc8 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 @@ -60,7 +60,13 @@ class LearnLessonDetailView extends StackedView { Widget _buildScaffoldWrapper(LearnLessonDetailViewModel viewModel) => Scaffold( backgroundColor: kcBackgroundColor, - body: _buildScaffold(viewModel), + body: _buildScaffoldContainer(viewModel), + ); + + Widget _buildScaffoldContainer(LearnLessonDetailViewModel viewModel) => + Container( + decoration: bgDecoration, + child: _buildScaffold(viewModel), ); Widget _buildScaffold(LearnLessonDetailViewModel viewModel) => diff --git a/lib/ui/views/learn_module/learn_module_view.dart b/lib/ui/views/learn_module/learn_module_view.dart index a2d5193..e80592c 100644 --- a/lib/ui/views/learn_module/learn_module_view.dart +++ b/lib/ui/views/learn_module/learn_module_view.dart @@ -37,7 +37,12 @@ class LearnModuleView extends StackedView { Widget _buildScaffoldWrapper(LearnModuleViewModel viewModel) => Scaffold( backgroundColor: kcBackgroundColor, - body: _buildScaffold(viewModel), + body: _buildScaffoldContainer(viewModel), + ); + + Widget _buildScaffoldContainer(LearnModuleViewModel viewModel) => Container( + decoration: bgDecoration, + child: _buildScaffold(viewModel), ); Widget _buildScaffold(LearnModuleViewModel viewModel) => diff --git a/lib/ui/views/learn_module/learn_module_viewmodel.dart b/lib/ui/views/learn_module/learn_module_viewmodel.dart index e408fc5..be18d00 100644 --- a/lib/ui/views/learn_module/learn_module_viewmodel.dart +++ b/lib/ui/views/learn_module/learn_module_viewmodel.dart @@ -4,7 +4,6 @@ import 'package:yimaru_app/app/app.router.dart'; import 'package:yimaru_app/models/learn_module.dart'; import '../../../app/app.locator.dart'; -import '../../../services/api_service.dart'; import '../../../services/learn_service.dart'; import '../../../services/status_checker_service.dart'; import '../../common/enmus.dart'; diff --git a/lib/ui/views/learn_practice/learn_practice_view.dart b/lib/ui/views/learn_practice/learn_practice_view.dart index dafbd0c..826742f 100644 --- a/lib/ui/views/learn_practice/learn_practice_view.dart +++ b/lib/ui/views/learn_practice/learn_practice_view.dart @@ -1,8 +1,9 @@ import 'package:flutter/material.dart'; import 'package:stacked/stacked.dart'; import 'package:yimaru_app/ui/common/enmus.dart'; -import 'package:yimaru_app/ui/views/learn_practice/screens/finish_learn_practice_screen.dart'; +import 'package:yimaru_app/ui/views/learn_practice/screens/learn_practice_finish_screen.dart'; import 'package:yimaru_app/ui/views/learn_practice/screens/learn_loading_screen.dart'; +import 'package:yimaru_app/ui/views/learn_practice/screens/learn_practice_appreciation_screen.dart'; import 'package:yimaru_app/ui/views/learn_practice/screens/learn_practice_completion_screen.dart'; import 'package:yimaru_app/ui/views/learn_practice/screens/learn_practice_description_screen.dart'; import 'package:yimaru_app/ui/views/learn_practice/screens/learn_practice_result_screen.dart'; @@ -115,10 +116,12 @@ class LearnPracticeView extends StackedView { List _buildScreens(LearnPracticeViewModel viewModel) => [ _buildLearnPracticeIntroScreen(), - _buildLearnPracticeElementsScreen(), + if (practice != LearnPractices.lesson) + _buildLearnPracticeElementsScreen(), _buildLearnPracticeQuestionsScreen(), - _buildFinishLearnPracticeScreen(), + _buildLearnPracticeAppreciationScreen(), _buildLearnPracticeResultScreen(), + _buildLearnPracticeFinishScreen(), if (practice == LearnPractices.course) _buildLearnPracticeCompletionScreen() ]; @@ -137,12 +140,14 @@ class LearnPracticeView extends StackedView { Widget _buildLearnPracticeQuestionsScreen() => const LearnPracticeQuestionsScreen(); - Widget _buildFinishLearnPracticeScreen() => const FinishLearnPracticeScreen(); + Widget _buildLearnPracticeAppreciationScreen() => + const LearnPracticeAppreciationScreen(); Widget _buildLearnPracticeResultScreen() => LearnPracticeResultScreen(practice: practice); - Widget _buildLearnPracticeCompletionScreen() => LearnPracticeCompletionScreen( - level: level ?? '', - ); + Widget _buildLearnPracticeFinishScreen() => const LearnPracticeFinishScreen(); + + Widget _buildLearnPracticeCompletionScreen() => + LearnPracticeCompletionScreen(level: level ?? ''); } diff --git a/lib/ui/views/learn_practice/screens/interact_learn_practice_screen.dart b/lib/ui/views/learn_practice/screens/interact_learn_practice_screen.dart index 12fb51d..09d69cb 100644 --- a/lib/ui/views/learn_practice/screens/interact_learn_practice_screen.dart +++ b/lib/ui/views/learn_practice/screens/interact_learn_practice_screen.dart @@ -55,7 +55,15 @@ class InteractLearnPracticeScreen required LearnPracticeViewModel viewModel}) => Scaffold( backgroundColor: kcBackgroundColor, - body: _buildScaffold(context: context, viewModel: viewModel), + body: _buildScaffoldContainer(context: context, viewModel: viewModel), + ); + + Widget _buildScaffoldContainer( + {required BuildContext context, + required LearnPracticeViewModel viewModel}) => + Container( + decoration: bgDecoration, + child: _buildScaffold(context: context, viewModel: viewModel), ); Widget _buildScaffold( diff --git a/lib/ui/views/learn_practice/screens/learn_loading_screen.dart b/lib/ui/views/learn_practice/screens/learn_loading_screen.dart index ffc67b3..c603e2b 100644 --- a/lib/ui/views/learn_practice/screens/learn_loading_screen.dart +++ b/lib/ui/views/learn_practice/screens/learn_loading_screen.dart @@ -24,7 +24,12 @@ class LearnLoadingScreen extends StatelessWidget { Widget _buildScaffoldWrapper() => Scaffold( backgroundColor: kcBackgroundColor, - body: _buildScaffold(), + body: _buildScaffoldContainer(), + ); + + Widget _buildScaffoldContainer() => Container( + decoration: bgDecoration, + child: _buildScaffold(), ); Widget _buildScaffold() => SafeArea(child: _buildStack()); diff --git a/lib/ui/views/learn_practice/screens/learn_practice_appreciation_screen.dart b/lib/ui/views/learn_practice/screens/learn_practice_appreciation_screen.dart new file mode 100644 index 0000000..5e6d79c --- /dev/null +++ b/lib/ui/views/learn_practice/screens/learn_practice_appreciation_screen.dart @@ -0,0 +1,160 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_svg/svg.dart'; +import 'package:stacked/stacked.dart'; +import 'package:yimaru_app/ui/views/learn_practice/learn_practice_viewmodel.dart'; + +import '../../../common/app_colors.dart'; +import '../../../common/ui_helpers.dart'; +import '../../../widgets/cancel_learn_practice_sheet.dart'; +import '../../../widgets/custom_elevated_button.dart'; +import '../../../widgets/small_app_bar.dart'; + +class LearnPracticeAppreciationScreen + extends ViewModelWidget { + const LearnPracticeAppreciationScreen({super.key}); + + Future _reset(LearnPracticeViewModel viewModel) async => + await viewModel.reset(); + + Future _cancel(LearnPracticeViewModel viewModel) async { + await viewModel.stopRecording(); + viewModel.pop(); + viewModel.pop(); + } + + Future _showSheet( + {required BuildContext context, + required LearnPracticeViewModel viewModel}) async => + await showModalBottomSheet( + context: context, + isScrollControlled: true, + backgroundColor: kcTransparent, + builder: (cxt) => _buildSheet(viewModel), + ); + + @override + Widget build(BuildContext context, LearnPracticeViewModel viewModel) => + _buildScaffoldWrapper(context: context, viewModel: viewModel); + + Widget _buildScaffoldWrapper( + {required BuildContext context, + required LearnPracticeViewModel viewModel}) => + Scaffold( + backgroundColor: kcBackgroundColor, + body: _buildScaffoldContainer(context: context, viewModel: viewModel), + ); + + Widget _buildScaffoldContainer( + {required BuildContext context, + required LearnPracticeViewModel viewModel}) => + Container( + decoration: bgDecoration, + child: _buildScaffold(context: context, viewModel: viewModel), + ); + + Widget _buildScaffold( + {required BuildContext context, + required LearnPracticeViewModel viewModel}) => + SafeArea( + child: + _buildBodyColumnWrapper(context: context, viewModel: viewModel)); + + Widget _buildBodyColumnWrapper( + {required BuildContext context, + required LearnPracticeViewModel viewModel}) => + Padding( + padding: const EdgeInsets.symmetric(horizontal: 15), + child: _buildBodyColumn(context: context, viewModel: viewModel), + ); + + Widget _buildBodyColumn( + {required BuildContext context, + required LearnPracticeViewModel viewModel}) => + Column( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: + _buildBodyColumnChildren(context: context, viewModel: viewModel), + ); + + List _buildBodyColumnChildren( + {required BuildContext context, + required LearnPracticeViewModel viewModel}) => + [ + _buildAppBarWrapper(context: context, viewModel: viewModel), + _buildSpeakingIndicatorWrapper(viewModel), + _buildLowerButtonsSectionWrapper(viewModel) + ]; + + Widget _buildAppBarWrapper( + {required BuildContext context, + required LearnPracticeViewModel viewModel}) => + Column( + children: [ + verticalSpaceMedium, + _buildAppBar(context: context, viewModel: viewModel), + verticalSpaceMedium, + ], + ); + + Widget _buildAppBar( + {required BuildContext context, + required LearnPracticeViewModel viewModel}) => + SmallAppBar( + showBackButton: true, + onPop: () async => + await _showSheet(context: context, viewModel: viewModel), + ); + + Widget _buildSheet(LearnPracticeViewModel viewModel) => + CancelLearnPracticeSheet( + onClose: viewModel.pop, + onContinue: viewModel.pop, + user: viewModel.user?.firstName ?? '', + onCancel: () async => await _cancel(viewModel), + ); + Widget _buildSpeakingIndicatorWrapper(LearnPracticeViewModel viewModel) => + Column( + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.start, + children: _buildSpeakingIndicatorChildren(viewModel), + ); + + List _buildSpeakingIndicatorChildren( + LearnPracticeViewModel viewModel) => + [ + _buildIcon(), + verticalSpaceMedium, + _buildTitle(viewModel), + _buildSubtitle(), + ]; + + Widget _buildIcon() => SvgPicture.asset('assets/icons/success.svg'); + + Widget _buildTitle(LearnPracticeViewModel viewModel) => Text( + 'Great work, ${viewModel.user?.firstName}', + style: style25DG600, + textAlign: TextAlign.center, + ); + + Widget _buildSubtitle() => Text( + 'You have finished your practice', + style: style14DG400, + textAlign: TextAlign.center, + ); + + Widget _buildLowerButtonsSectionWrapper(LearnPracticeViewModel viewModel) => + Padding( + padding: const EdgeInsets.symmetric(vertical: 50), + child: _buildContinueButton(viewModel), + ); + + Widget _buildContinueButton(LearnPracticeViewModel viewModel) => + CustomElevatedButton( + height: 55, + borderRadius: 12, + text: 'View My Results', + foregroundColor: kcWhite, + onTap: () => viewModel.goTo(4), + backgroundColor: kcPrimaryColor, + ); +} diff --git a/lib/ui/views/learn_practice/screens/learn_practice_completion_screen.dart b/lib/ui/views/learn_practice/screens/learn_practice_completion_screen.dart index 8064403..5776f8f 100644 --- a/lib/ui/views/learn_practice/screens/learn_practice_completion_screen.dart +++ b/lib/ui/views/learn_practice/screens/learn_practice_completion_screen.dart @@ -3,12 +3,9 @@ import 'package:flutter_svg/svg.dart'; import 'package:stacked/stacked.dart'; import 'package:yimaru_app/ui/views/learn_practice/learn_practice_viewmodel.dart'; -import '../../../../models/learn_practice.dart'; import '../../../common/app_colors.dart'; -import '../../../common/enmus.dart'; import '../../../common/ui_helpers.dart'; import '../../../widgets/custom_elevated_button.dart'; -import '../../../widgets/page_loading_indicator.dart'; class LearnPracticeCompletionScreen extends ViewModelWidget { @@ -21,7 +18,12 @@ class LearnPracticeCompletionScreen Widget _buildScaffoldWrapper(LearnPracticeViewModel viewModel) => Scaffold( backgroundColor: kcBackgroundColor, - body: _buildBodyWrapper(viewModel), + body: _buildScaffoldContainer(viewModel), + ); + + Widget _buildScaffoldContainer(LearnPracticeViewModel viewModel) => Container( + decoration: bgDecoration, + child: _buildBodyWrapper(viewModel), ); Widget _buildBodyWrapper(LearnPracticeViewModel viewModel) => Padding( @@ -29,14 +31,18 @@ class LearnPracticeCompletionScreen child: _buildBody(viewModel), ); - Widget _buildBody(LearnPracticeViewModel viewModel) => Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - mainAxisAlignment: MainAxisAlignment.spaceBetween, + Widget _buildBody(LearnPracticeViewModel viewModel) => Stack( children: _buildBodyChildren(viewModel), ); - List _buildBodyChildren(LearnPracticeViewModel viewModel) => - [_buildUpperColumn(viewModel), _buildContinueButtonWrapper(viewModel)]; + List _buildBodyChildren(LearnPracticeViewModel viewModel) => [ + _buildUpperColumnWrapper(viewModel), + _buildContinueButtonWrapper(viewModel) + ]; + Widget _buildUpperColumnWrapper(LearnPracticeViewModel viewModel) => Align( + alignment: Alignment.center, + child: _buildUpperColumn(viewModel), + ); Widget _buildUpperColumn(LearnPracticeViewModel viewModel) => Column( mainAxisSize: MainAxisSize.min, @@ -45,16 +51,13 @@ class LearnPracticeCompletionScreen ); List _buildUpperColumnChildren(LearnPracticeViewModel viewModel) => [ - verticalSpaceMassive, _buildIcon(), verticalSpaceMedium, _buildTitle(), - verticalSpaceSmall, - _buildSubtitle(), ]; Widget _buildIcon() => SvgPicture.asset( - 'assets/icons/complete.svg', + 'assets/icons/mascot.svg', ); Widget _buildTitle() => Text( @@ -63,13 +66,12 @@ class LearnPracticeCompletionScreen textAlign: TextAlign.center, ); - Widget _buildSubtitle() => Text( - 'We’re now analyzing your speaking skills', - textAlign: TextAlign.center, - style: style14MG400, + Widget _buildContinueButtonWrapper(LearnPracticeViewModel viewModel) => Align( + alignment: Alignment.bottomCenter, + child: _buildContinueButtonPadding(viewModel), ); - Widget _buildContinueButtonWrapper(LearnPracticeViewModel viewModel) => + Widget _buildContinueButtonPadding(LearnPracticeViewModel viewModel) => Padding( padding: const EdgeInsets.only(bottom: 50), child: _buildContinueButton(viewModel), diff --git a/lib/ui/views/learn_practice/screens/learn_practice_description_screen.dart b/lib/ui/views/learn_practice/screens/learn_practice_description_screen.dart index 0144c2a..5940e20 100644 --- a/lib/ui/views/learn_practice/screens/learn_practice_description_screen.dart +++ b/lib/ui/views/learn_practice/screens/learn_practice_description_screen.dart @@ -39,7 +39,15 @@ class LearnPracticeDescriptionScreen required LearnPracticeViewModel viewModel}) => Scaffold( backgroundColor: kcBackgroundColor, - body: _buildScaffold(context: context, viewModel: viewModel), + body: _buildScaffoldContainer(context: context, viewModel: viewModel), + ); + + Widget _buildScaffoldContainer( + {required BuildContext context, + required LearnPracticeViewModel viewModel}) => + Container( + decoration: bgDecoration, + child: _buildScaffold(context: context, viewModel: viewModel), ); Widget _buildScaffold( diff --git a/lib/ui/views/learn_practice/screens/finish_learn_practice_screen.dart b/lib/ui/views/learn_practice/screens/learn_practice_finish_screen.dart similarity index 92% rename from lib/ui/views/learn_practice/screens/finish_learn_practice_screen.dart rename to lib/ui/views/learn_practice/screens/learn_practice_finish_screen.dart index 3c59be7..0991d0d 100644 --- a/lib/ui/views/learn_practice/screens/finish_learn_practice_screen.dart +++ b/lib/ui/views/learn_practice/screens/learn_practice_finish_screen.dart @@ -8,9 +8,9 @@ import '../../../common/ui_helpers.dart'; import '../../../widgets/custom_elevated_button.dart'; import '../../../widgets/small_app_bar.dart'; -class FinishLearnPracticeScreen +class LearnPracticeFinishScreen extends ViewModelWidget { - const FinishLearnPracticeScreen({super.key}); + const LearnPracticeFinishScreen({super.key}); Future _reset(LearnPracticeViewModel viewModel) async => await viewModel.reset(); @@ -21,7 +21,12 @@ class FinishLearnPracticeScreen Widget _buildScaffoldWrapper(LearnPracticeViewModel viewModel) => Scaffold( backgroundColor: kcBackgroundColor, - body: _buildScaffold(viewModel), + body: _buildScaffoldContainer(viewModel), + ); + + Widget _buildScaffoldContainer(LearnPracticeViewModel viewModel) => Container( + decoration: bgDecoration, + child: _buildScaffold(viewModel), ); Widget _buildScaffold(LearnPracticeViewModel viewModel) => @@ -110,9 +115,9 @@ class FinishLearnPracticeScreen CustomElevatedButton( height: 55, borderRadius: 12, + onTap: viewModel.pop, foregroundColor: kcWhite, text: 'Continue Practice', - onTap: () => viewModel.goTo(4), backgroundColor: kcPrimaryColor, ); diff --git a/lib/ui/views/learn_practice/screens/learn_practice_intro_screen.dart b/lib/ui/views/learn_practice/screens/learn_practice_intro_screen.dart index 5229abb..f972446 100644 --- a/lib/ui/views/learn_practice/screens/learn_practice_intro_screen.dart +++ b/lib/ui/views/learn_practice/screens/learn_practice_intro_screen.dart @@ -50,7 +50,15 @@ class LearnPracticeIntroScreen extends ViewModelWidget { required LearnPracticeViewModel viewModel}) => Scaffold( backgroundColor: kcBackgroundColor, - body: _buildScaffold(context: context, viewModel: viewModel), + body: _buildScaffoldContainer(context: context, viewModel: viewModel), + ); + + Widget _buildScaffoldContainer( + {required BuildContext context, + required LearnPracticeViewModel viewModel}) => + Container( + decoration: bgDecoration, + child: _buildScaffold(context: context, viewModel: viewModel), ); Widget _buildScaffold( diff --git a/lib/ui/views/learn_practice/screens/learn_practice_result_screen.dart b/lib/ui/views/learn_practice/screens/learn_practice_result_screen.dart index 7b98efd..514cc5c 100644 --- a/lib/ui/views/learn_practice/screens/learn_practice_result_screen.dart +++ b/lib/ui/views/learn_practice/screens/learn_practice_result_screen.dart @@ -21,9 +21,11 @@ class LearnPracticeResultScreen Future _navigate(LearnPracticeViewModel viewModel) async { await viewModel.completeLearnPractices(); if (practice == LearnPractices.course) { + viewModel.goTo(6); + } else if (practice == LearnPractices.module) { viewModel.goTo(5); } else { - viewModel.pop(); + viewModel.goTo(4); } } @@ -55,7 +57,15 @@ class LearnPracticeResultScreen required LearnPracticeViewModel viewModel}) => Scaffold( backgroundColor: kcBackgroundColor, - body: _buildScaffoldState(context: context, viewModel: viewModel), + body: _buildScaffoldContainer(context: context, viewModel: viewModel), + ); + + Widget _buildScaffoldContainer( + {required BuildContext context, + required LearnPracticeViewModel viewModel}) => + Container( + decoration: bgDecoration, + child: _buildScaffoldState(context: context, viewModel: viewModel), ); Widget _buildScaffoldState( diff --git a/lib/ui/views/learn_practice/screens/start_learn_practice_screen.dart b/lib/ui/views/learn_practice/screens/start_learn_practice_screen.dart index 70f6b6c..e2e6f11 100644 --- a/lib/ui/views/learn_practice/screens/start_learn_practice_screen.dart +++ b/lib/ui/views/learn_practice/screens/start_learn_practice_screen.dart @@ -44,7 +44,15 @@ class StartLearnPracticeScreen extends ViewModelWidget { required LearnPracticeViewModel viewModel}) => Scaffold( backgroundColor: kcBackgroundColor, - body: _buildScaffold(context: context, viewModel: viewModel), + body: _buildScaffoldContainer(context: context, viewModel: viewModel), + ); + + Widget _buildScaffoldContainer( + {required BuildContext context, + required LearnPracticeViewModel viewModel}) => + Container( + decoration: bgDecoration, + child: _buildScaffold(context: context, viewModel: viewModel), ); Widget _buildScaffold( diff --git a/lib/ui/views/learn_program/learn_program_view.dart b/lib/ui/views/learn_program/learn_program_view.dart index 7a7e93d..38f985f 100644 --- a/lib/ui/views/learn_program/learn_program_view.dart +++ b/lib/ui/views/learn_program/learn_program_view.dart @@ -33,7 +33,12 @@ class LearnProgramView extends StackedView { Widget _buildScaffoldWrapper(LearnProgramViewModel viewModel) => Scaffold( backgroundColor: kcBackgroundColor, - body: _buildScaffold(viewModel), + body: _buildScaffoldContainer(viewModel), + ); + + Widget _buildScaffoldContainer(LearnProgramViewModel viewModel) => Container( + decoration: bgDecoration, + child: _buildScaffold(viewModel), ); Widget _buildScaffold(LearnProgramViewModel viewModel) => diff --git a/lib/ui/views/learn_program/learn_program_viewmodel.dart b/lib/ui/views/learn_program/learn_program_viewmodel.dart index 5415691..0c63a3a 100644 --- a/lib/ui/views/learn_program/learn_program_viewmodel.dart +++ b/lib/ui/views/learn_program/learn_program_viewmodel.dart @@ -5,7 +5,6 @@ import 'package:yimaru_app/models/learn_program.dart'; import '../../../app/app.locator.dart'; import '../../../models/user.dart'; -import '../../../services/api_service.dart'; import '../../../services/authentication_service.dart'; import '../../../services/learn_service.dart'; import '../../../services/status_checker_service.dart'; diff --git a/lib/ui/views/learn_subscription/learn_subscription_view.dart b/lib/ui/views/learn_subscription/learn_subscription_view.dart index 18c8fbf..df1f9fd 100644 --- a/lib/ui/views/learn_subscription/learn_subscription_view.dart +++ b/lib/ui/views/learn_subscription/learn_subscription_view.dart @@ -4,14 +4,8 @@ import 'package:stacked/stacked_annotations.dart'; import 'package:yimaru_app/ui/views/learn_subscription/learn_subscription_view.form.dart'; import 'package:yimaru_app/ui/views/learn_subscription/screens/learn_subscription_form_screen.dart'; import 'package:yimaru_app/ui/views/learn_subscription/screens/learn_subscription_package_screen.dart'; -import 'package:yimaru_app/ui/widgets/learn_subscription_card.dart'; -import 'package:yimaru_app/ui/widgets/learn_subscription_pricing_section.dart'; -import '../../common/app_colors.dart'; -import '../../common/ui_helpers.dart'; import '../../common/validators/form_validator.dart'; -import '../../widgets/custom_elevated_button.dart'; -import '../../widgets/small_app_bar.dart'; import 'learn_subscription_viewmodel.dart'; @FormView(fields: [ diff --git a/lib/ui/views/learn_subscription/learn_subscription_viewmodel.dart b/lib/ui/views/learn_subscription/learn_subscription_viewmodel.dart index ade0e9c..706ae0b 100644 --- a/lib/ui/views/learn_subscription/learn_subscription_viewmodel.dart +++ b/lib/ui/views/learn_subscription/learn_subscription_viewmodel.dart @@ -2,7 +2,6 @@ import 'package:stacked/stacked.dart'; import 'package:stacked_services/stacked_services.dart'; import 'package:yimaru_app/app/app.router.dart'; import 'package:yimaru_app/models/learn_subscription.dart'; -import 'package:yimaru_app/models/learn_subscription_request.dart'; import '../../../app/app.locator.dart'; import '../../../services/api_service.dart'; diff --git a/lib/ui/views/learn_subscription/screens/learn_subscription_form_screen.dart b/lib/ui/views/learn_subscription/screens/learn_subscription_form_screen.dart index 668f24e..9139539 100644 --- a/lib/ui/views/learn_subscription/screens/learn_subscription_form_screen.dart +++ b/lib/ui/views/learn_subscription/screens/learn_subscription_form_screen.dart @@ -3,13 +3,10 @@ import 'package:flutter/services.dart'; import 'package:stacked/stacked.dart'; import 'package:yimaru_app/ui/views/learn_subscription/learn_subscription_viewmodel.dart'; import 'package:yimaru_app/ui/widgets/phone_number_prefix.dart'; -import 'package:yimaru_app/ui/widgets/speaking_partner_image.dart'; import '../../../common/app_colors.dart'; import '../../../common/ui_helpers.dart'; import '../../../widgets/small_app_bar.dart'; -import '../../course_practice_question/course_practice_question_view.form.dart'; -import '../../../widgets/custom_bottom_sheet.dart'; import '../../../widgets/custom_elevated_button.dart'; import '../learn_subscription_view.form.dart'; @@ -29,7 +26,13 @@ class LearnSubscriptionFormScreen Widget _buildScaffoldWrapper(LearnSubscriptionViewModel viewModel) => Scaffold( backgroundColor: kcBackgroundColor, - body: _buildScaffold(viewModel), + body: _buildScaffoldContainer(viewModel), + ); + + Widget _buildScaffoldContainer(LearnSubscriptionViewModel viewModel) => + Container( + decoration: bgDecoration, + child: _buildScaffold(viewModel), ); Widget _buildScaffold(LearnSubscriptionViewModel viewModel) => diff --git a/lib/ui/views/learn_subscription/screens/learn_subscription_package_screen.dart b/lib/ui/views/learn_subscription/screens/learn_subscription_package_screen.dart index 7db45ea..9fca733 100644 --- a/lib/ui/views/learn_subscription/screens/learn_subscription_package_screen.dart +++ b/lib/ui/views/learn_subscription/screens/learn_subscription_package_screen.dart @@ -22,7 +22,13 @@ class LearnSubscriptionPackageScreen Widget _buildScaffoldWrapper(LearnSubscriptionViewModel viewModel) => Scaffold( backgroundColor: kcBackgroundColor, - body: _buildScaffoldState(viewModel), + body: _buildScaffoldContainer(viewModel), + ); + + Widget _buildScaffoldContainer(LearnSubscriptionViewModel viewModel) => + Container( + decoration: bgDecoration, + child: _buildScaffoldState(viewModel), ); Widget _buildScaffoldState(LearnSubscriptionViewModel viewModel) => diff --git a/lib/ui/views/login/login_viewmodel.dart b/lib/ui/views/login/login_viewmodel.dart index 9c5f264..ca70a80 100644 --- a/lib/ui/views/login/login_viewmodel.dart +++ b/lib/ui/views/login/login_viewmodel.dart @@ -30,7 +30,8 @@ class LoginViewModel extends ReactiveViewModel final _authenticationService = locator(); @override - List get listenableServices => [_googleAuthService,_localizationService]; + List get listenableServices => + [_googleAuthService, _localizationService]; // Google user GoogleSignInAccount? get _googleUser => _googleAuthService.googleUser; @@ -38,7 +39,8 @@ class LoginViewModel extends ReactiveViewModel GoogleSignInAccount? get googleUser => _googleUser; // Languages - Map get _selectedLanguage => _localizationService.selectedLanguage; + Map get _selectedLanguage => + _localizationService.selectedLanguage; Map get selectedLanguage => _selectedLanguage; @@ -172,8 +174,6 @@ class LoginViewModel extends ReactiveViewModel Future navigateToForgetPassword() async => await _navigationService.navigateToForgetPasswordView(); - - Future replaceWithStartUp() async => await _navigationService.clearStackAndShow(Routes.startupView); diff --git a/lib/ui/views/login/screens/login_otp_screen.dart b/lib/ui/views/login/screens/login_otp_screen.dart index e0a35dc..055d8de 100644 --- a/lib/ui/views/login/screens/login_otp_screen.dart +++ b/lib/ui/views/login/screens/login_otp_screen.dart @@ -1,9 +1,11 @@ +import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter_timer_countdown/flutter_timer_countdown.dart'; import 'package:pinput/pinput.dart'; import 'package:stacked/stacked.dart'; import 'package:yimaru_app/app/app.locator.dart'; import 'package:yimaru_app/services/smart_auth_service.dart'; +import 'package:yimaru_app/ui/common/translations/locale_keys.g.dart'; import 'package:yimaru_app/ui/widgets/custom_cursor.dart'; import '../../../common/app_colors.dart'; @@ -52,7 +54,14 @@ class LoginOtpScreen extends ViewModelWidget { {required BuildContext context, required LoginViewModel viewModel}) => Scaffold( backgroundColor: kcBackgroundColor, - body: _buildScaffoldStack(context: context, viewModel: viewModel), + body: _buildScaffoldContainer(context: context, viewModel: viewModel), + ); + + Widget _buildScaffoldContainer( + {required BuildContext context, required LoginViewModel viewModel}) => + Container( + decoration: bgDecoration, + child: _buildScaffoldStack(context: context, viewModel: viewModel), ); Widget _buildScaffoldStack( @@ -80,14 +89,12 @@ class LoginOtpScreen extends ViewModelWidget { _buildExpandedBody(context: context, viewModel: viewModel) ]; - Widget _buildAppBar(LoginViewModel viewModel) => LargeAppBar( + Widget _buildAppBar(LoginViewModel viewModel) => LargeAppBar( showBackButton: false, showLanguageSelection: true, - language: viewModel.selectedLanguage['code'], - - onLanguage: ()async => await viewModel.navigateToLanguage(), - - ); + language: viewModel.selectedLanguage['code'], + onLanguage: () async => await viewModel.navigateToLanguage(), + ); Widget _buildExpandedBody( {required BuildContext context, required LoginViewModel viewModel}) => @@ -145,7 +152,7 @@ class LoginOtpScreen extends ViewModelWidget { ]; Widget _buildTitle() => Text( - 'Verification Code', + LocaleKeys.verification_code.tr(), style: style25DG600, ); @@ -153,7 +160,7 @@ class LoginOtpScreen extends ViewModelWidget { phoneNumberController.text.length == 9 ? _buildSubtitle() : Container(); Widget _buildSubtitle() => Text( - 'Code sent to your number +251${phoneNumberController.text.substring(0, 5)}****', + '${LocaleKeys.code_sent_to_phone.tr()} +251${phoneNumberController.text.substring(0, 3)}******', style: style14DG400, ); @@ -199,7 +206,7 @@ class LoginOtpScreen extends ViewModelWidget { child: _buildResendText()); Widget _buildResendText() => Text( - 'Resend code', + LocaleKeys.reset_code.tr(), style: style14P600.copyWith(fontStyle: FontStyle.italic), ); @@ -211,7 +218,8 @@ class LoginOtpScreen extends ViewModelWidget { ], ); - Widget _buildCountdownText() => Text('Resend code in ', style: style14DG400); + Widget _buildCountdownText() => + Text('${LocaleKeys.resend_code_in.tr()} ', style: style14DG400); Widget _buildTimer(LoginViewModel viewModel) => TimerCountdown( enableDescriptions: false, @@ -229,9 +237,9 @@ class LoginOtpScreen extends ViewModelWidget { Widget _buildContinueButton(LoginViewModel viewModel) => CustomElevatedButton( height: 55, - text: 'Continue', borderRadius: 12, foregroundColor: kcWhite, + text: LocaleKeys.cont.tr(), backgroundColor: otpController.text.length == 6 && !viewModel.hasOtpValidationMessage ? kcPrimaryColor diff --git a/lib/ui/views/login/screens/login_with_email_screen.dart b/lib/ui/views/login/screens/login_with_email_screen.dart index bfb8aaa..196d9fb 100644 --- a/lib/ui/views/login/screens/login_with_email_screen.dart +++ b/lib/ui/views/login/screens/login_with_email_screen.dart @@ -51,7 +51,14 @@ class LoginWithEmailScreen extends ViewModelWidget { {required BuildContext context, required LoginViewModel viewModel}) => Scaffold( backgroundColor: kcBackgroundColor, - body: _buildScaffoldStack(context: context, viewModel: viewModel), + body: _buildScaffoldContainer(context: context, viewModel: viewModel), + ); + + Widget _buildScaffoldContainer( + {required BuildContext context, required LoginViewModel viewModel}) => + Container( + decoration: bgDecoration, + child: _buildScaffoldStack(context: context, viewModel: viewModel), ); Widget _buildScaffoldStack( @@ -260,15 +267,14 @@ class LoginWithEmailScreen extends ViewModelWidget { Widget _buildLoginWithPhoneButton(LoginViewModel viewModel) => CustomElevatedButton( - height: 55, - borderRadius: 12, - backgroundColor: kcWhite, - leadingIcon: Icons.phone, - borderColor: kcPrimaryColor, - onTap: () => viewModel.goTo(1), - foregroundColor: kcPrimaryColor, - text: LocaleKeys.login_with_phone.tr() - ); + height: 55, + borderRadius: 12, + backgroundColor: kcWhite, + leadingIcon: Icons.phone, + borderColor: kcPrimaryColor, + onTap: () => viewModel.goTo(1), + foregroundColor: kcPrimaryColor, + text: LocaleKeys.login_with_phone.tr()); Widget _buildLoginWithEmailState(LoginViewModel viewModel) => viewModel.busy(StateObjects.loginWithEmail) diff --git a/lib/ui/views/login/screens/login_with_phone_number_screen.dart b/lib/ui/views/login/screens/login_with_phone_number_screen.dart index 4765476..8d26215 100644 --- a/lib/ui/views/login/screens/login_with_phone_number_screen.dart +++ b/lib/ui/views/login/screens/login_with_phone_number_screen.dart @@ -1,6 +1,8 @@ +import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:stacked/stacked.dart'; +import 'package:yimaru_app/ui/common/translations/locale_keys.g.dart'; import 'package:yimaru_app/ui/views/login/login_viewmodel.dart'; import 'package:yimaru_app/ui/widgets/option_text_divider.dart'; import 'package:yimaru_app/ui/widgets/register_for_account.dart'; @@ -46,7 +48,14 @@ class LoginWithPhoneNumberScreen extends ViewModelWidget { {required BuildContext context, required LoginViewModel viewModel}) => Scaffold( backgroundColor: kcBackgroundColor, - body: _buildScaffoldStack(context: context, viewModel: viewModel), + body: _buildScaffoldContainer(context: context, viewModel: viewModel), + ); + + Widget _buildScaffoldContainer( + {required BuildContext context, required LoginViewModel viewModel}) => + Container( + decoration: bgDecoration, + child: _buildScaffoldStack(context: context, viewModel: viewModel), ); Widget _buildScaffoldStack( @@ -76,11 +85,9 @@ class LoginWithPhoneNumberScreen extends ViewModelWidget { showBackButton: true, showLanguageSelection: true, onPop: () => viewModel.goTo(0), - language: viewModel.selectedLanguage['code'], - - onLanguage: ()async => await viewModel.navigateToLanguage(), - - ); + language: viewModel.selectedLanguage['code'], + onLanguage: () async => await viewModel.navigateToLanguage(), + ); Widget _buildExpandedBody( {required BuildContext context, required LoginViewModel viewModel}) => @@ -138,7 +145,7 @@ class LoginWithPhoneNumberScreen extends ViewModelWidget { ]; Widget _buildTitle() => Text( - 'Welcome Back', + LocaleKeys.welcome_back.tr(), style: style25DG600, ); @@ -147,7 +154,7 @@ class LoginWithPhoneNumberScreen extends ViewModelWidget { ); Widget _buildSubtitle() => Text( - 'Enter your phone number. We will send you a confirmation code there', + LocaleKeys.enter_phone_number.tr(), style: style14MG400, ); @@ -205,9 +212,9 @@ class LoginWithPhoneNumberScreen extends ViewModelWidget { Widget _buildContinueButton(LoginViewModel viewModel) => CustomElevatedButton( height: 55, - text: 'Continue', borderRadius: 12, foregroundColor: kcWhite, + text: LocaleKeys.cont.tr(), onTap: phoneNumberController.text.isNotEmpty ? () async => await _login(viewModel) : null, @@ -220,12 +227,12 @@ class LoginWithPhoneNumberScreen extends ViewModelWidget { CustomElevatedButton( height: 55, borderRadius: 12, - text: 'Login with Email', backgroundColor: kcWhite, leadingIcon: Icons.email, borderColor: kcPrimaryColor, - foregroundColor: kcPrimaryColor, onTap: () => viewModel.goTo(0), + foregroundColor: kcPrimaryColor, + text: LocaleKeys.login_with_email.tr(), ); Widget _buildLoginWithPhoneNumber(LoginViewModel viewModel) => diff --git a/lib/ui/views/onboarding/onboarding_viewmodel.dart b/lib/ui/views/onboarding/onboarding_viewmodel.dart index 52aad06..c3fefdc 100644 --- a/lib/ui/views/onboarding/onboarding_viewmodel.dart +++ b/lib/ui/views/onboarding/onboarding_viewmodel.dart @@ -17,19 +17,18 @@ class OnboardingViewModel extends ReactiveViewModel final _localizationService = locator(); - - @override - List get listenableServices => [_googleAuthService,_localizationService]; + List get listenableServices => + [_googleAuthService, _localizationService]; // Google user GoogleSignInAccount? get _googleUser => _googleAuthService.googleUser; GoogleSignInAccount? get googleUser => _googleUser; - // Languages - Map get _selectedLanguage => _localizationService.selectedLanguage; + Map get _selectedLanguage => + _localizationService.selectedLanguage; Map get selectedLanguage => _selectedLanguage; @@ -218,7 +217,6 @@ class OnboardingViewModel extends ReactiveViewModel List get topics => _topics; - // User data final Map _userData = {}; diff --git a/lib/ui/views/onboarding/screens/age_group_form_screen.dart b/lib/ui/views/onboarding/screens/age_group_form_screen.dart index a05640d..d31ead4 100644 --- a/lib/ui/views/onboarding/screens/age_group_form_screen.dart +++ b/lib/ui/views/onboarding/screens/age_group_form_screen.dart @@ -88,9 +88,8 @@ class AgeGroupFormScreen extends ViewModelWidget { showBackButton: true, showLanguageSelection: true, onPop: () => _pop(viewModel), - language: viewModel.selectedLanguage['code'], - - onLanguage: () async => await viewModel.navigateToLanguage(), + language: viewModel.selectedLanguage['code'], + onLanguage: () async => await viewModel.navigateToLanguage(), ); Widget _buildTitle() => Text( diff --git a/lib/ui/views/onboarding/screens/challenge_form_screen.dart b/lib/ui/views/onboarding/screens/challenge_form_screen.dart index 9ce2fa7..9c9563c 100644 --- a/lib/ui/views/onboarding/screens/challenge_form_screen.dart +++ b/lib/ui/views/onboarding/screens/challenge_form_screen.dart @@ -102,9 +102,8 @@ class ChallengeFormScreen extends ViewModelWidget { showBackButton: true, showLanguageSelection: true, onPop: () => _pop(viewModel), - language: viewModel.selectedLanguage['code'], - - onLanguage: () async => await viewModel.navigateToLanguage(), + language: viewModel.selectedLanguage['code'], + onLanguage: () async => await viewModel.navigateToLanguage(), ); Widget _buildTitle() => Text( diff --git a/lib/ui/views/onboarding/screens/country_region_form_screen.dart b/lib/ui/views/onboarding/screens/country_region_form_screen.dart index 6b5c424..e629288 100644 --- a/lib/ui/views/onboarding/screens/country_region_form_screen.dart +++ b/lib/ui/views/onboarding/screens/country_region_form_screen.dart @@ -112,8 +112,8 @@ class CountryRegionFormScreen extends ViewModelWidget { showBackButton: true, showLanguageSelection: true, onPop: () => _pop(viewModel), - language: viewModel.selectedLanguage['code'], - onLanguage: () async => await viewModel.navigateToLanguage(), + language: viewModel.selectedLanguage['code'], + onLanguage: () async => await viewModel.navigateToLanguage(), ); Widget _buildTitle() => Text( diff --git a/lib/ui/views/onboarding/screens/educational_background_form_screen.dart b/lib/ui/views/onboarding/screens/educational_background_form_screen.dart index ba49d19..91a0cbf 100644 --- a/lib/ui/views/onboarding/screens/educational_background_form_screen.dart +++ b/lib/ui/views/onboarding/screens/educational_background_form_screen.dart @@ -88,8 +88,8 @@ class EducationalBackgroundFormScreen showBackButton: true, showLanguageSelection: true, onPop: () => _pop(viewModel), - language: viewModel.selectedLanguage['code'], - onLanguage: () async => await viewModel.navigateToLanguage(), + language: viewModel.selectedLanguage['code'], + onLanguage: () async => await viewModel.navigateToLanguage(), ); Widget _buildTitle() => const Text( diff --git a/lib/ui/views/onboarding/screens/full_name_form_screen.dart b/lib/ui/views/onboarding/screens/full_name_form_screen.dart index b15fb23..fe55cb1 100644 --- a/lib/ui/views/onboarding/screens/full_name_form_screen.dart +++ b/lib/ui/views/onboarding/screens/full_name_form_screen.dart @@ -88,8 +88,8 @@ class FullNameFormScreen extends ViewModelWidget { Widget _buildAppBar(OnboardingViewModel viewModel) => LargeAppBar( showBackButton: false, showLanguageSelection: true, - language: viewModel.selectedLanguage['code'], - onLanguage: () async => await viewModel.navigateToLanguage(), + language: viewModel.selectedLanguage['code'], + onLanguage: () async => await viewModel.navigateToLanguage(), ); Widget _buildTitle() => const Text( diff --git a/lib/ui/views/onboarding/screens/gender_form_screen.dart b/lib/ui/views/onboarding/screens/gender_form_screen.dart index 4e29cef..7430425 100644 --- a/lib/ui/views/onboarding/screens/gender_form_screen.dart +++ b/lib/ui/views/onboarding/screens/gender_form_screen.dart @@ -80,9 +80,8 @@ class GenderFormScreen extends ViewModelWidget { showBackButton: true, showLanguageSelection: true, onPop: () => _pop(viewModel), - language: viewModel.selectedLanguage['code'], - - onLanguage: () async => await viewModel.navigateToLanguage(), + language: viewModel.selectedLanguage['code'], + onLanguage: () async => await viewModel.navigateToLanguage(), ); Widget _buildTitle() => Text( diff --git a/lib/ui/views/onboarding/screens/language_goal_form_screen.dart b/lib/ui/views/onboarding/screens/language_goal_form_screen.dart index 6474fea..e082097 100644 --- a/lib/ui/views/onboarding/screens/language_goal_form_screen.dart +++ b/lib/ui/views/onboarding/screens/language_goal_form_screen.dart @@ -103,8 +103,8 @@ class LanguageGoalFormScreen extends ViewModelWidget { showBackButton: true, showLanguageSelection: true, onPop: () => _pop(viewModel), - language: viewModel.selectedLanguage['code'], - onLanguage: () async => await viewModel.navigateToLanguage(), + language: viewModel.selectedLanguage['code'], + onLanguage: () async => await viewModel.navigateToLanguage(), ); Widget _buildTitle() => Text( diff --git a/lib/ui/views/onboarding/screens/learning_goal_form_screen.dart b/lib/ui/views/onboarding/screens/learning_goal_form_screen.dart index a2823bd..109535b 100644 --- a/lib/ui/views/onboarding/screens/learning_goal_form_screen.dart +++ b/lib/ui/views/onboarding/screens/learning_goal_form_screen.dart @@ -98,9 +98,8 @@ class LearningGoalFormScreen extends ViewModelWidget { showBackButton: true, showLanguageSelection: true, onPop: () => _pop(viewModel), - language: viewModel.selectedLanguage['code'], - - onLanguage: () async => await viewModel.navigateToLanguage(), + language: viewModel.selectedLanguage['code'], + onLanguage: () async => await viewModel.navigateToLanguage(), ); Widget _buildTitle(OnboardingViewModel viewModel) => Text.rich( diff --git a/lib/ui/views/onboarding/screens/occupation_form_screen.dart b/lib/ui/views/onboarding/screens/occupation_form_screen.dart index 31f2eec..de1797b 100644 --- a/lib/ui/views/onboarding/screens/occupation_form_screen.dart +++ b/lib/ui/views/onboarding/screens/occupation_form_screen.dart @@ -86,9 +86,8 @@ class OccupationFormScreen extends ViewModelWidget { showBackButton: true, showLanguageSelection: true, onPop: () => _pop(viewModel), - language: viewModel.selectedLanguage['code'], - - onLanguage: () async => await viewModel.navigateToLanguage(), + language: viewModel.selectedLanguage['code'], + onLanguage: () async => await viewModel.navigateToLanguage(), ); Widget _buildTitle() => Text( diff --git a/lib/ui/views/onboarding/screens/topic_form_screen.dart b/lib/ui/views/onboarding/screens/topic_form_screen.dart index 0569107..21817b6 100644 --- a/lib/ui/views/onboarding/screens/topic_form_screen.dart +++ b/lib/ui/views/onboarding/screens/topic_form_screen.dart @@ -58,9 +58,8 @@ class TopicFormScreen extends ViewModelWidget { showBackButton: true, showLanguageSelection: true, onPop: () => _pop(viewModel), - language: viewModel.selectedLanguage['code'], - - onLanguage: () async => await viewModel.navigateToLanguage(), + language: viewModel.selectedLanguage['code'], + onLanguage: () async => await viewModel.navigateToLanguage(), ); Widget _buildExpandedBody(OnboardingViewModel viewModel) => diff --git a/lib/ui/views/privacy_policy/privacy_policy_view.dart b/lib/ui/views/privacy_policy/privacy_policy_view.dart index 6ae303b..f78a9bd 100644 --- a/lib/ui/views/privacy_policy/privacy_policy_view.dart +++ b/lib/ui/views/privacy_policy/privacy_policy_view.dart @@ -1,5 +1,7 @@ import 'package:flutter/material.dart'; +import 'package:flutter_html/flutter_html.dart'; import 'package:stacked/stacked.dart'; +import 'package:yimaru_app/ui/common/app_strings.dart'; import 'package:yimaru_app/ui/widgets/privacy_policy_tile.dart'; import '../../common/app_colors.dart'; @@ -22,7 +24,7 @@ class PrivacyPolicyView extends StackedView { ) => _buildScaffoldWrapper(viewModel); - Widget _buildScaffoldWrapper(PrivacyPolicyViewModel viewModel) => Scaffold( +/* Widget _buildScaffoldWrapper(PrivacyPolicyViewModel viewModel) => Scaffold( backgroundColor: kcBackgroundColor, body: _buildScaffold(viewModel), ); @@ -91,4 +93,62 @@ class PrivacyPolicyView extends StackedView { ); Widget _buildTile(String title) => PrivacyPolicyTile(title: title); +*/ + + Widget _buildScaffoldWrapper(PrivacyPolicyViewModel viewModel) => Scaffold( + backgroundColor: kcBackgroundColor, + body: _buildScaffold(viewModel), + ); + + Widget _buildScaffold(PrivacyPolicyViewModel viewModel) => + SafeArea(child: _buildBodyWrapper(viewModel)); + + Widget _buildBodyWrapper(PrivacyPolicyViewModel viewModel) => + _buildBody(viewModel); + + Widget _buildBody(PrivacyPolicyViewModel viewModel) => + _buildColumn(viewModel); + + Widget _buildColumn(PrivacyPolicyViewModel viewModel) => Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: _buildColumnChildren(viewModel), + ); + + List _buildColumnChildren(PrivacyPolicyViewModel viewModel) => [ + verticalSpaceMedium, + _buildAppBarWrapper(viewModel), + verticalSpaceSmall, + _buildContentWrapper(viewModel) + ]; + + Widget _buildAppBarWrapper(PrivacyPolicyViewModel viewModel) => Padding( + padding: const EdgeInsets.symmetric(horizontal: 15), + child: _buildAppbar(viewModel), + ); + + Widget _buildAppbar(PrivacyPolicyViewModel viewModel) => SmallAppBar( + onPop: viewModel.pop, + showBackButton: true, + title: 'Privacy Policy', + ); + + Widget _buildContentWrapper(PrivacyPolicyViewModel viewModel) => + Expanded(child: _buildContentColumnWrapper(viewModel)); + + Widget _buildContentColumnWrapper(PrivacyPolicyViewModel viewModel) => + Padding( + padding: const EdgeInsets.symmetric(horizontal: 15), + child: _buildMenuColumnScrollView(viewModel), + ); + + Widget _buildMenuColumnScrollView(PrivacyPolicyViewModel viewModel) => + SingleChildScrollView( + child: _buildContent(), + ); + + Widget _buildContent() => Html( + shrinkWrap: true, + style: htmlStyle, + data: ksPrivacyPolicy, + ); } diff --git a/lib/ui/views/register/register_viewmodel.dart b/lib/ui/views/register/register_viewmodel.dart index de4fc4e..b1fc0ff 100644 --- a/lib/ui/views/register/register_viewmodel.dart +++ b/lib/ui/views/register/register_viewmodel.dart @@ -30,7 +30,8 @@ class RegisterViewModel extends ReactiveViewModel final _authenticationService = locator(); @override - List get listenableServices => [_googleAuthService,_localizationService]; + List get listenableServices => + [_googleAuthService, _localizationService]; // Google user GoogleSignInAccount? get _googleUser => _googleAuthService.googleUser; @@ -38,11 +39,11 @@ class RegisterViewModel extends ReactiveViewModel GoogleSignInAccount? get googleUser => _googleUser; // Languages - Map get _selectedLanguage => _localizationService.selectedLanguage; + Map get _selectedLanguage => + _localizationService.selectedLanguage; Map get selectedLanguage => _selectedLanguage; - // Navigation int _currentPage = 0; @@ -275,11 +276,9 @@ class RegisterViewModel extends ReactiveViewModel Future navigateToLanguage() async => await _navigationService.navigateToLanguageView(); - Future navigateToPrivacyPolicy() async => await _navigationService.navigateToPrivacyPolicyView(); - Future navigateToTermsAndConditions() async => await _navigationService.navigateToTermsAndConditionsView(); diff --git a/lib/ui/views/register/screens/create_password_screen.dart b/lib/ui/views/register/screens/create_password_screen.dart index 4147dff..e8350c7 100644 --- a/lib/ui/views/register/screens/create_password_screen.dart +++ b/lib/ui/views/register/screens/create_password_screen.dart @@ -1,3 +1,4 @@ +import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/gestures.dart'; import 'package:flutter/material.dart'; import 'package:stacked/stacked.dart'; @@ -8,6 +9,7 @@ import 'package:yimaru_app/ui/widgets/validator_list_tile.dart'; import '../../../common/app_colors.dart'; import '../../../common/enmus.dart'; +import '../../../common/translations/locale_keys.g.dart'; import '../../../common/ui_helpers.dart'; import '../../../widgets/custom_elevated_button.dart'; import '../../../widgets/large_app_bar.dart'; @@ -43,7 +45,12 @@ class CreatePasswordScreen extends ViewModelWidget { Widget _buildScaffoldWrapper(RegisterViewModel viewModel) => Scaffold( backgroundColor: kcBackgroundColor, - body: _buildScaffoldStack(viewModel), + body: _buildScaffoldContainer(viewModel), + ); + + Widget _buildScaffoldContainer(RegisterViewModel viewModel) => Container( + decoration: bgDecoration, + child: _buildScaffoldStack(viewModel), ); Widget _buildScaffoldStack(RegisterViewModel viewModel) => Stack( @@ -68,11 +75,9 @@ class CreatePasswordScreen extends ViewModelWidget { showBackButton: true, onPop: viewModel.goBack, showLanguageSelection: true, - language: viewModel.selectedLanguage['code'], - - onLanguage: ()async => await viewModel.navigateToLanguage(), - - ); + language: viewModel.selectedLanguage['code'], + onLanguage: () async => await viewModel.navigateToLanguage(), + ); Widget _buildExpandedBody(RegisterViewModel viewModel) => Expanded(child: _buildColumnScroller(viewModel)); @@ -97,7 +102,7 @@ class CreatePasswordScreen extends ViewModelWidget { verticalSpaceMedium, _buildTitle(), verticalSpaceMedium, - _buildPasswordLabel('Password'), + _buildPasswordLabel(LocaleKeys.password.tr()), verticalSpaceSmall, _buildPasswordFormField(viewModel), if (viewModel.hasPasswordValidationMessage && viewModel.focusPassword) @@ -105,7 +110,7 @@ class CreatePasswordScreen extends ViewModelWidget { if (viewModel.hasPasswordValidationMessage && viewModel.focusPassword) _buildPasswordValidationWrapper(viewModel), verticalSpaceMedium, - _buildPasswordLabel('Confirm Password'), + _buildPasswordLabel(LocaleKeys.confirm_password.tr()), verticalSpaceSmall, _buildConfirmPasswordFormField(viewModel), if (viewModel.hasConfirmPasswordValidationMessage && @@ -125,13 +130,9 @@ class CreatePasswordScreen extends ViewModelWidget { verticalSpaceMedium ]; - Widget _buildTitle() => const Text( - 'Create Password', - style: TextStyle( - fontSize: 25, - color: kcDarkGrey, - fontWeight: FontWeight.w600, - ), + Widget _buildTitle() => Text( + LocaleKeys.create_password.tr(), + style: style25DG600, ); Widget _buildPasswordLabel(String label) => CustomFormLabel( @@ -144,7 +145,7 @@ class CreatePasswordScreen extends ViewModelWidget { onTap: viewModel.setPasswordFocus, obscureText: viewModel.obscurePassword, decoration: inputDecoration( - hint: 'Password', + hint: LocaleKeys.password.tr(), focus: viewModel.focusPassword, suffix: _buildObscurePassword(viewModel), filled: passwordController.text.isNotEmpty), @@ -166,11 +167,7 @@ class CreatePasswordScreen extends ViewModelWidget { Widget _buildPasswordValidator(RegisterViewModel viewModel) => Text( viewModel.passwordValidationMessage!, - style: const TextStyle( - fontSize: 12, - color: Colors.red, - fontWeight: FontWeight.w700, - ), + style: style12R700, ); Widget _buildConfirmPasswordFormField(RegisterViewModel viewModel) => @@ -182,8 +179,8 @@ class CreatePasswordScreen extends ViewModelWidget { password: passwordController.text, confirmPassword: confirmPasswordController.text), decoration: inputDecoration( - hint: 'Confirm Password', focus: viewModel.focusConfirmPassword, + hint: LocaleKeys.confirm_password.tr(), suffix: _buildObscureConfirmPassword(viewModel), filled: confirmPasswordController.text.isNotEmpty), ); @@ -214,14 +211,15 @@ class CreatePasswordScreen extends ViewModelWidget { Widget _buildCharLengthValidator(RegisterViewModel viewModel) => ValidatorListTile( - backgroundColor: viewModel.length ? kcPrimaryColor : kcLightGrey, - label: '8 characters minimum'); + label: LocaleKeys.eight_character_minimum.tr(), + backgroundColor: viewModel.length ? kcPrimaryColor : kcLightGrey, + ); Widget _buildPasswordMatchValidator(RegisterViewModel viewModel) => ValidatorListTile( - backgroundColor: - viewModel.passwordMatch ? kcPrimaryColor : kcLightGrey, - label: 'password match'); + label: LocaleKeys.password_match.tr(), + backgroundColor: viewModel.passwordMatch ? kcPrimaryColor : kcLightGrey, + ); Widget _buildCheckBox(RegisterViewModel viewMode) => CheckboxListTile( value: viewMode.agree, @@ -232,18 +230,18 @@ class CreatePasswordScreen extends ViewModelWidget { Widget _buildCheckBoxTitle(RegisterViewModel viewMode) => Text.rich( TextSpan( - text: 'By clicking "Sign Up", you agree to our', + text: LocaleKeys.sign_up_agreement.tr(), style: style14DG400, children: [ TextSpan( - text: ' Terms of Service', + text: ' ${LocaleKeys.terms_of_services.tr()}', style: style14P600, recognizer: TapGestureRecognizer() ..onTap = () => viewMode.navigateToTermsAndConditions()), - TextSpan(text: ' and ', style: style14DG400), + TextSpan(text: ' ${LocaleKeys.and.tr()} ', style: style14DG400), TextSpan( - text: 'Privacy Policy', style: style14P600, + text: LocaleKeys.privacy_policy.tr(), recognizer: TapGestureRecognizer() ..onTap = () => viewMode.navigateToPrivacyPolicy()), ]), @@ -252,9 +250,9 @@ class CreatePasswordScreen extends ViewModelWidget { Widget _buildSignUpButton(RegisterViewModel viewModel) => CustomElevatedButton( height: 55, - text: 'Sign Up', borderRadius: 12, foregroundColor: kcWhite, + text: LocaleKeys.register.tr(), onTap: passwordController.text.isNotEmpty && confirmPasswordController.text.isNotEmpty && viewModel.length && diff --git a/lib/ui/views/register/screens/register_with_email_screen.dart b/lib/ui/views/register/screens/register_with_email_screen.dart index 4806cfb..3630c4f 100644 --- a/lib/ui/views/register/screens/register_with_email_screen.dart +++ b/lib/ui/views/register/screens/register_with_email_screen.dart @@ -1,9 +1,11 @@ +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/widgets/login_account.dart'; import '../../../common/app_colors.dart'; +import '../../../common/translations/locale_keys.g.dart'; import '../../../common/ui_helpers.dart'; import '../../../widgets/custom_elevated_button.dart'; import '../../../widgets/large_app_bar.dart'; @@ -46,7 +48,15 @@ class RegisterWithEmailScreen extends ViewModelWidget { required RegisterViewModel viewModel}) => Scaffold( backgroundColor: kcBackgroundColor, - body: _buildScaffoldStack(context: context, viewModel: viewModel), + body: _buildScaffoldContainer(context: context, viewModel: viewModel), + ); + + Widget _buildScaffoldContainer( + {required BuildContext context, + required RegisterViewModel viewModel}) => + Container( + decoration: bgDecoration, + child: _buildScaffoldStack(context: context, viewModel: viewModel), ); Widget _buildScaffoldStack( @@ -81,11 +91,9 @@ class RegisterWithEmailScreen extends ViewModelWidget { showBackButton: true, onPop: viewModel.goBack, showLanguageSelection: true, - language: viewModel.selectedLanguage['code'], - - onLanguage: ()async => await viewModel.navigateToLanguage(), - - ); + language: viewModel.selectedLanguage['code'], + onLanguage: () async => await viewModel.navigateToLanguage(), + ); Widget _buildExpandedBody( {required BuildContext context, @@ -144,13 +152,9 @@ class RegisterWithEmailScreen extends ViewModelWidget { _buildEmailValidatorWrapper(viewModel), ]; - Widget _buildTitle() => const Text( - 'Create an Account', - style: TextStyle( - fontSize: 25, - color: kcDarkGrey, - fontWeight: FontWeight.w600, - ), + Widget _buildTitle() => Text( + LocaleKeys.create_account.tr(), + style: style25DG600, ); Widget _buildSubtitleWrapper(RegisterViewModel viewModel) => LoginAccount( @@ -159,10 +163,10 @@ class RegisterWithEmailScreen extends ViewModelWidget { Widget _buildEmailFormField(RegisterViewModel viewModel) => TextFormField( controller: emailController, - keyboardType: TextInputType.emailAddress, onTap: viewModel.setEmailFocus, + keyboardType: TextInputType.emailAddress, decoration: inputDecoration( - hint: 'Email', + hint: LocaleKeys.email.tr(), focus: viewModel.focusEmail, filled: emailController.text.isNotEmpty), ); @@ -174,11 +178,7 @@ class RegisterWithEmailScreen extends ViewModelWidget { Widget _buildEmailValidator(RegisterViewModel viewModel) => Text( viewModel.emailValidationMessage!, - style: const TextStyle( - fontSize: 12, - color: Colors.red, - fontWeight: FontWeight.w700, - ), + style: style12R700, ); Widget _buildLowerColumn(RegisterViewModel viewModel) => Column( @@ -198,9 +198,9 @@ class RegisterWithEmailScreen extends ViewModelWidget { CustomElevatedButton( height: 55, safe: false, - text: 'Continue', borderRadius: 12, foregroundColor: kcWhite, + text: LocaleKeys.cont.tr(), onTap: emailController.text.isNotEmpty && !viewModel.hasEmailValidationMessage ? () => _addUserData(viewModel) @@ -216,9 +216,9 @@ class RegisterWithEmailScreen extends ViewModelWidget { height: 55, borderRadius: 12, backgroundColor: kcWhite, - text: 'Login with Google', borderColor: kcPrimaryColor, foregroundColor: kcPrimaryColor, + text: LocaleKeys.register_with_google.tr(), leadingImage: 'assets/icons/google.png', onTap: () async => await viewModel.registerWithGoogle(), ); @@ -233,8 +233,8 @@ class RegisterWithEmailScreen extends ViewModelWidget { leadingIcon: Icons.phone, borderColor: kcPrimaryColor, foregroundColor: kcPrimaryColor, - text: 'Register with Phone Number', onTap: () => viewModel.goTo(page: 1), + text: LocaleKeys.register_with_phone.tr(), ); Widget _buildRegisterWithEmailState(RegisterViewModel viewModel) => diff --git a/lib/ui/views/register/screens/register_with_phone_number_screen.dart b/lib/ui/views/register/screens/register_with_phone_number_screen.dart index f2cc333..e90398b 100644 --- a/lib/ui/views/register/screens/register_with_phone_number_screen.dart +++ b/lib/ui/views/register/screens/register_with_phone_number_screen.dart @@ -1,6 +1,8 @@ +import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:stacked/stacked.dart'; +import 'package:yimaru_app/ui/common/translations/locale_keys.g.dart'; import 'package:yimaru_app/ui/widgets/login_account.dart'; import 'package:yimaru_app/ui/widgets/option_text_divider.dart'; @@ -49,7 +51,15 @@ class RegisterWithPhoneNumberScreen extends ViewModelWidget { required RegisterViewModel viewModel}) => Scaffold( backgroundColor: kcBackgroundColor, - body: _buildScaffoldStack(context: context, viewModel: viewModel), + body: _buildScaffoldContainer(context: context, viewModel: viewModel), + ); + + Widget _buildScaffoldContainer( + {required BuildContext context, + required RegisterViewModel viewModel}) => + Container( + decoration: bgDecoration, + child: _buildScaffoldStack(context: context, viewModel: viewModel), ); Widget _buildScaffoldStack( @@ -84,11 +94,9 @@ class RegisterWithPhoneNumberScreen extends ViewModelWidget { showBackButton: true, onPop: viewModel.goBack, showLanguageSelection: true, - language: viewModel.selectedLanguage['code'], - - onLanguage: ()async => await viewModel.navigateToLanguage(), - - ); + language: viewModel.selectedLanguage['code'], + onLanguage: () async => await viewModel.navigateToLanguage(), + ); Widget _buildExpandedBody( {required BuildContext context, @@ -152,7 +160,7 @@ class RegisterWithPhoneNumberScreen extends ViewModelWidget { ]; Widget _buildTitle() => Text( - 'Create an Account', + LocaleKeys.create_account.tr(), style: style25DG600, ); @@ -161,7 +169,7 @@ class RegisterWithPhoneNumberScreen extends ViewModelWidget { ); Widget _buildSubtitle() => Text( - 'Enter your phone number. We will send you a confirmation code there', + LocaleKeys.enter_phone_number.tr(), style: style14MG400, ); @@ -221,9 +229,9 @@ class RegisterWithPhoneNumberScreen extends ViewModelWidget { Widget _buildContinueButton(RegisterViewModel viewModel) => CustomElevatedButton( height: 55, - text: 'Continue', borderRadius: 12, foregroundColor: kcWhite, + text: LocaleKeys.cont.tr(), onTap: phoneNumberController.text.isNotEmpty ? () async => await _addUserData(viewModel) : null, @@ -239,9 +247,9 @@ class RegisterWithPhoneNumberScreen extends ViewModelWidget { backgroundColor: kcWhite, leadingIcon: Icons.email, borderColor: kcPrimaryColor, - text: 'Register with Email', foregroundColor: kcPrimaryColor, onTap: () => viewModel.goTo(page: 0), + text: LocaleKeys.register_with_email.tr(), ); Widget _buildRegisterWithPhoneState(RegisterViewModel viewModel) => diff --git a/lib/ui/views/register/screens/registration_otp_screen.dart b/lib/ui/views/register/screens/registration_otp_screen.dart index e5dcecc..2a6f35a 100644 --- a/lib/ui/views/register/screens/registration_otp_screen.dart +++ b/lib/ui/views/register/screens/registration_otp_screen.dart @@ -1,7 +1,9 @@ +import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter_timer_countdown/flutter_timer_countdown.dart'; import 'package:pinput/pinput.dart'; import 'package:stacked/stacked.dart'; +import 'package:yimaru_app/ui/common/translations/locale_keys.g.dart'; import 'package:yimaru_app/ui/views/register/register_viewmodel.dart'; import 'package:yimaru_app/ui/widgets/custom_cursor.dart'; @@ -60,7 +62,15 @@ class RegistrationOtpScreen extends ViewModelWidget { required RegisterViewModel viewModel}) => Scaffold( backgroundColor: kcBackgroundColor, - body: _buildScaffoldStack(context: context, viewModel: viewModel), + body: _buildScaffoldContainer(context: context, viewModel: viewModel), + ); + + Widget _buildScaffoldContainer( + {required BuildContext context, + required RegisterViewModel viewModel}) => + Container( + decoration: bgDecoration, + child: _buildScaffoldStack(context: context, viewModel: viewModel), ); Widget _buildScaffoldStack( @@ -160,7 +170,7 @@ class RegistrationOtpScreen extends ViewModelWidget { ]; Widget _buildTitle() => Text( - 'Verification Code', + LocaleKeys.verification_code.tr(), style: style25DG600, ); @@ -174,7 +184,7 @@ class RegistrationOtpScreen extends ViewModelWidget { : Container(); Widget _buildPhoneSubtitle() => Text( - 'Code sent to your number +251${phoneNumberController.text.substring(0, 5)}****', + '${LocaleKeys.code_sent_to_phone.tr()} +251${phoneNumberController.text.substring(0, 3)}******', softWrap: false, style: style14DG400, ); @@ -183,7 +193,7 @@ class RegistrationOtpScreen extends ViewModelWidget { emailController.text.isNotEmpty ? _buildEmailSubtitle() : Container(); Widget _buildEmailSubtitle() => Text( - 'Code sent to your number email ${emailController.text.substring(0, 3)}****${emailController.text.split('@').last}', + '${LocaleKeys.code_sent_to_email.tr()} ${emailController.text.substring(0, 2)}******${emailController.text.split('@').last}', softWrap: false, style: style14DG400, ); @@ -229,7 +239,7 @@ class RegistrationOtpScreen extends ViewModelWidget { child: _buildResendText()); Widget _buildResendText() => Text( - 'Resend code', + LocaleKeys.resend_code.tr(), style: style14P600.copyWith(fontStyle: FontStyle.italic), ); @@ -241,7 +251,8 @@ class RegistrationOtpScreen extends ViewModelWidget { ], ); - Widget _buildCountdownText() => Text('Resend code in ', style: style14DG400); + Widget _buildCountdownText() => + Text('${LocaleKeys.resend_code_in.tr()} ', style: style14DG400); Widget _buildTimer(RegisterViewModel viewModel) => TimerCountdown( enableDescriptions: false, @@ -260,9 +271,9 @@ class RegistrationOtpScreen extends ViewModelWidget { Widget _buildContinueButton(RegisterViewModel viewModel) => CustomElevatedButton( height: 55, - text: 'Continue', borderRadius: 12, foregroundColor: kcWhite, + text: LocaleKeys.cont.tr(), backgroundColor: otpController.text.length == 6 && !viewModel.hasOtpValidationMessage ? kcPrimaryColor diff --git a/lib/ui/views/startup/startup_view.dart b/lib/ui/views/startup/startup_view.dart index 317e943..d403042 100644 --- a/lib/ui/views/startup/startup_view.dart +++ b/lib/ui/views/startup/startup_view.dart @@ -1,3 +1,4 @@ +import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter/scheduler.dart'; import 'package:flutter_svg/svg.dart'; @@ -7,11 +8,12 @@ import 'package:yimaru_app/ui/widgets/custom_circular_progress_indicator.dart'; import '../../common/app_colors.dart'; import '../../common/enmus.dart'; +import '../../common/translations/locale_keys.g.dart'; import 'startup_viewmodel.dart'; class StartupView extends StackedView { - final String label; - const StartupView({Key? key, this.label = 'Loading'}) : super(key: key); + final String? label; + const StartupView({Key? key, this.label}) : super(key: key); @override Widget builder( @@ -31,7 +33,8 @@ class StartupView extends StackedView { ? _buildStartUpView() : _buildScaffold(); - Widget _buildStartUpView() => const StartupView(label: 'Checking user info'); + Widget _buildStartUpView() => + StartupView(label: LocaleKeys.checking_user_info.tr()); Widget _buildScaffold() => Stack( children: _buildScaffoldChildren(), @@ -78,7 +81,8 @@ class StartupView extends StackedView { _buildIndicatorWrapper(), ]; - Widget _buildLoadingText() => Text('$label ...', style: style16W600); + Widget _buildLoadingText() => + Text('${label ?? LocaleKeys.loading.tr()} ...', style: style16W600); Widget _buildIndicatorWrapper() => SizedBox( width: 16, diff --git a/lib/ui/views/startup/startup_viewmodel.dart b/lib/ui/views/startup/startup_viewmodel.dart index eb9f4a1..ea0abf0 100644 --- a/lib/ui/views/startup/startup_viewmodel.dart +++ b/lib/ui/views/startup/startup_viewmodel.dart @@ -34,7 +34,7 @@ class StartupViewModel extends ReactiveViewModel { final firstTimeInstall = await _authenticationService.isFirstTimeInstall(); if (firstTimeInstall) { - await _navigationService.replaceWithWelcomeView(); + await _navigationService.replaceWithLandingView(); } else { if (loggedIn) { await _authenticationService.getUser(); @@ -56,12 +56,9 @@ class StartupViewModel extends ReactiveViewModel { label: 'Check you internet connection', onTap: () async => await _getProfileStatus()); - - Future replaceWithOnboarding() async => await _navigationService.replaceWithOnboardingView(); - // Remote api calls // Get profile status diff --git a/lib/ui/views/terms_and_conditions/terms_and_conditions_view.dart b/lib/ui/views/terms_and_conditions/terms_and_conditions_view.dart index a739a0c..89357d7 100644 --- a/lib/ui/views/terms_and_conditions/terms_and_conditions_view.dart +++ b/lib/ui/views/terms_and_conditions/terms_and_conditions_view.dart @@ -73,38 +73,12 @@ class TermsAndConditionsView extends StackedView { Widget _buildMenuColumnScrollView(TermsAndConditionsViewModel viewModel) => SingleChildScrollView( - child: _buildContentColumn(), + child: _buildContent(), ); - Widget _buildContentColumn() => Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.start, - children: _buildContentColumnChildren(), - ); - - List _buildContentColumnChildren() => [ - _buildContent(), - verticalSpaceMedium, - // _buildDownloadButtonWrapper(), - ]; - Widget _buildContent() => Html( data: ksTerms, shrinkWrap: true, style: htmlStyle, ); - - Widget _buildDownloadButtonWrapper() => Padding( - padding: const EdgeInsets.only(bottom: 50), - child: _buildDownloadButton(), - ); - - Widget _buildDownloadButton() => const CustomElevatedButton( - height: 55, - borderRadius: 12, - text: 'Download PDF', - leadingIcon: Icons.download, - foregroundColor: kcWhite, - backgroundColor: kcPrimaryColor, - ); } diff --git a/lib/ui/widgets/course_category_card.dart b/lib/ui/widgets/course_category_card.dart index 6adcdb9..fa2b7c1 100644 --- a/lib/ui/widgets/course_category_card.dart +++ b/lib/ui/widgets/course_category_card.dart @@ -2,7 +2,6 @@ import 'package:flutter/material.dart'; import 'package:yimaru_app/ui/common/helper_functions.dart'; import '../common/app_colors.dart'; -import '../common/app_strings.dart'; import '../common/ui_helpers.dart'; import 'custom_elevated_button.dart'; diff --git a/lib/ui/widgets/course_unit_tile.dart b/lib/ui/widgets/course_unit_tile.dart index d5e2943..21351f3 100644 --- a/lib/ui/widgets/course_unit_tile.dart +++ b/lib/ui/widgets/course_unit_tile.dart @@ -1,7 +1,6 @@ import 'package:flutter/material.dart'; import 'package:stacked/stacked.dart'; import 'package:yimaru_app/models/course_unit.dart'; -import 'package:yimaru_app/models/submodule.dart'; import 'package:yimaru_app/ui/common/enmus.dart'; import 'package:yimaru_app/ui/widgets/course_module_tile_small.dart'; import 'package:yimaru_app/ui/widgets/custom_linear_progress_indicator.dart'; diff --git a/lib/ui/widgets/login_account.dart b/lib/ui/widgets/login_account.dart index 4c17a03..a28d7e4 100644 --- a/lib/ui/widgets/login_account.dart +++ b/lib/ui/widgets/login_account.dart @@ -1,6 +1,7 @@ +import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; -import '../common/app_colors.dart'; +import '../common/translations/locale_keys.g.dart'; import '../common/ui_helpers.dart'; class LoginAccount extends StatelessWidget { @@ -18,9 +19,9 @@ class LoginAccount extends StatelessWidget { ], ); - Widget _buildLeadingText() => const Text( - 'Already have an account? ', - style: TextStyle(color: kcMediumGrey), + Widget _buildLeadingText() => Text( + LocaleKeys.already_have_account.tr(), + style: style14MG400, ); Widget _buildRegisterTextButton() => TextButton( @@ -31,8 +32,8 @@ class LoginAccount extends StatelessWidget { child: _buildRegisterText(), ); - Widget _buildRegisterText() => const Text( - 'Login', - style: TextStyle(color: kcPrimaryColor), + Widget _buildRegisterText() => Text( + LocaleKeys.login.tr(), + style: style14P400, ); } diff --git a/lib/ui/widgets/page_loading_indicator.dart b/lib/ui/widgets/page_loading_indicator.dart index e582d57..c93baae 100644 --- a/lib/ui/widgets/page_loading_indicator.dart +++ b/lib/ui/widgets/page_loading_indicator.dart @@ -1,5 +1,7 @@ +import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:yimaru_app/ui/common/app_colors.dart'; +import 'package:yimaru_app/ui/common/translations/locale_keys.g.dart'; import 'package:yimaru_app/ui/common/ui_helpers.dart'; import 'custom_circular_progress_indicator.dart'; @@ -53,8 +55,8 @@ class PageLoadingIndicator extends StatelessWidget { child: CustomCircularProgressIndicator(color: kcPrimaryColor), ); - Widget _buildText() => const Text( - 'Please wait', - style: TextStyle(color: kcPrimaryColor), + Widget _buildText() => Text( + LocaleKeys.please_wait.tr(), + style: style14P400, ); } diff --git a/lib/ui/widgets/privacy_policy_tile.dart b/lib/ui/widgets/privacy_policy_tile.dart index f6529bc..b15f0c7 100644 --- a/lib/ui/widgets/privacy_policy_tile.dart +++ b/lib/ui/widgets/privacy_policy_tile.dart @@ -1,6 +1,7 @@ import 'package:flutter/material.dart'; import 'package:iconsax/iconsax.dart'; import 'package:yimaru_app/ui/common/app_strings.dart'; +import 'package:yimaru_app/ui/common/ui_helpers.dart'; import '../common/app_colors.dart'; @@ -64,17 +65,11 @@ class PrivacyPolicyTile extends StatelessWidget { Widget _buildTitle() => Text( title, - style: const TextStyle( - fontSize: 16, - color: kcDarkGrey, - fontWeight: FontWeight.w600, - ), + style: style16DG600, ); - Widget _buildContent() => const Text( + Widget _buildContent() => Text( ksPrivacyPolicy, - style: TextStyle( - color: kcDarkGrey, - ), + style: style14DG400, ); } diff --git a/lib/ui/widgets/register_for_account.dart b/lib/ui/widgets/register_for_account.dart index 7a403ff..4463122 100644 --- a/lib/ui/widgets/register_for_account.dart +++ b/lib/ui/widgets/register_for_account.dart @@ -2,7 +2,6 @@ import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:yimaru_app/ui/common/translations/locale_keys.g.dart'; -import '../common/app_colors.dart'; import '../common/ui_helpers.dart'; class RegisterForAccount extends StatelessWidget { @@ -20,7 +19,7 @@ class RegisterForAccount extends StatelessWidget { ], ); - Widget _buildLeadingText() => Text( + Widget _buildLeadingText() => Text( '${LocaleKeys.dont_have_account.tr()} ', style: style14MG400, ); @@ -33,8 +32,8 @@ class RegisterForAccount extends StatelessWidget { child: _buildRegisterText(), ); - Widget _buildRegisterText() => Text( - LocaleKeys.register.tr(), - style:style14P400 , + Widget _buildRegisterText() => Text( + LocaleKeys.register.tr(), + style: style14P400, ); } diff --git a/pubspec.yaml b/pubspec.yaml index ce5ce46..e8b045c 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,5 +1,5 @@ name: yimaru_app -version: 0.1.16+18 +version: 0.1.17+19 publish_to: 'none' description: A new Flutter project. diff --git a/test/viewmodels/landing_viewmodel_test.dart b/test/viewmodels/landing_viewmodel_test.dart new file mode 100644 index 0000000..c208a25 --- /dev/null +++ b/test/viewmodels/landing_viewmodel_test.dart @@ -0,0 +1,11 @@ +import 'package:flutter_test/flutter_test.dart'; +import 'package:yimaru_app/app/app.locator.dart'; + +import '../helpers/test_helpers.dart'; + +void main() { + group('LandingViewModel Tests -', () { + setUp(() => registerServices()); + tearDown(() => locator.reset()); + }); +}