fix: Apply Learn UAT comments
This commit is contained in:
parent
5f31135bce
commit
62c895893a
|
|
@ -1,6 +1,7 @@
|
||||||
{
|
{
|
||||||
|
"loading": "በመጫን ላይ",
|
||||||
"welcome_back": "እንኳን በደህና ተመለሱ",
|
"welcome_back": "እንኳን በደህና ተመለሱ",
|
||||||
|
"checking_user_info": "የተጠቃሚ መረጃን በማረጋገጥ ላይ",
|
||||||
"dont_have_account": "መለያ የለዎትም? ይመዝገቡ",
|
"dont_have_account": "መለያ የለዎትም? ይመዝገቡ",
|
||||||
"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 ፊደላት",
|
||||||
|
"password_match": "የይለፍ ቃሉ ተመሳስሏል",
|
||||||
"sign_up_agreement": "‘ይመዝገቡ’ የሚለውን ሲጫኑ በ‘አገልግሎት ውሎች’ እና ‘በግላዊነት ፖሊሲ’ ይስማማሉ።" ,
|
"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": " የይለፍ ቃልን ይቀይሩ ",
|
"reset_password": " የይለፍ ቃልን ይቀይሩ ",
|
||||||
"enter_email_reset_code": "ኢሜይልዎን ያስገቡ። የይለፍ ቃል መለወጫ ኮድ እንልክልዎታለን።" ,
|
"enter_email_reset_code": "ኢሜይልዎን ያስገቡ። የይለፍ ቃል መለወጫ ኮድ እንልክልዎታለን።" ,
|
||||||
"please_wait": "እባክዎ ይጠብቁ",
|
"please_wait": "እባክዎ ይጠብቁ",
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
|
|
||||||
{
|
{"loading": "Loading",
|
||||||
"welcome_back": "Welcome back",
|
"welcome_back": "Welcome back",
|
||||||
|
"checking_user_info": "Checking user info",
|
||||||
"dont_have_account": "Don't have an account? Register",
|
"dont_have_account": "Don't have an account? Register",
|
||||||
"email": "Email",
|
"email": "Email",
|
||||||
"password": "Password",
|
"password": "Password",
|
||||||
|
|
@ -19,7 +20,18 @@
|
||||||
"login_with_email": "Login with email",
|
"login_with_email": "Login with email",
|
||||||
"create_password": "Create password",
|
"create_password": "Create password",
|
||||||
"confirm_password": "Confirm 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’",
|
"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",
|
"reset_password": "Reset Password",
|
||||||
"enter_email_reset_code": "Enter your email. We will send you a reset code.",
|
"enter_email_reset_code": "Enter your email. We will send you a reset code.",
|
||||||
"please_wait": "Please wait",
|
"please_wait": "Please wait",
|
||||||
|
|
|
||||||
|
|
@ -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_catalog/course_catalog_view.dart';
|
||||||
import 'package:yimaru_app/ui/views/course_unit/course_unit_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/services/localization_service.dart';
|
||||||
|
import 'package:yimaru_app/ui/views/landing/landing_view.dart';
|
||||||
// @stacked-import
|
// @stacked-import
|
||||||
|
|
||||||
@StackedApp(
|
@StackedApp(
|
||||||
|
|
@ -100,6 +101,7 @@ import 'package:yimaru_app/services/localization_service.dart';
|
||||||
MaterialRoute(page: ArifPayView),
|
MaterialRoute(page: ArifPayView),
|
||||||
MaterialRoute(page: CourseCatalogView),
|
MaterialRoute(page: CourseCatalogView),
|
||||||
MaterialRoute(page: CourseUnitView),
|
MaterialRoute(page: CourseUnitView),
|
||||||
|
MaterialRoute(page: LandingView),
|
||||||
// @stacked-route
|
// @stacked-route
|
||||||
],
|
],
|
||||||
dependencies: [
|
dependencies: [
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load Diff
|
|
@ -1,4 +1,3 @@
|
||||||
import 'package:flutter_html/flutter_html.dart';
|
|
||||||
import 'package:stacked/stacked.dart';
|
import 'package:stacked/stacked.dart';
|
||||||
import 'package:yimaru_app/app/app.locator.dart';
|
import 'package:yimaru_app/app/app.locator.dart';
|
||||||
import 'package:yimaru_app/models/course_progress.dart';
|
import 'package:yimaru_app/models/course_progress.dart';
|
||||||
|
|
|
||||||
|
|
@ -9,52 +9,299 @@ const String ksCategorySubtitle =
|
||||||
const String ksHomeBottomSheetDescription =
|
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';
|
'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 =
|
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 = """
|
|
||||||
<p style="color:#9C2C91;font-size:13px;">
|
<p style="color:#9C2C91;font-size:13px;">
|
||||||
Last updated: October 26, 2025
|
Last updated: May 12, 2026
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h1>Privacy Policy</h1>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Yimaru Academy App• May 12, 2026
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<h2>Introduction</h2>
|
<h2>Introduction</h2>
|
||||||
<p>
|
<p>
|
||||||
Welcome to Yimaru! These terms and conditions outline the rules and regulations
|
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”).
|
||||||
for the use of our application. By accessing this app, we assume you accept
|
|
||||||
these terms and conditions.
|
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<h2>User Accounts</h2>
|
<h2>Contact Details</h2>
|
||||||
<p>
|
<p>
|
||||||
When you create an account with us, you must provide us with information that is
|
If you have any questions about this Privacy Policy, please contact us:
|
||||||
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.
|
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<h2>Content & Services</h2>
|
|
||||||
<p>
|
<p>
|
||||||
Our Service allows you to access learning materials. You are granted a limited
|
<strong>Yimaru Academy</strong><br>
|
||||||
license to access and use the app content for personal, non-commercial purposes.
|
22 Djibouti St, Addis Ababa, Ethiopia<br>
|
||||||
You agree not to:
|
+251 946396655<br>
|
||||||
|
Email: yimaruacademy@gmail.com
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h2>Consent</h2>
|
||||||
|
<p>
|
||||||
|
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.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h2>Information We Collect</h2>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
When you interact with Yimaru Academy, we may collect the following types of information:
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<ul>
|
<ul>
|
||||||
<li>Reproduce, duplicate, copy, or sell any material from the app.</li>
|
<li><strong>Identity Data:</strong> Full name, username, date of birth, and profile information.</li>
|
||||||
<li>Redistribute content from Yimaru.</li>
|
<li><strong>Contact Data:</strong> Email address, phone number, and billing information.</li>
|
||||||
<li>Use the app in any way that is damaging or harmful.</li>
|
<li><strong>Account & Learning Data:</strong> Lessons accessed, progress, scores, achievements, streaks, and certificates.</li>
|
||||||
|
<li><strong>Voice & AI Interaction Data:</strong> Voice recordings, pronunciation samples, AI chat messages, prompts, and feedback.</li>
|
||||||
|
<li><strong>Usage Data:</strong> App activity, feature usage, and interaction history.</li>
|
||||||
|
<li><strong>Technical Data:</strong> Device type, IP address, OS, app version, language, crash logs, and identifiers.</li>
|
||||||
|
<li><strong>Payment Data:</strong> Subscription and transaction details processed via third-party payment providers.</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<h2>Privacy Policy</h2>
|
|
||||||
<p>
|
<p>
|
||||||
Your privacy is important to us. Please read our
|
We do not intentionally collect sensitive personal data such as health, biometric, religious, or political information unless required by law and with proper consent.
|
||||||
<a href="#">Privacy Policy</a>
|
</p>
|
||||||
to understand how we collect, use, and share information about you.
|
|
||||||
|
<h2>How We Use Your Data</h2>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
We use your personal data for the following purposes:
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<li>To create and manage your account</li>
|
||||||
|
<li>To deliver personalized learning experiences and AI features</li>
|
||||||
|
<li>To communicate updates, alerts, and support messages</li>
|
||||||
|
<li>To process payments and subscriptions</li>
|
||||||
|
<li>To improve app performance and services</li>
|
||||||
|
<li>To detect fraud or misuse</li>
|
||||||
|
<li>To comply with legal obligations</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<h2>Third-Party Links</h2>
|
||||||
|
<p>
|
||||||
|
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.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h2>Cookies</h2>
|
||||||
|
<p>
|
||||||
|
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.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h2>User Profiles</h2>
|
||||||
|
<p>
|
||||||
|
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.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h2>Data Security</h2>
|
||||||
|
<p>
|
||||||
|
We use appropriate technical and organizational measures such as encryption, secure servers, and access controls to protect your data.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
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.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h2>Data Retention</h2>
|
||||||
|
<p>
|
||||||
|
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.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h2>Your Rights</h2>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Under applicable law, you may have the right to:
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<li>Access your personal data</li>
|
||||||
|
<li>Correct inaccurate information</li>
|
||||||
|
<li>Request deletion of your data</li>
|
||||||
|
<li>Restrict or object to processing</li>
|
||||||
|
<li>Request data portability</li>
|
||||||
|
<li>Withdraw consent (via parent/guardian if under 16)</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
To exercise these rights, contact us using the details above. You may also contact the relevant authority if you believe your rights are violated.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h2>Cross-Border Data Transfers</h2>
|
||||||
|
<p>
|
||||||
|
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.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h2>Changes to This Privacy Policy</h2>
|
||||||
|
<p>
|
||||||
|
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.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h2>Disclaimer</h2>
|
||||||
|
<p>
|
||||||
|
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.
|
||||||
|
</p>
|
||||||
|
""";
|
||||||
|
|
||||||
|
const String ksTerms = """
|
||||||
|
<p style="color:#9C2C91;font-size:13px;">
|
||||||
|
Last updated: May 12, 2026
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h1>Terms of Service</h1>
|
||||||
|
<p>
|
||||||
|
Yimaru Academy App
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h2>Introduction</h2>
|
||||||
|
<p>
|
||||||
|
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”).
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
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.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h2>Definitions</h2>
|
||||||
|
<p>
|
||||||
|
“Platform” refers to the Yimaru Academy mobile app, website, and related services.<br>
|
||||||
|
“Content” refers to all lessons, videos, quizzes, exams, AI feedback, and learning materials.<br>
|
||||||
|
“Subscription” refers to paid access plans for premium content and services.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h2>Eligibility</h2>
|
||||||
|
<p>
|
||||||
|
Our services are intended for users who are at least 8 years old.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Users under the age of 16 may require parental or guardian consent under applicable law.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
By using the Platform, you confirm that you meet these eligibility requirements.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h2>Acceptance of Terms</h2>
|
||||||
|
<p>
|
||||||
|
By creating an account, subscribing, or accessing our content, you accept these Terms and our Privacy Policy.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
We may update these Terms from time to time. Continued use of the Platform means you accept the updated version.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h2>Subscription & Fees</h2>
|
||||||
|
<p>
|
||||||
|
Certain features, courses, and English proficiency exam preparation materials require a paid subscription.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Subscription pricing, billing periods, and available plans are displayed on the Platform and may be updated from time to time.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
By purchasing a subscription, you authorize us to charge the applicable fees through your selected payment method.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h2>No Refund Policy</h2>
|
||||||
|
<p>
|
||||||
|
We do not offer refunds once a subscription has been purchased. Please review available content carefully before subscribing.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h2>Use of Service</h2>
|
||||||
|
<p>
|
||||||
|
You agree to use the Platform only for lawful, personal, and educational purposes.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>You must not:</p>
|
||||||
|
<ul>
|
||||||
|
<li>Share your account credentials with others.</li>
|
||||||
|
<li>Copy, reproduce, or distribute our content without written permission.</li>
|
||||||
|
<li>Use the Platform for harmful, abusive, or fraudulent activities.</li>
|
||||||
|
<li>Attempt to access or modify the system in any unauthorized way.</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<h2>Intellectual Property</h2>
|
||||||
|
<p>
|
||||||
|
All content, including lessons, videos, exams, quizzes, AI-generated feedback, and learning materials, is the intellectual property of Yimaru Academy.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
You are granted a limited, non-exclusive, non-transferable license to use the content for personal learning only.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Unauthorized use, resale, or redistribution of our materials is strictly prohibited.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h2>AI-Generated Content Disclaimer</h2>
|
||||||
|
<p>
|
||||||
|
Some features of the Platform may provide AI-generated feedback, recommendations, or learning assistance.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
While we strive for accuracy, AI-generated content may contain errors and should not be considered professional or guaranteed academic advice.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h2>Privacy</h2>
|
||||||
|
<p>
|
||||||
|
Your use of the Platform is also governed by our Privacy Policy, which explains how we collect, use, and protect your information.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h2>Account Security</h2>
|
||||||
|
<p>
|
||||||
|
You are responsible for maintaining the confidentiality of your account credentials.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
If you suspect unauthorized access, contact us immediately at <strong>yimaruacademy@gmail.com</strong>.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
We are not responsible for losses caused by failure to secure your account.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h2>Termination</h2>
|
||||||
|
<p>
|
||||||
|
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.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
After termination, access to the Platform and content may be removed.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h2>Limitation of Liability</h2>
|
||||||
|
<p>
|
||||||
|
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).
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
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.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h2>Governing Law & Jurisdiction</h2>
|
||||||
|
<p>
|
||||||
|
These Terms are governed by the laws of the Federal Democratic Republic of Ethiopia. Any disputes shall be handled under Ethiopian jurisdiction.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h2>Changes to Terms</h2>
|
||||||
|
<p>
|
||||||
|
We may update these Terms from time to time. Users will be notified of major changes through the Platform or email.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Continued use of the Platform means acceptance of the updated Terms.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<h2>Contact Us</h2>
|
<h2>Contact Us</h2>
|
||||||
<p>
|
<p>
|
||||||
If you have any questions about these Terms, please contact us at
|
If you have any questions about these Terms & Conditions, contact us:
|
||||||
<strong>support@yimaru.et</strong>.
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
<strong>Yimaru Academy</strong><br>
|
||||||
|
22 Djibouti St, Addis Ababa, Ethiopia<br>
|
||||||
|
+251 946396655<br>
|
||||||
|
yimaruacademy@gmail.com
|
||||||
</p>
|
</p>
|
||||||
""";
|
""";
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@ import 'dart:ui';
|
||||||
|
|
||||||
import 'package:easy_localization/easy_localization.dart' show AssetLoader;
|
import 'package:easy_localization/easy_localization.dart' show AssetLoader;
|
||||||
|
|
||||||
class CodegenLoader extends AssetLoader{
|
class CodegenLoader extends AssetLoader {
|
||||||
const CodegenLoader();
|
const CodegenLoader();
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
|
@ -14,169 +14,203 @@ class CodegenLoader extends AssetLoader{
|
||||||
return Future.value(mapLocales[locale.toString()]);
|
return Future.value(mapLocales[locale.toString()]);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const Map<String,dynamic> _am = {
|
static const Map<String, dynamic> _am = {
|
||||||
"welcome_back": "እንኳን በደህና ተመለሱ",
|
"loading": "በመጫን ላይ",
|
||||||
"dont_have_account": "መለያ የለዎትም? ይመዝገቡ",
|
"welcome_back": "እንኳን በደህና ተመለሱ",
|
||||||
"email": "ኢሜይል",
|
"checking_user_info": "የተጠቃሚ መረጃን በማረጋገጥ ላይ",
|
||||||
"password": "የይለፍ ቃል",
|
"dont_have_account": "መለያ የለዎትም? ይመዝገቡ",
|
||||||
"forgot_password": "የይለፍ ቃል ረሱ?",
|
"email": "ኢሜይል",
|
||||||
"cont": "ቀጥል",
|
"password": "የይለፍ ቃል",
|
||||||
"register": "ይመዝገቡ",
|
"forgot_password": "የይለፍ ቃል ረሱ?",
|
||||||
"login_with_google": "በጉግል ይግቡ",
|
"cont": "ቀጥል",
|
||||||
"or": "ወይም",
|
"register": "ይመዝገቡ",
|
||||||
"login_with_phone": "በስልክ ቁጥር ይግቡ",
|
"login_with_google": "በጉግል ይግቡ",
|
||||||
"create_account": "አዲስ መለያ ይፍጠሩ",
|
"or": "ወይም",
|
||||||
"already_have_account": "መለያ አለዎት?",
|
"login_with_phone": "በስልክ ቁጥር ይግቡ",
|
||||||
"login": " ይግቡ ",
|
"create_account": "አዲስ መለያ ይፍጠሩ",
|
||||||
"register_with_google": "በጉግል ይመዝገቡ",
|
"already_have_account": "መለያ አለዎት?",
|
||||||
"register_with_phone": "በስልክ ቁጥር ይመዝገቡ",
|
"login": " ይግቡ ",
|
||||||
"enter_phone_number": "የስልክ ቁጥርዎን ያስገቡ። የማረጋገጫ ኮድ እንልክልዎታለን።",
|
"register_with_google": "በጉግል ይመዝገቡ",
|
||||||
"login_with_email": "በኢሜይል ይግቡ",
|
"register_with_phone": "በስልክ ቁጥር ይመዝገቡ",
|
||||||
"create_password": "የይለፍ ቃል ይፍጠሩ",
|
"enter_phone_number": "የስልክ ቁጥርዎን ያስገቡ። የማረጋገጫ ኮድ እንልክልዎታለን።",
|
||||||
"confirm_password": "የይለፍ ቃል ያረጋግጡ",
|
"login_with_email": "በኢሜይል ይግቡ",
|
||||||
"sign_up_agreement": "‘ይመዝገቡ’ የሚለውን ሲጫኑ በ‘አገልግሎት ውሎች’ እና ‘በግላዊነት ፖሊሲ’ ይስማማሉ።",
|
"create_password": "የይለፍ ቃል ይፍጠሩ",
|
||||||
"reset_password": " የይለፍ ቃልን ይቀይሩ ",
|
"confirm_password": "የይለፍ ቃል ያረጋግጡ",
|
||||||
"enter_email_reset_code": "ኢሜይልዎን ያስገቡ። የይለፍ ቃል መለወጫ ኮድ እንልክልዎታለን።",
|
"eight_character_minimum": "ቢያንስ 8 ፊደላት",
|
||||||
"please_wait": "እባክዎ ይጠብቁ",
|
"password_match": "የይለፍ ቃሉ ተመሳስሏል",
|
||||||
"reset_code_sent": "የመቀየሪያ ኮድ በተሳካ ሁኔታ ተልኳል",
|
"sign_up_agreement":
|
||||||
"reset_code": " የመቀየሪያ ኮድ ",
|
"‘ይመዝገቡ’ የሚለውን ሲጫኑ በ‘አገልግሎት ውሎች’ እና ‘በግላዊነት ፖሊሲ’ ይስማማሉ።",
|
||||||
"new_password": "አዲስ የይለፍ ቃል",
|
"terms_of_services": "የአገልግሎት ውሎች",
|
||||||
"logged_in_successfully": "በተሳካ ሁኔታ ገብተዋል",
|
"and": "እና",
|
||||||
"view_course": " ኮርሱን ይመልከቱ ",
|
"privacy_policy": "የግላዊነት ፖሊሲ",
|
||||||
"take_practice": " ልምምድ ያድርጉ ",
|
"register_with_email": "በኢሜል ይመዝገቡ",
|
||||||
"your_current_level": "የአሁኑ ደረጃዎ",
|
"verification_code": "የማረጋገጫ ኮድ",
|
||||||
"overall_progress": "አጠቃላይ እድገት",
|
"resend_code": "ኮዱን እንደገና ላክ",
|
||||||
"great_work": "በርቱ! በጣም ጥሩ እየሰሩ ነው ",
|
"code_sent_to_phone": "ኮዱ ወደ ስልክ ቁጥርዎ ተልኳል",
|
||||||
"view_module": "ሞጁሉን ይመልከቱ",
|
"code_sent_to_email": "ኮዱ ወደ ኢሜል ተልኳል",
|
||||||
"progress": "እድገት",
|
"resend_code_in": "ኮዱን እንደገና ለመላክ የቀረው ጊዜ",
|
||||||
"keep_going": " ይቀጥሉ - ከግማሽ በላይ ጨርሰዋል ",
|
"reset_password": " የይለፍ ቃልን ይቀይሩ ",
|
||||||
"lessons_in_module": " በዚህ ሞጁል ውስጥ ያሉ ትምህርቶች ",
|
"enter_email_reset_code": "ኢሜይልዎን ያስገቡ። የይለፍ ቃል መለወጫ ኮድ እንልክልዎታለን።",
|
||||||
"practice": "ልምምድ",
|
"please_wait": "እባክዎ ይጠብቁ",
|
||||||
"start": "ጀምር",
|
"reset_code_sent": "የመቀየሪያ ኮድ በተሳካ ሁኔታ ተልኳል",
|
||||||
"in_progress": "በሂደት ላይ",
|
"reset_code": " የመቀየሪያ ኮድ ",
|
||||||
"hello": "ሰላም",
|
"new_password": "አዲስ የይለፍ ቃል",
|
||||||
"ready_to_learn": " ዛሬ እንግሊዝኛ ለመማር ተዘጋጅተዋል? ",
|
"logged_in_successfully": "በተሳካ ሁኔታ ገብተዋል",
|
||||||
"learn": "ይማሩ ",
|
"view_course": " ኮርሱን ይመልከቱ ",
|
||||||
"course": "ኮርስ",
|
"take_practice": " ልምምድ ያድርጉ ",
|
||||||
"profile": " ፕሮፋይል ",
|
"your_current_level": "የአሁኑ ደረጃዎ",
|
||||||
"speaking_partner": "የንግግር ጓደኛ ",
|
"overall_progress": "አጠቃላይ እድገት",
|
||||||
"practice_what_you_learned": "አሁን የተማሩትን እንለማመድ",
|
"great_work": "በርቱ! በጣም ጥሩ እየሰሩ ነው ",
|
||||||
"practice_questions": "ጥቂት ጥያቄዎችን እጠይቃለሁ እና መልስ መስጠት ይችላሉ",
|
"view_module": "ሞጁሉን ይመልከቱ",
|
||||||
"start_practice": "ልምምድ ጀምር",
|
"progress": "እድገት",
|
||||||
"almost_there": "ሊጨርሱ ተቃርበዋል",
|
"keep_going": " ይቀጥሉ - ከግማሽ በላይ ጨርሰዋል ",
|
||||||
"finish_session": "እድገትዎን ለማየት ክፍለ ጊዜውን ያጠናቅቁ",
|
"lessons_in_module": " በዚህ ሞጁል ውስጥ ያሉ ትምህርቶች ",
|
||||||
"continue_practice": "ልምምዱን ይቀጥሉ",
|
"practice": "ልምምድ",
|
||||||
"end_session": "ክፍለ ጊዜውን ያብቁ ",
|
"start": "ጀምር",
|
||||||
"tap_start_to_listen": "ለማዳመጥ የጀምር ቁልፉን ይጫኑ",
|
"in_progress": "በሂደት ላይ",
|
||||||
"practice_speaking": "ንግግርን ይለማመዱ ",
|
"hello": "ሰላም",
|
||||||
"tap_microphone": "ለመናገር ማይክሮፎኑን ይጫኑ",
|
"ready_to_learn": " ዛሬ እንግሊዝኛ ለመማር ተዘጋጅተዋል? ",
|
||||||
"reply": "እንደገና አዳምጥ",
|
"learn": "ይማሩ ",
|
||||||
"cancel": "ይቅር",
|
"course": "ኮርስ",
|
||||||
"you_are_speaking": "እየተናገሩ ነው",
|
"profile": " ፕሮፋይል ",
|
||||||
"practice_completed": "ልምምዱ ተጠናቅቋል",
|
"speaking_partner": "የንግግር ጓደኛ ",
|
||||||
"great_improvement": "በዚህኛው በራስ መተማመንዎ ጨምሯል፤ ትልቅ መሻሻል ነው",
|
"practice_what_you_learned": "አሁን የተማሩትን እንለማመድ",
|
||||||
"practice_again": "እንደገና ይለማመዱ",
|
"practice_questions": "ጥቂት ጥያቄዎችን እጠይቃለሁ እና መልስ መስጠት ይችላሉ",
|
||||||
"conversation_review": "የንግግር ግምገማ ",
|
"start_practice": "ልምምድ ጀምር",
|
||||||
"result": "ውጤት",
|
"almost_there": "ሊጨርሱ ተቃርበዋል",
|
||||||
"quick_tip": "ጠቃሚ ምክር",
|
"finish_session": "እድገትዎን ለማየት ክፍለ ጊዜውን ያጠናቅቁ",
|
||||||
"retry": "እንደገና ይሞክሩ",
|
"continue_practice": "ልምምዱን ይቀጥሉ",
|
||||||
"completed_a1": "እንኳን ደስ አለዎት! A1 ደረጃን አጠናቅቀዋል",
|
"end_session": "ክፍለ ጊዜውን ያብቁ ",
|
||||||
"analyzing_speaking": "የንግግር ችሎታዎን እየገመገምን ነው",
|
"tap_start_to_listen": "ለማዳመጥ የጀምር ቁልፉን ይጫኑ",
|
||||||
"view_profile": "ፕሮፋይሎን ይመልከቱ ",
|
"practice_speaking": "ንግግርን ይለማመዱ ",
|
||||||
"hi": "ሰላም",
|
"tap_microphone": "ለመናገር ማይክሮፎኑን ይጫኑ",
|
||||||
"edit_profile": "መገለጫ ያስተካክሉ",
|
"reply": "እንደገና አዳምጥ",
|
||||||
"first_name": "የመጀመሪያ ስም",
|
"cancel": "ይቅር",
|
||||||
"last_name": "የአባት ስም",
|
"you_are_speaking": "እየተናገሩ ነው",
|
||||||
"gender": "ፆታ",
|
"practice_completed": "ልምምዱ ተጠናቅቋል",
|
||||||
"male": "ወንድ",
|
"great_improvement": "በዚህኛው በራስ መተማመንዎ ጨምሯል፤ ትልቅ መሻሻል ነው",
|
||||||
"female": "ሴት",
|
"practice_again": "እንደገና ይለማመዱ",
|
||||||
"phone_number": "የስልክ ቁጥር",
|
"conversation_review": "የንግግር ግምገማ ",
|
||||||
"country": "ሀገር",
|
"result": "ውጤት",
|
||||||
"region": "ክልል",
|
"quick_tip": "ጠቃሚ ምክር",
|
||||||
"occupation": "የስራ መስክ ",
|
"retry": "እንደገና ይሞክሩ",
|
||||||
"save_changes": "ለውጦችን ያስቀምጡ"
|
"completed_a1": "እንኳን ደስ አለዎት! A1 ደረጃን አጠናቅቀዋል",
|
||||||
};
|
"analyzing_speaking": "የንግግር ችሎታዎን እየገመገምን ነው",
|
||||||
static const Map<String,dynamic> _en = {
|
"view_profile": "ፕሮፋይሎን ይመልከቱ ",
|
||||||
"welcome_back": "Welcome back",
|
"hi": "ሰላም",
|
||||||
"dont_have_account": "Don't have an account? Register",
|
"edit_profile": "መገለጫ ያስተካክሉ",
|
||||||
"email": "Email",
|
"first_name": "የመጀመሪያ ስም",
|
||||||
"password": "Password",
|
"last_name": "የአባት ስም",
|
||||||
"forgot_password": "Forgot password?",
|
"gender": "ፆታ",
|
||||||
"cont": "Continue",
|
"male": "ወንድ",
|
||||||
"register": "Register",
|
"female": "ሴት",
|
||||||
"login_with_google": "Login with Google",
|
"phone_number": "የስልክ ቁጥር",
|
||||||
"or": "Or",
|
"country": "ሀገር",
|
||||||
"login_with_phone": "Login with phone number",
|
"region": "ክልል",
|
||||||
"create_account": "Create an account",
|
"occupation": "የስራ መስክ ",
|
||||||
"already_have_account": "Already have an account?",
|
"save_changes": "ለውጦችን ያስቀምጡ"
|
||||||
"login": "Login",
|
};
|
||||||
"register_with_google": "Register with Google",
|
static const Map<String, dynamic> _en = {
|
||||||
"register_with_phone": "Register with phone number",
|
"loading": "Loading",
|
||||||
"enter_phone_number": "Enter your phone number. We will send you a confirmation code there.",
|
"welcome_back": "Welcome back",
|
||||||
"login_with_email": "Login with email",
|
"checking_user_info": "Checking user info",
|
||||||
"create_password": "Create password",
|
"dont_have_account": "Don't have an account? Register",
|
||||||
"confirm_password": "Confirm password",
|
"email": "Email",
|
||||||
"sign_up_agreement": "By clicking ‘Sign Up’, you agree to our ‘Terms of Service’ and ‘Privacy Policy’",
|
"password": "Password",
|
||||||
"reset_password": "Reset Password",
|
"forgot_password": "Forgot password?",
|
||||||
"enter_email_reset_code": "Enter your email. We will send you a reset code.",
|
"cont": "Continue",
|
||||||
"please_wait": "Please wait",
|
"register": "Register",
|
||||||
"reset_code_sent": "Reset code sent successfully",
|
"login_with_google": "Login with Google",
|
||||||
"reset_code": "Reset code",
|
"or": "Or",
|
||||||
"new_password": "New password",
|
"login_with_phone": "Login with phone number",
|
||||||
"logged_in_successfully": "Logged in successfully",
|
"create_account": "Create an account",
|
||||||
"view_course": "View course",
|
"already_have_account": "Already have an account?",
|
||||||
"take_practice": "Take practice",
|
"login": "Login",
|
||||||
"your_current_level": "Your current level",
|
"register_with_google": "Register with Google",
|
||||||
"overall_progress": "Overall progress",
|
"register_with_phone": "Register with phone number",
|
||||||
"great_work": "Keep up the great work! You're doing amazing",
|
"enter_phone_number":
|
||||||
"view_module": "View module",
|
"Enter your phone number. We will send you a confirmation code there.",
|
||||||
"progress": "Progress",
|
"login_with_email": "Login with email",
|
||||||
"keep_going": "Let's keep going - you're more than half there",
|
"create_password": "Create password",
|
||||||
"lessons_in_module": "Lessons in this module",
|
"confirm_password": "Confirm password",
|
||||||
"practice": "Practice",
|
"eight_character_minimum": "8 characters minimum",
|
||||||
"start": "Start",
|
"password_math": "password match",
|
||||||
"in_progress": "In Progress",
|
"sign_up_agreement":
|
||||||
"hello": "Hello",
|
"By clicking ‘Sign Up’, you agree to our ‘Terms of Service’ and ‘Privacy Policy’",
|
||||||
"ready_to_learn": "Ready to keep learning English today",
|
"terms_of_services": "Terms of Service",
|
||||||
"learn": "Learn",
|
"and": "and",
|
||||||
"course": "Course",
|
"privacy_policy": "Privacy Policy",
|
||||||
"profile": "Profile",
|
"register_with_email": "Register with email",
|
||||||
"speaking_partner": "Speaking partner",
|
"verification_code": "Verification Code",
|
||||||
"practice_what_you_learned": "Let's practice what you just learnt",
|
"resend_code": "Resend Code",
|
||||||
"practice_questions": "I will ask you a few questions and you can respond",
|
"code_sent_to_phone": "Code sent to your number",
|
||||||
"start_practice": "Start practice",
|
"code_sent_to_email": "Code sent to your email",
|
||||||
"almost_there": "You're almost there",
|
"resend_code_in": "Resend code in",
|
||||||
"finish_session": "Finish the session to see your progress",
|
"reset_password": "Reset Password",
|
||||||
"continue_practice": "Continue practice",
|
"enter_email_reset_code":
|
||||||
"end_session": "End session",
|
"Enter your email. We will send you a reset code.",
|
||||||
"tap_start_to_listen": "Tap the start button to listen",
|
"please_wait": "Please wait",
|
||||||
"practice_speaking": "Practice speaking",
|
"reset_code_sent": "Reset code sent successfully",
|
||||||
"tap_microphone": "Tap the microphone to speak",
|
"reset_code": "Reset code",
|
||||||
"reply": "Reply",
|
"new_password": "New password",
|
||||||
"cancel": "Cancel",
|
"logged_in_successfully": "Logged in successfully",
|
||||||
"you_are_speaking": "You're speaking",
|
"view_course": "View course",
|
||||||
"practice_completed": "Practice completed",
|
"take_practice": "Take practice",
|
||||||
"great_improvement": "You sound more confident this time, great improvement",
|
"your_current_level": "Your current level",
|
||||||
"practice_again": "Practice again",
|
"overall_progress": "Overall progress",
|
||||||
"conversation_review": "Conversation review",
|
"great_work": "Keep up the great work! You're doing amazing",
|
||||||
"result": "Result",
|
"view_module": "View module",
|
||||||
"quick_tip": "Quick tip",
|
"progress": "Progress",
|
||||||
"retry": "Retry",
|
"keep_going": "Let's keep going - you're more than half there",
|
||||||
"completed_a1": "Yay, you've completed A1",
|
"lessons_in_module": "Lessons in this module",
|
||||||
"analyzing_speaking": "We're now analyzing your speaking skill",
|
"practice": "Practice",
|
||||||
"view_profile": "View profile",
|
"start": "Start",
|
||||||
"hi": "Hi",
|
"in_progress": "In Progress",
|
||||||
"edit_profile": "Edit profile",
|
"hello": "Hello",
|
||||||
"first_name": "First name",
|
"ready_to_learn": "Ready to keep learning English today",
|
||||||
"last_name": "Last name",
|
"learn": "Learn",
|
||||||
"gender": "Gender",
|
"course": "Course",
|
||||||
"male": "Male",
|
"profile": "Profile",
|
||||||
"female": "Female",
|
"speaking_partner": "Speaking partner",
|
||||||
"phone_number": "Phone number",
|
"practice_what_you_learned": "Let's practice what you just learnt",
|
||||||
"country": "Country",
|
"practice_questions": "I will ask you a few questions and you can respond",
|
||||||
"region": "Region",
|
"start_practice": "Start practice",
|
||||||
"occupation": "Occupation",
|
"almost_there": "You're almost there",
|
||||||
"save_changes": "Save changes"
|
"finish_session": "Finish the session to see your progress",
|
||||||
};
|
"continue_practice": "Continue practice",
|
||||||
static const Map<String, Map<String,dynamic>> mapLocales = {"am": _am, "en": _en};
|
"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<String, Map<String, dynamic>> mapLocales = {
|
||||||
|
"am": _am,
|
||||||
|
"en": _en
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,8 +2,10 @@
|
||||||
|
|
||||||
// ignore_for_file: constant_identifier_names
|
// ignore_for_file: constant_identifier_names
|
||||||
|
|
||||||
abstract class LocaleKeys {
|
abstract class LocaleKeys {
|
||||||
|
static const loading = 'loading';
|
||||||
static const welcome_back = 'welcome_back';
|
static const welcome_back = 'welcome_back';
|
||||||
|
static const checking_user_info = 'checking_user_info';
|
||||||
static const dont_have_account = 'dont_have_account';
|
static const dont_have_account = 'dont_have_account';
|
||||||
static const email = 'email';
|
static const email = 'email';
|
||||||
static const password = 'password';
|
static const password = 'password';
|
||||||
|
|
@ -22,7 +24,18 @@ abstract class LocaleKeys {
|
||||||
static const login_with_email = 'login_with_email';
|
static const login_with_email = 'login_with_email';
|
||||||
static const create_password = 'create_password';
|
static const create_password = 'create_password';
|
||||||
static const confirm_password = 'confirm_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 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 reset_password = 'reset_password';
|
||||||
static const enter_email_reset_code = 'enter_email_reset_code';
|
static const enter_email_reset_code = 'enter_email_reset_code';
|
||||||
static const please_wait = 'please_wait';
|
static const please_wait = 'please_wait';
|
||||||
|
|
@ -81,5 +94,4 @@ abstract class LocaleKeys {
|
||||||
static const region = 'region';
|
static const region = 'region';
|
||||||
static const occupation = 'occupation';
|
static const occupation = 'occupation';
|
||||||
static const save_changes = 'save_changes';
|
static const save_changes = 'save_changes';
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -100,6 +100,12 @@ double getResponsiveFontSize(
|
||||||
return responsiveSize;
|
return responsiveSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BoxDecoration bgDecoration = const BoxDecoration(
|
||||||
|
image: DecorationImage(
|
||||||
|
image: AssetImage('assets/images/pattern.png'),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
InputDecoration inputDecoration(
|
InputDecoration inputDecoration(
|
||||||
{String? hint,
|
{String? hint,
|
||||||
Widget? suffix,
|
Widget? suffix,
|
||||||
|
|
@ -191,6 +197,13 @@ TextStyle style18W600 = const TextStyle(
|
||||||
fontWeight: FontWeight.w600,
|
fontWeight: FontWeight.w600,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
TextStyle style25W400 = const TextStyle(
|
||||||
|
fontSize: 25,
|
||||||
|
color: kcWhite,
|
||||||
|
fontWeight: FontWeight.w400
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
TextStyle style25W600 = const TextStyle(
|
TextStyle style25W600 = const TextStyle(
|
||||||
fontSize: 25,
|
fontSize: 25,
|
||||||
color: kcWhite,
|
color: kcWhite,
|
||||||
|
|
@ -238,6 +251,12 @@ TextStyle style25P600 = const TextStyle(
|
||||||
fontWeight: FontWeight.w600,
|
fontWeight: FontWeight.w600,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
TextStyle style25P400 = const TextStyle(
|
||||||
|
fontSize: 25,
|
||||||
|
color: kcPrimaryColor,
|
||||||
|
fontWeight: FontWeight.w400,
|
||||||
|
);
|
||||||
|
|
||||||
TextStyle style40P900 = const TextStyle(
|
TextStyle style40P900 = const TextStyle(
|
||||||
fontSize: 40,
|
fontSize: 40,
|
||||||
color: kcPrimaryColor,
|
color: kcPrimaryColor,
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,11 @@
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_inappwebview/flutter_inappwebview.dart';
|
import 'package:flutter_inappwebview/flutter_inappwebview.dart';
|
||||||
import 'package:stacked/stacked.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/app_constants.dart';
|
||||||
import 'package:yimaru_app/ui/common/enmus.dart';
|
import 'package:yimaru_app/ui/common/enmus.dart';
|
||||||
import 'package:yimaru_app/ui/common/ui_helpers.dart';
|
import 'package:yimaru_app/ui/common/ui_helpers.dart';
|
||||||
import 'package:yimaru_app/ui/widgets/page_loading_indicator.dart';
|
import 'package:yimaru_app/ui/widgets/page_loading_indicator.dart';
|
||||||
|
|
||||||
import '../../../models/learn_subscription_request.dart';
|
|
||||||
import 'arif_pay_viewmodel.dart';
|
import 'arif_pay_viewmodel.dart';
|
||||||
|
|
||||||
class ArifPayView extends StackedView<ArifPayViewModel> {
|
class ArifPayView extends StackedView<ArifPayViewModel> {
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,8 @@ class AssessmentViewModel extends ReactiveViewModel {
|
||||||
List<ListenableServiceMixin> get listenableServices => [_localizationService];
|
List<ListenableServiceMixin> get listenableServices => [_localizationService];
|
||||||
|
|
||||||
// Languages
|
// Languages
|
||||||
Map<String, dynamic> get _selectedLanguage => _localizationService.selectedLanguage;
|
Map<String, dynamic> get _selectedLanguage =>
|
||||||
|
_localizationService.selectedLanguage;
|
||||||
|
|
||||||
Map<String, dynamic> get selectedLanguage => _selectedLanguage;
|
Map<String, dynamic> get selectedLanguage => _selectedLanguage;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -67,8 +67,8 @@ class AssessmentIntroScreen extends ViewModelWidget<AssessmentViewModel> {
|
||||||
showBackButton: true,
|
showBackButton: true,
|
||||||
onPop: viewModel.goBack,
|
onPop: viewModel.goBack,
|
||||||
showLanguageSelection: true,
|
showLanguageSelection: true,
|
||||||
language: viewModel.selectedLanguage['code'],
|
language: viewModel.selectedLanguage['code'],
|
||||||
onLanguage: () async => await viewModel.navigateToLanguage(),
|
onLanguage: () async => await viewModel.navigateToLanguage(),
|
||||||
);
|
);
|
||||||
|
|
||||||
Widget _buildTitle() => Text(
|
Widget _buildTitle() => Text(
|
||||||
|
|
|
||||||
|
|
@ -35,9 +35,8 @@ class AssessmentResultScreen extends ViewModelWidget<AssessmentViewModel> {
|
||||||
showBackButton: true,
|
showBackButton: true,
|
||||||
onPop: viewModel.goBack,
|
onPop: viewModel.goBack,
|
||||||
showLanguageSelection: true,
|
showLanguageSelection: true,
|
||||||
language: viewModel.selectedLanguage['code'],
|
language: viewModel.selectedLanguage['code'],
|
||||||
|
onLanguage: () async => await viewModel.navigateToLanguage(),
|
||||||
onLanguage: () async => await viewModel.navigateToLanguage(),
|
|
||||||
);
|
);
|
||||||
|
|
||||||
Widget _buildExpandedBody(AssessmentViewModel viewModel) =>
|
Widget _buildExpandedBody(AssessmentViewModel viewModel) =>
|
||||||
|
|
|
||||||
|
|
@ -1,16 +1,10 @@
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:stacked/stacked.dart';
|
import 'package:stacked/stacked.dart';
|
||||||
|
|
||||||
import '../../../models/course_detail.dart';
|
|
||||||
import '../../../models/course_catalog.dart';
|
|
||||||
import '../../common/app_colors.dart';
|
import '../../common/app_colors.dart';
|
||||||
import '../../common/enmus.dart';
|
|
||||||
import '../../common/ui_helpers.dart';
|
import '../../common/ui_helpers.dart';
|
||||||
import '../../widgets/course_category_card.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/profile_app_bar.dart';
|
||||||
import '../../widgets/small_app_bar.dart';
|
|
||||||
import 'course_viewmodel.dart';
|
import 'course_viewmodel.dart';
|
||||||
|
|
||||||
class CourseView extends StackedView<CourseViewModel> {
|
class CourseView extends StackedView<CourseViewModel> {
|
||||||
|
|
|
||||||
|
|
@ -3,13 +3,8 @@ import 'package:stacked_services/stacked_services.dart';
|
||||||
|
|
||||||
import '../../../app/app.locator.dart';
|
import '../../../app/app.locator.dart';
|
||||||
import '../../../app/app.router.dart';
|
import '../../../app/app.router.dart';
|
||||||
import '../../../models/course.dart';
|
|
||||||
import '../../../models/course_detail.dart';
|
|
||||||
import '../../../models/user.dart';
|
import '../../../models/user.dart';
|
||||||
import '../../../services/authentication_service.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 {
|
class CourseViewModel extends ReactiveViewModel {
|
||||||
// Dependency injection
|
// Dependency injection
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,6 @@ import 'package:yimaru_app/models/course_catalog.dart';
|
||||||
|
|
||||||
import '../../../app/app.locator.dart';
|
import '../../../app/app.locator.dart';
|
||||||
import '../../../app/app.router.dart';
|
import '../../../app/app.router.dart';
|
||||||
import '../../../services/api_service.dart';
|
|
||||||
import '../../../services/course_service.dart';
|
import '../../../services/course_service.dart';
|
||||||
import '../../../services/status_checker_service.dart';
|
import '../../../services/status_checker_service.dart';
|
||||||
import '../../common/enmus.dart';
|
import '../../common/enmus.dart';
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,6 @@ import 'package:stacked/stacked.dart';
|
||||||
import 'package:stacked_services/stacked_services.dart';
|
import 'package:stacked_services/stacked_services.dart';
|
||||||
|
|
||||||
import '../../../app/app.locator.dart';
|
import '../../../app/app.locator.dart';
|
||||||
import '../../../app/app.router.dart';
|
|
||||||
import '../../../models/option.dart';
|
import '../../../models/option.dart';
|
||||||
import '../../../models/assessment_question.dart';
|
import '../../../models/assessment_question.dart';
|
||||||
import '../../../services/api_service.dart';
|
import '../../../services/api_service.dart';
|
||||||
|
|
@ -154,8 +153,6 @@ class CoursePracticeQuestionViewModel extends FormViewModel {
|
||||||
// Navigation
|
// Navigation
|
||||||
void pop() => _navigationService.back();
|
void pop() => _navigationService.back();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Remote api call
|
// Remote api call
|
||||||
|
|
||||||
// Question navigation
|
// Question navigation
|
||||||
|
|
|
||||||
|
|
@ -44,8 +44,7 @@ class QuestionLoadingScreen extends StatelessWidget {
|
||||||
onPop: onPop,
|
onPop: onPop,
|
||||||
showBackButton: true,
|
showBackButton: true,
|
||||||
showLanguageSelection: false,
|
showLanguageSelection: false,
|
||||||
|
);
|
||||||
);
|
|
||||||
|
|
||||||
Widget _buildBody() => Expanded(child: Container());
|
Widget _buildBody() => Expanded(child: Container());
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,8 @@
|
||||||
import 'package:stacked/stacked.dart';
|
import 'package:stacked/stacked.dart';
|
||||||
import 'package:stacked_services/stacked_services.dart';
|
import 'package:stacked_services/stacked_services.dart';
|
||||||
import 'package:yimaru_app/models/course_module.dart';
|
|
||||||
|
|
||||||
import '../../../app/app.locator.dart';
|
import '../../../app/app.locator.dart';
|
||||||
import '../../../models/course_unit.dart';
|
import '../../../models/course_unit.dart';
|
||||||
import '../../../services/api_service.dart';
|
|
||||||
import '../../../services/course_service.dart';
|
import '../../../services/course_service.dart';
|
||||||
import '../../../services/status_checker_service.dart';
|
import '../../../services/status_checker_service.dart';
|
||||||
import '../../common/enmus.dart';
|
import '../../common/enmus.dart';
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,8 @@ class ForgetPasswordViewModel extends ReactiveViewModel
|
||||||
List<ListenableServiceMixin> get listenableServices => [_localizationService];
|
List<ListenableServiceMixin> get listenableServices => [_localizationService];
|
||||||
|
|
||||||
// Languages
|
// Languages
|
||||||
Map<String, dynamic> get _selectedLanguage => _localizationService.selectedLanguage;
|
Map<String, dynamic> get _selectedLanguage =>
|
||||||
|
_localizationService.selectedLanguage;
|
||||||
|
|
||||||
Map<String, dynamic> get selectedLanguage => _selectedLanguage;
|
Map<String, dynamic> get selectedLanguage => _selectedLanguage;
|
||||||
|
|
||||||
|
|
@ -181,7 +182,6 @@ class ForgetPasswordViewModel extends ReactiveViewModel
|
||||||
Future<void> navigateToLanguage() async =>
|
Future<void> navigateToLanguage() async =>
|
||||||
await _navigationService.navigateToLanguageView();
|
await _navigationService.navigateToLanguageView();
|
||||||
|
|
||||||
|
|
||||||
Future<void> replaceWithLogin() async =>
|
Future<void> replaceWithLogin() async =>
|
||||||
await _navigationService.clearStackAndShow(Routes.loginView);
|
await _navigationService.clearStackAndShow(Routes.loginView);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -53,7 +53,15 @@ class RequestCodeScreen extends ViewModelWidget<ForgetPasswordViewModel> {
|
||||||
required ForgetPasswordViewModel viewModel}) =>
|
required ForgetPasswordViewModel viewModel}) =>
|
||||||
Scaffold(
|
Scaffold(
|
||||||
backgroundColor: kcBackgroundColor,
|
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(
|
Widget _buildScaffoldStack(
|
||||||
|
|
@ -88,11 +96,9 @@ class RequestCodeScreen extends ViewModelWidget<ForgetPasswordViewModel> {
|
||||||
showBackButton: true,
|
showBackButton: true,
|
||||||
showLanguageSelection: true,
|
showLanguageSelection: true,
|
||||||
onPop: () => _inAppPop(viewModel),
|
onPop: () => _inAppPop(viewModel),
|
||||||
language: viewModel.selectedLanguage['code'],
|
language: viewModel.selectedLanguage['code'],
|
||||||
|
onLanguage: () async => await viewModel.navigateToLanguage(),
|
||||||
onLanguage: ()async => await viewModel.navigateToLanguage(),
|
);
|
||||||
|
|
||||||
);
|
|
||||||
|
|
||||||
Widget _buildExpandedBody(
|
Widget _buildExpandedBody(
|
||||||
{required BuildContext context,
|
{required BuildContext context,
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,10 @@
|
||||||
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:stacked/stacked.dart';
|
import 'package:stacked/stacked.dart';
|
||||||
|
|
||||||
import '../../../common/app_colors.dart';
|
import '../../../common/app_colors.dart';
|
||||||
import '../../../common/enmus.dart';
|
import '../../../common/enmus.dart';
|
||||||
|
import '../../../common/translations/locale_keys.g.dart';
|
||||||
import '../../../common/ui_helpers.dart';
|
import '../../../common/ui_helpers.dart';
|
||||||
import '../../../widgets/custom_elevated_button.dart';
|
import '../../../widgets/custom_elevated_button.dart';
|
||||||
import '../../../widgets/custom_form_label.dart';
|
import '../../../widgets/custom_form_label.dart';
|
||||||
|
|
@ -58,7 +60,15 @@ class ResetPasswordScreen extends ViewModelWidget<ForgetPasswordViewModel> {
|
||||||
required ForgetPasswordViewModel viewModel}) =>
|
required ForgetPasswordViewModel viewModel}) =>
|
||||||
Scaffold(
|
Scaffold(
|
||||||
backgroundColor: kcBackgroundColor,
|
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(
|
Widget _buildScaffoldStack(
|
||||||
|
|
@ -86,11 +96,9 @@ class ResetPasswordScreen extends ViewModelWidget<ForgetPasswordViewModel> {
|
||||||
showBackButton: true,
|
showBackButton: true,
|
||||||
showLanguageSelection: true,
|
showLanguageSelection: true,
|
||||||
onPop: () => _inAppPop(viewModel),
|
onPop: () => _inAppPop(viewModel),
|
||||||
language: viewModel.selectedLanguage['code'],
|
language: viewModel.selectedLanguage['code'],
|
||||||
|
onLanguage: () async => await viewModel.navigateToLanguage(),
|
||||||
onLanguage: ()async => await viewModel.navigateToLanguage(),
|
);
|
||||||
|
|
||||||
);
|
|
||||||
|
|
||||||
Widget _buildExpandedBody(ForgetPasswordViewModel viewModel) =>
|
Widget _buildExpandedBody(ForgetPasswordViewModel viewModel) =>
|
||||||
Expanded(child: _buildColumnScroller(viewModel));
|
Expanded(child: _buildColumnScroller(viewModel));
|
||||||
|
|
@ -115,7 +123,7 @@ class ResetPasswordScreen extends ViewModelWidget<ForgetPasswordViewModel> {
|
||||||
verticalSpaceMedium,
|
verticalSpaceMedium,
|
||||||
_buildTitle(),
|
_buildTitle(),
|
||||||
verticalSpaceMedium,
|
verticalSpaceMedium,
|
||||||
_buildFormLabel('Reset code'),
|
_buildFormLabel(LocaleKeys.reset_code.tr()),
|
||||||
verticalSpaceSmall,
|
verticalSpaceSmall,
|
||||||
_buildResetCodeFormField(viewModel),
|
_buildResetCodeFormField(viewModel),
|
||||||
if (viewModel.hasResetCodeValidationMessage && viewModel.focusResetCode)
|
if (viewModel.hasResetCodeValidationMessage && viewModel.focusResetCode)
|
||||||
|
|
@ -123,7 +131,7 @@ class ResetPasswordScreen extends ViewModelWidget<ForgetPasswordViewModel> {
|
||||||
if (viewModel.hasResetCodeValidationMessage && viewModel.focusResetCode)
|
if (viewModel.hasResetCodeValidationMessage && viewModel.focusResetCode)
|
||||||
_buildResetCodeValidationWrapper(viewModel),
|
_buildResetCodeValidationWrapper(viewModel),
|
||||||
verticalSpaceMedium,
|
verticalSpaceMedium,
|
||||||
_buildFormLabel('New Password'),
|
_buildFormLabel(LocaleKeys.new_password.tr()),
|
||||||
verticalSpaceSmall,
|
verticalSpaceSmall,
|
||||||
_buildPasswordFormField(viewModel),
|
_buildPasswordFormField(viewModel),
|
||||||
if (viewModel.hasPasswordValidationMessage && viewModel.focusPassword)
|
if (viewModel.hasPasswordValidationMessage && viewModel.focusPassword)
|
||||||
|
|
@ -131,7 +139,7 @@ class ResetPasswordScreen extends ViewModelWidget<ForgetPasswordViewModel> {
|
||||||
if (viewModel.hasPasswordValidationMessage && viewModel.focusPassword)
|
if (viewModel.hasPasswordValidationMessage && viewModel.focusPassword)
|
||||||
_buildPasswordValidationWrapper(viewModel),
|
_buildPasswordValidationWrapper(viewModel),
|
||||||
verticalSpaceMedium,
|
verticalSpaceMedium,
|
||||||
_buildFormLabel('Confirm Password'),
|
_buildFormLabel(LocaleKeys.confirm_password.tr()),
|
||||||
verticalSpaceSmall,
|
verticalSpaceSmall,
|
||||||
_buildConfirmPasswordFormField(viewModel),
|
_buildConfirmPasswordFormField(viewModel),
|
||||||
if (viewModel.hasConfirmPasswordValidationMessage &&
|
if (viewModel.hasConfirmPasswordValidationMessage &&
|
||||||
|
|
@ -151,7 +159,7 @@ class ResetPasswordScreen extends ViewModelWidget<ForgetPasswordViewModel> {
|
||||||
];
|
];
|
||||||
|
|
||||||
Widget _buildTitle() => Text(
|
Widget _buildTitle() => Text(
|
||||||
'Reset password',
|
LocaleKeys.reset_password.tr(),
|
||||||
style: style25DG600,
|
style: style25DG600,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
@ -165,7 +173,7 @@ class ResetPasswordScreen extends ViewModelWidget<ForgetPasswordViewModel> {
|
||||||
controller: resetCodeController,
|
controller: resetCodeController,
|
||||||
onTap: viewModel.setResetCodeFocus,
|
onTap: viewModel.setResetCodeFocus,
|
||||||
decoration: inputDecoration(
|
decoration: inputDecoration(
|
||||||
hint: 'Reset code',
|
hint: LocaleKeys.reset_code.tr(),
|
||||||
focus: viewModel.focusResetCode,
|
focus: viewModel.focusResetCode,
|
||||||
filled: passwordController.text.isNotEmpty),
|
filled: passwordController.text.isNotEmpty),
|
||||||
);
|
);
|
||||||
|
|
@ -186,7 +194,7 @@ class ResetPasswordScreen extends ViewModelWidget<ForgetPasswordViewModel> {
|
||||||
onTap: viewModel.setPasswordFocus,
|
onTap: viewModel.setPasswordFocus,
|
||||||
obscureText: viewModel.obscurePassword,
|
obscureText: viewModel.obscurePassword,
|
||||||
decoration: inputDecoration(
|
decoration: inputDecoration(
|
||||||
hint: 'Password',
|
hint: LocaleKeys.password.tr(),
|
||||||
focus: viewModel.focusPassword,
|
focus: viewModel.focusPassword,
|
||||||
suffix: _buildObscurePassword(viewModel),
|
suffix: _buildObscurePassword(viewModel),
|
||||||
filled: passwordController.text.isNotEmpty),
|
filled: passwordController.text.isNotEmpty),
|
||||||
|
|
@ -221,7 +229,7 @@ class ResetPasswordScreen extends ViewModelWidget<ForgetPasswordViewModel> {
|
||||||
password: passwordController.text,
|
password: passwordController.text,
|
||||||
confirmPassword: confirmPasswordController.text),
|
confirmPassword: confirmPasswordController.text),
|
||||||
decoration: inputDecoration(
|
decoration: inputDecoration(
|
||||||
hint: 'Confirm Password',
|
hint: LocaleKeys.confirm_password.tr(),
|
||||||
focus: viewModel.focusConfirmPassword,
|
focus: viewModel.focusConfirmPassword,
|
||||||
suffix: _buildObscureConfirmPassword(viewModel),
|
suffix: _buildObscureConfirmPassword(viewModel),
|
||||||
filled: confirmPasswordController.text.isNotEmpty),
|
filled: confirmPasswordController.text.isNotEmpty),
|
||||||
|
|
@ -255,21 +263,22 @@ class ResetPasswordScreen extends ViewModelWidget<ForgetPasswordViewModel> {
|
||||||
|
|
||||||
Widget _buildCharLengthValidator(ForgetPasswordViewModel viewModel) =>
|
Widget _buildCharLengthValidator(ForgetPasswordViewModel viewModel) =>
|
||||||
ValidatorListTile(
|
ValidatorListTile(
|
||||||
backgroundColor: viewModel.length ? kcPrimaryColor : kcLightGrey,
|
label: LocaleKeys.eight_character_minimum.tr(),
|
||||||
label: '8 characters minimum');
|
backgroundColor: viewModel.length ? kcPrimaryColor : kcLightGrey,
|
||||||
|
);
|
||||||
|
|
||||||
Widget _buildPasswordMatchValidator(ForgetPasswordViewModel viewModel) =>
|
Widget _buildPasswordMatchValidator(ForgetPasswordViewModel viewModel) =>
|
||||||
ValidatorListTile(
|
ValidatorListTile(
|
||||||
backgroundColor:
|
label: LocaleKeys.password_match.tr(),
|
||||||
viewModel.passwordMatch ? kcPrimaryColor : kcLightGrey,
|
backgroundColor: viewModel.passwordMatch ? kcPrimaryColor : kcLightGrey,
|
||||||
label: 'password match');
|
);
|
||||||
|
|
||||||
Widget _buildSignUpButton(ForgetPasswordViewModel viewModel) =>
|
Widget _buildSignUpButton(ForgetPasswordViewModel viewModel) =>
|
||||||
CustomElevatedButton(
|
CustomElevatedButton(
|
||||||
height: 55,
|
height: 55,
|
||||||
text: 'Continue',
|
|
||||||
borderRadius: 12,
|
borderRadius: 12,
|
||||||
foregroundColor: kcWhite,
|
foregroundColor: kcWhite,
|
||||||
|
text: LocaleKeys.cont.tr(),
|
||||||
onTap: passwordController.text.isNotEmpty &&
|
onTap: passwordController.text.isNotEmpty &&
|
||||||
confirmPasswordController.text.isNotEmpty &&
|
confirmPasswordController.text.isNotEmpty &&
|
||||||
resetCodeController.text.isNotEmpty &&
|
resetCodeController.text.isNotEmpty &&
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,6 @@ import 'package:stacked/stacked.dart';
|
||||||
import 'package:yimaru_app/ui/common/app_colors.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/learn_program/learn_program_view.dart';
|
||||||
import 'package:yimaru_app/ui/views/profile/profile_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 '../course/course_view.dart';
|
||||||
import 'home_viewmodel.dart';
|
import 'home_viewmodel.dart';
|
||||||
|
|
|
||||||
52
lib/ui/views/landing/landing_view.dart
Normal file
52
lib/ui/views/landing/landing_view.dart
Normal file
|
|
@ -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<LandingViewModel> {
|
||||||
|
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<Widget> _buildScreens() =>
|
||||||
|
[_buildFirstWelcome(), _buildSecondWelcome(), _buildThirdWelcome()];
|
||||||
|
|
||||||
|
Widget _buildFirstWelcome() => const FirstLandingScreen();
|
||||||
|
|
||||||
|
Widget _buildSecondWelcome() => const SecondLandingScreen();
|
||||||
|
|
||||||
|
Widget _buildThirdWelcome() => const ThirdLandingScreen();
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
29
lib/ui/views/landing/landing_viewmodel.dart
Normal file
29
lib/ui/views/landing/landing_viewmodel.dart
Normal file
|
|
@ -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<NavigationService>();
|
||||||
|
|
||||||
|
final _authenticationService = locator<AuthenticationService>();
|
||||||
|
|
||||||
|
// Navigation
|
||||||
|
Future<void> navigateToLogin() async =>
|
||||||
|
await _navigationService.replaceWithLoginView();
|
||||||
|
|
||||||
|
// Remote api call
|
||||||
|
|
||||||
|
// First time install
|
||||||
|
Future<void> setFirstTimeInstall() async {
|
||||||
|
await runBusyFuture(_setFirstTimeInstall());
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> _setFirstTimeInstall() async {
|
||||||
|
await _authenticationService.setFirstTimeInstall(false);
|
||||||
|
await navigateToLogin();
|
||||||
|
}
|
||||||
|
}
|
||||||
145
lib/ui/views/landing/screens/first_landing_screen.dart
Normal file
145
lib/ui/views/landing/screens/first_landing_screen.dart
Normal file
|
|
@ -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<LandingViewModel> {
|
||||||
|
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<Widget> _buildScaffoldChildren(LandingViewModel viewModel) =>
|
||||||
|
[ _buildUpperColumn(),_buildLowerColumnWrapper(viewModel)];
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Widget _buildUpperColumn() => Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||||
|
children: _buildUpperColumnChildren(),
|
||||||
|
);
|
||||||
|
|
||||||
|
List<Widget> _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<Widget> _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(),
|
||||||
|
);
|
||||||
|
}
|
||||||
146
lib/ui/views/landing/screens/second_landing_screen.dart
Normal file
146
lib/ui/views/landing/screens/second_landing_screen.dart
Normal file
|
|
@ -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<LandingViewModel> {
|
||||||
|
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<Widget> _buildScaffoldChildren(LandingViewModel viewModel) =>
|
||||||
|
[ _buildUpperColumn(),_buildLowerColumnWrapper(viewModel)];
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Widget _buildUpperColumn() => Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||||
|
children: _buildUpperColumnChildren(),
|
||||||
|
);
|
||||||
|
|
||||||
|
List<Widget> _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<Widget> _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(),
|
||||||
|
);
|
||||||
|
}
|
||||||
146
lib/ui/views/landing/screens/third_landing_screen.dart
Normal file
146
lib/ui/views/landing/screens/third_landing_screen.dart
Normal file
|
|
@ -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<LandingViewModel> {
|
||||||
|
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<Widget> _buildScaffoldChildren(LandingViewModel viewModel) =>
|
||||||
|
[ _buildUpperColumn(),_buildLowerColumnWrapper(viewModel)];
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Widget _buildUpperColumn() => Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||||
|
children: _buildUpperColumnChildren(),
|
||||||
|
);
|
||||||
|
|
||||||
|
List<Widget> _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<Widget> _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(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
@ -29,7 +29,15 @@ class LanguageView extends StackedView<LanguageViewModel> {
|
||||||
required LanguageViewModel viewModel}) =>
|
required LanguageViewModel viewModel}) =>
|
||||||
Scaffold(
|
Scaffold(
|
||||||
backgroundColor: kcBackgroundColor,
|
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(
|
Widget _buildScaffold(
|
||||||
|
|
|
||||||
|
|
@ -14,14 +14,13 @@ class LanguageViewModel extends ReactiveViewModel {
|
||||||
@override
|
@override
|
||||||
List<ListenableServiceMixin> get listenableServices => [_localizationService];
|
List<ListenableServiceMixin> get listenableServices => [_localizationService];
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Languages
|
// Languages
|
||||||
List<Map<String, dynamic>> get _languages => _localizationService.languages;
|
List<Map<String, dynamic>> get _languages => _localizationService.languages;
|
||||||
|
|
||||||
List<Map<String, dynamic>> get languages => _languages;
|
List<Map<String, dynamic>> get languages => _languages;
|
||||||
|
|
||||||
Map<String, dynamic> get _selectedLanguage => _localizationService.selectedLanguage;
|
Map<String, dynamic> get _selectedLanguage =>
|
||||||
|
_localizationService.selectedLanguage;
|
||||||
|
|
||||||
Map<String, dynamic> get selectedLanguage => _selectedLanguage;
|
Map<String, dynamic> get selectedLanguage => _selectedLanguage;
|
||||||
// Languages
|
// Languages
|
||||||
|
|
|
||||||
|
|
@ -34,7 +34,12 @@ class LearnCourseView extends StackedView<LearnCourseViewModel> {
|
||||||
|
|
||||||
Widget _buildScaffoldWrapper(LearnCourseViewModel viewModel) => Scaffold(
|
Widget _buildScaffoldWrapper(LearnCourseViewModel viewModel) => Scaffold(
|
||||||
backgroundColor: kcBackgroundColor,
|
backgroundColor: kcBackgroundColor,
|
||||||
body: _buildScaffold(viewModel),
|
body: _buildScaffoldContainer(viewModel),
|
||||||
|
);
|
||||||
|
|
||||||
|
Widget _buildScaffoldContainer(LearnCourseViewModel viewModel) => Container(
|
||||||
|
decoration: bgDecoration,
|
||||||
|
child: _buildScaffold(viewModel),
|
||||||
);
|
);
|
||||||
|
|
||||||
Widget _buildScaffold(LearnCourseViewModel viewModel) =>
|
Widget _buildScaffold(LearnCourseViewModel viewModel) =>
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,6 @@ import 'package:yimaru_app/app/app.router.dart';
|
||||||
|
|
||||||
import '../../../app/app.locator.dart';
|
import '../../../app/app.locator.dart';
|
||||||
import '../../../models/learn_course.dart';
|
import '../../../models/learn_course.dart';
|
||||||
import '../../../services/api_service.dart';
|
|
||||||
import '../../../services/learn_service.dart';
|
import '../../../services/learn_service.dart';
|
||||||
import '../../../services/status_checker_service.dart';
|
import '../../../services/status_checker_service.dart';
|
||||||
import '../../common/enmus.dart';
|
import '../../common/enmus.dart';
|
||||||
|
|
|
||||||
|
|
@ -48,7 +48,15 @@ class LearnLessonView extends StackedView<LearnLessonViewModel> {
|
||||||
required LearnLessonViewModel viewModel}) =>
|
required LearnLessonViewModel viewModel}) =>
|
||||||
Scaffold(
|
Scaffold(
|
||||||
backgroundColor: kcBackgroundColor,
|
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(
|
Widget _buildScaffold(
|
||||||
|
|
|
||||||
|
|
@ -60,7 +60,13 @@ class LearnLessonDetailView extends StackedView<LearnLessonDetailViewModel> {
|
||||||
Widget _buildScaffoldWrapper(LearnLessonDetailViewModel viewModel) =>
|
Widget _buildScaffoldWrapper(LearnLessonDetailViewModel viewModel) =>
|
||||||
Scaffold(
|
Scaffold(
|
||||||
backgroundColor: kcBackgroundColor,
|
backgroundColor: kcBackgroundColor,
|
||||||
body: _buildScaffold(viewModel),
|
body: _buildScaffoldContainer(viewModel),
|
||||||
|
);
|
||||||
|
|
||||||
|
Widget _buildScaffoldContainer(LearnLessonDetailViewModel viewModel) =>
|
||||||
|
Container(
|
||||||
|
decoration: bgDecoration,
|
||||||
|
child: _buildScaffold(viewModel),
|
||||||
);
|
);
|
||||||
|
|
||||||
Widget _buildScaffold(LearnLessonDetailViewModel viewModel) =>
|
Widget _buildScaffold(LearnLessonDetailViewModel viewModel) =>
|
||||||
|
|
|
||||||
|
|
@ -37,7 +37,12 @@ class LearnModuleView extends StackedView<LearnModuleViewModel> {
|
||||||
|
|
||||||
Widget _buildScaffoldWrapper(LearnModuleViewModel viewModel) => Scaffold(
|
Widget _buildScaffoldWrapper(LearnModuleViewModel viewModel) => Scaffold(
|
||||||
backgroundColor: kcBackgroundColor,
|
backgroundColor: kcBackgroundColor,
|
||||||
body: _buildScaffold(viewModel),
|
body: _buildScaffoldContainer(viewModel),
|
||||||
|
);
|
||||||
|
|
||||||
|
Widget _buildScaffoldContainer(LearnModuleViewModel viewModel) => Container(
|
||||||
|
decoration: bgDecoration,
|
||||||
|
child: _buildScaffold(viewModel),
|
||||||
);
|
);
|
||||||
|
|
||||||
Widget _buildScaffold(LearnModuleViewModel viewModel) =>
|
Widget _buildScaffold(LearnModuleViewModel viewModel) =>
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,6 @@ import 'package:yimaru_app/app/app.router.dart';
|
||||||
import 'package:yimaru_app/models/learn_module.dart';
|
import 'package:yimaru_app/models/learn_module.dart';
|
||||||
|
|
||||||
import '../../../app/app.locator.dart';
|
import '../../../app/app.locator.dart';
|
||||||
import '../../../services/api_service.dart';
|
|
||||||
import '../../../services/learn_service.dart';
|
import '../../../services/learn_service.dart';
|
||||||
import '../../../services/status_checker_service.dart';
|
import '../../../services/status_checker_service.dart';
|
||||||
import '../../common/enmus.dart';
|
import '../../common/enmus.dart';
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,9 @@
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:stacked/stacked.dart';
|
import 'package:stacked/stacked.dart';
|
||||||
import 'package:yimaru_app/ui/common/enmus.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_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_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_description_screen.dart';
|
||||||
import 'package:yimaru_app/ui/views/learn_practice/screens/learn_practice_result_screen.dart';
|
import 'package:yimaru_app/ui/views/learn_practice/screens/learn_practice_result_screen.dart';
|
||||||
|
|
@ -115,10 +116,12 @@ class LearnPracticeView extends StackedView<LearnPracticeViewModel> {
|
||||||
|
|
||||||
List<Widget> _buildScreens(LearnPracticeViewModel viewModel) => [
|
List<Widget> _buildScreens(LearnPracticeViewModel viewModel) => [
|
||||||
_buildLearnPracticeIntroScreen(),
|
_buildLearnPracticeIntroScreen(),
|
||||||
_buildLearnPracticeElementsScreen(),
|
if (practice != LearnPractices.lesson)
|
||||||
|
_buildLearnPracticeElementsScreen(),
|
||||||
_buildLearnPracticeQuestionsScreen(),
|
_buildLearnPracticeQuestionsScreen(),
|
||||||
_buildFinishLearnPracticeScreen(),
|
_buildLearnPracticeAppreciationScreen(),
|
||||||
_buildLearnPracticeResultScreen(),
|
_buildLearnPracticeResultScreen(),
|
||||||
|
_buildLearnPracticeFinishScreen(),
|
||||||
if (practice == LearnPractices.course)
|
if (practice == LearnPractices.course)
|
||||||
_buildLearnPracticeCompletionScreen()
|
_buildLearnPracticeCompletionScreen()
|
||||||
];
|
];
|
||||||
|
|
@ -137,12 +140,14 @@ class LearnPracticeView extends StackedView<LearnPracticeViewModel> {
|
||||||
Widget _buildLearnPracticeQuestionsScreen() =>
|
Widget _buildLearnPracticeQuestionsScreen() =>
|
||||||
const LearnPracticeQuestionsScreen();
|
const LearnPracticeQuestionsScreen();
|
||||||
|
|
||||||
Widget _buildFinishLearnPracticeScreen() => const FinishLearnPracticeScreen();
|
Widget _buildLearnPracticeAppreciationScreen() =>
|
||||||
|
const LearnPracticeAppreciationScreen();
|
||||||
|
|
||||||
Widget _buildLearnPracticeResultScreen() =>
|
Widget _buildLearnPracticeResultScreen() =>
|
||||||
LearnPracticeResultScreen(practice: practice);
|
LearnPracticeResultScreen(practice: practice);
|
||||||
|
|
||||||
Widget _buildLearnPracticeCompletionScreen() => LearnPracticeCompletionScreen(
|
Widget _buildLearnPracticeFinishScreen() => const LearnPracticeFinishScreen();
|
||||||
level: level ?? '',
|
|
||||||
);
|
Widget _buildLearnPracticeCompletionScreen() =>
|
||||||
|
LearnPracticeCompletionScreen(level: level ?? '');
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -55,7 +55,15 @@ class InteractLearnPracticeScreen
|
||||||
required LearnPracticeViewModel viewModel}) =>
|
required LearnPracticeViewModel viewModel}) =>
|
||||||
Scaffold(
|
Scaffold(
|
||||||
backgroundColor: kcBackgroundColor,
|
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(
|
Widget _buildScaffold(
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,12 @@ class LearnLoadingScreen extends StatelessWidget {
|
||||||
|
|
||||||
Widget _buildScaffoldWrapper() => Scaffold(
|
Widget _buildScaffoldWrapper() => Scaffold(
|
||||||
backgroundColor: kcBackgroundColor,
|
backgroundColor: kcBackgroundColor,
|
||||||
body: _buildScaffold(),
|
body: _buildScaffoldContainer(),
|
||||||
|
);
|
||||||
|
|
||||||
|
Widget _buildScaffoldContainer() => Container(
|
||||||
|
decoration: bgDecoration,
|
||||||
|
child: _buildScaffold(),
|
||||||
);
|
);
|
||||||
|
|
||||||
Widget _buildScaffold() => SafeArea(child: _buildStack());
|
Widget _buildScaffold() => SafeArea(child: _buildStack());
|
||||||
|
|
|
||||||
|
|
@ -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<LearnPracticeViewModel> {
|
||||||
|
const LearnPracticeAppreciationScreen({super.key});
|
||||||
|
|
||||||
|
Future<void> _reset(LearnPracticeViewModel viewModel) async =>
|
||||||
|
await viewModel.reset();
|
||||||
|
|
||||||
|
Future<void> _cancel(LearnPracticeViewModel viewModel) async {
|
||||||
|
await viewModel.stopRecording();
|
||||||
|
viewModel.pop();
|
||||||
|
viewModel.pop();
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> _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<Widget> _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<Widget> _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,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
@ -3,12 +3,9 @@ import 'package:flutter_svg/svg.dart';
|
||||||
import 'package:stacked/stacked.dart';
|
import 'package:stacked/stacked.dart';
|
||||||
import 'package:yimaru_app/ui/views/learn_practice/learn_practice_viewmodel.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/app_colors.dart';
|
||||||
import '../../../common/enmus.dart';
|
|
||||||
import '../../../common/ui_helpers.dart';
|
import '../../../common/ui_helpers.dart';
|
||||||
import '../../../widgets/custom_elevated_button.dart';
|
import '../../../widgets/custom_elevated_button.dart';
|
||||||
import '../../../widgets/page_loading_indicator.dart';
|
|
||||||
|
|
||||||
class LearnPracticeCompletionScreen
|
class LearnPracticeCompletionScreen
|
||||||
extends ViewModelWidget<LearnPracticeViewModel> {
|
extends ViewModelWidget<LearnPracticeViewModel> {
|
||||||
|
|
@ -21,7 +18,12 @@ class LearnPracticeCompletionScreen
|
||||||
|
|
||||||
Widget _buildScaffoldWrapper(LearnPracticeViewModel viewModel) => Scaffold(
|
Widget _buildScaffoldWrapper(LearnPracticeViewModel viewModel) => Scaffold(
|
||||||
backgroundColor: kcBackgroundColor,
|
backgroundColor: kcBackgroundColor,
|
||||||
body: _buildBodyWrapper(viewModel),
|
body: _buildScaffoldContainer(viewModel),
|
||||||
|
);
|
||||||
|
|
||||||
|
Widget _buildScaffoldContainer(LearnPracticeViewModel viewModel) => Container(
|
||||||
|
decoration: bgDecoration,
|
||||||
|
child: _buildBodyWrapper(viewModel),
|
||||||
);
|
);
|
||||||
|
|
||||||
Widget _buildBodyWrapper(LearnPracticeViewModel viewModel) => Padding(
|
Widget _buildBodyWrapper(LearnPracticeViewModel viewModel) => Padding(
|
||||||
|
|
@ -29,14 +31,18 @@ class LearnPracticeCompletionScreen
|
||||||
child: _buildBody(viewModel),
|
child: _buildBody(viewModel),
|
||||||
);
|
);
|
||||||
|
|
||||||
Widget _buildBody(LearnPracticeViewModel viewModel) => Column(
|
Widget _buildBody(LearnPracticeViewModel viewModel) => Stack(
|
||||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
||||||
children: _buildBodyChildren(viewModel),
|
children: _buildBodyChildren(viewModel),
|
||||||
);
|
);
|
||||||
|
|
||||||
List<Widget> _buildBodyChildren(LearnPracticeViewModel viewModel) =>
|
List<Widget> _buildBodyChildren(LearnPracticeViewModel viewModel) => [
|
||||||
[_buildUpperColumn(viewModel), _buildContinueButtonWrapper(viewModel)];
|
_buildUpperColumnWrapper(viewModel),
|
||||||
|
_buildContinueButtonWrapper(viewModel)
|
||||||
|
];
|
||||||
|
Widget _buildUpperColumnWrapper(LearnPracticeViewModel viewModel) => Align(
|
||||||
|
alignment: Alignment.center,
|
||||||
|
child: _buildUpperColumn(viewModel),
|
||||||
|
);
|
||||||
|
|
||||||
Widget _buildUpperColumn(LearnPracticeViewModel viewModel) => Column(
|
Widget _buildUpperColumn(LearnPracticeViewModel viewModel) => Column(
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
|
@ -45,16 +51,13 @@ class LearnPracticeCompletionScreen
|
||||||
);
|
);
|
||||||
|
|
||||||
List<Widget> _buildUpperColumnChildren(LearnPracticeViewModel viewModel) => [
|
List<Widget> _buildUpperColumnChildren(LearnPracticeViewModel viewModel) => [
|
||||||
verticalSpaceMassive,
|
|
||||||
_buildIcon(),
|
_buildIcon(),
|
||||||
verticalSpaceMedium,
|
verticalSpaceMedium,
|
||||||
_buildTitle(),
|
_buildTitle(),
|
||||||
verticalSpaceSmall,
|
|
||||||
_buildSubtitle(),
|
|
||||||
];
|
];
|
||||||
|
|
||||||
Widget _buildIcon() => SvgPicture.asset(
|
Widget _buildIcon() => SvgPicture.asset(
|
||||||
'assets/icons/complete.svg',
|
'assets/icons/mascot.svg',
|
||||||
);
|
);
|
||||||
|
|
||||||
Widget _buildTitle() => Text(
|
Widget _buildTitle() => Text(
|
||||||
|
|
@ -63,13 +66,12 @@ class LearnPracticeCompletionScreen
|
||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
);
|
);
|
||||||
|
|
||||||
Widget _buildSubtitle() => Text(
|
Widget _buildContinueButtonWrapper(LearnPracticeViewModel viewModel) => Align(
|
||||||
'We’re now analyzing your speaking skills',
|
alignment: Alignment.bottomCenter,
|
||||||
textAlign: TextAlign.center,
|
child: _buildContinueButtonPadding(viewModel),
|
||||||
style: style14MG400,
|
|
||||||
);
|
);
|
||||||
|
|
||||||
Widget _buildContinueButtonWrapper(LearnPracticeViewModel viewModel) =>
|
Widget _buildContinueButtonPadding(LearnPracticeViewModel viewModel) =>
|
||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.only(bottom: 50),
|
padding: const EdgeInsets.only(bottom: 50),
|
||||||
child: _buildContinueButton(viewModel),
|
child: _buildContinueButton(viewModel),
|
||||||
|
|
|
||||||
|
|
@ -39,7 +39,15 @@ class LearnPracticeDescriptionScreen
|
||||||
required LearnPracticeViewModel viewModel}) =>
|
required LearnPracticeViewModel viewModel}) =>
|
||||||
Scaffold(
|
Scaffold(
|
||||||
backgroundColor: kcBackgroundColor,
|
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(
|
Widget _buildScaffold(
|
||||||
|
|
|
||||||
|
|
@ -8,9 +8,9 @@ import '../../../common/ui_helpers.dart';
|
||||||
import '../../../widgets/custom_elevated_button.dart';
|
import '../../../widgets/custom_elevated_button.dart';
|
||||||
import '../../../widgets/small_app_bar.dart';
|
import '../../../widgets/small_app_bar.dart';
|
||||||
|
|
||||||
class FinishLearnPracticeScreen
|
class LearnPracticeFinishScreen
|
||||||
extends ViewModelWidget<LearnPracticeViewModel> {
|
extends ViewModelWidget<LearnPracticeViewModel> {
|
||||||
const FinishLearnPracticeScreen({super.key});
|
const LearnPracticeFinishScreen({super.key});
|
||||||
|
|
||||||
Future<void> _reset(LearnPracticeViewModel viewModel) async =>
|
Future<void> _reset(LearnPracticeViewModel viewModel) async =>
|
||||||
await viewModel.reset();
|
await viewModel.reset();
|
||||||
|
|
@ -21,7 +21,12 @@ class FinishLearnPracticeScreen
|
||||||
|
|
||||||
Widget _buildScaffoldWrapper(LearnPracticeViewModel viewModel) => Scaffold(
|
Widget _buildScaffoldWrapper(LearnPracticeViewModel viewModel) => Scaffold(
|
||||||
backgroundColor: kcBackgroundColor,
|
backgroundColor: kcBackgroundColor,
|
||||||
body: _buildScaffold(viewModel),
|
body: _buildScaffoldContainer(viewModel),
|
||||||
|
);
|
||||||
|
|
||||||
|
Widget _buildScaffoldContainer(LearnPracticeViewModel viewModel) => Container(
|
||||||
|
decoration: bgDecoration,
|
||||||
|
child: _buildScaffold(viewModel),
|
||||||
);
|
);
|
||||||
|
|
||||||
Widget _buildScaffold(LearnPracticeViewModel viewModel) =>
|
Widget _buildScaffold(LearnPracticeViewModel viewModel) =>
|
||||||
|
|
@ -110,9 +115,9 @@ class FinishLearnPracticeScreen
|
||||||
CustomElevatedButton(
|
CustomElevatedButton(
|
||||||
height: 55,
|
height: 55,
|
||||||
borderRadius: 12,
|
borderRadius: 12,
|
||||||
|
onTap: viewModel.pop,
|
||||||
foregroundColor: kcWhite,
|
foregroundColor: kcWhite,
|
||||||
text: 'Continue Practice',
|
text: 'Continue Practice',
|
||||||
onTap: () => viewModel.goTo(4),
|
|
||||||
backgroundColor: kcPrimaryColor,
|
backgroundColor: kcPrimaryColor,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
@ -50,7 +50,15 @@ class LearnPracticeIntroScreen extends ViewModelWidget<LearnPracticeViewModel> {
|
||||||
required LearnPracticeViewModel viewModel}) =>
|
required LearnPracticeViewModel viewModel}) =>
|
||||||
Scaffold(
|
Scaffold(
|
||||||
backgroundColor: kcBackgroundColor,
|
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(
|
Widget _buildScaffold(
|
||||||
|
|
|
||||||
|
|
@ -21,9 +21,11 @@ class LearnPracticeResultScreen
|
||||||
Future<void> _navigate(LearnPracticeViewModel viewModel) async {
|
Future<void> _navigate(LearnPracticeViewModel viewModel) async {
|
||||||
await viewModel.completeLearnPractices();
|
await viewModel.completeLearnPractices();
|
||||||
if (practice == LearnPractices.course) {
|
if (practice == LearnPractices.course) {
|
||||||
|
viewModel.goTo(6);
|
||||||
|
} else if (practice == LearnPractices.module) {
|
||||||
viewModel.goTo(5);
|
viewModel.goTo(5);
|
||||||
} else {
|
} else {
|
||||||
viewModel.pop();
|
viewModel.goTo(4);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -55,7 +57,15 @@ class LearnPracticeResultScreen
|
||||||
required LearnPracticeViewModel viewModel}) =>
|
required LearnPracticeViewModel viewModel}) =>
|
||||||
Scaffold(
|
Scaffold(
|
||||||
backgroundColor: kcBackgroundColor,
|
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(
|
Widget _buildScaffoldState(
|
||||||
|
|
|
||||||
|
|
@ -44,7 +44,15 @@ class StartLearnPracticeScreen extends ViewModelWidget<LearnPracticeViewModel> {
|
||||||
required LearnPracticeViewModel viewModel}) =>
|
required LearnPracticeViewModel viewModel}) =>
|
||||||
Scaffold(
|
Scaffold(
|
||||||
backgroundColor: kcBackgroundColor,
|
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(
|
Widget _buildScaffold(
|
||||||
|
|
|
||||||
|
|
@ -33,7 +33,12 @@ class LearnProgramView extends StackedView<LearnProgramViewModel> {
|
||||||
|
|
||||||
Widget _buildScaffoldWrapper(LearnProgramViewModel viewModel) => Scaffold(
|
Widget _buildScaffoldWrapper(LearnProgramViewModel viewModel) => Scaffold(
|
||||||
backgroundColor: kcBackgroundColor,
|
backgroundColor: kcBackgroundColor,
|
||||||
body: _buildScaffold(viewModel),
|
body: _buildScaffoldContainer(viewModel),
|
||||||
|
);
|
||||||
|
|
||||||
|
Widget _buildScaffoldContainer(LearnProgramViewModel viewModel) => Container(
|
||||||
|
decoration: bgDecoration,
|
||||||
|
child: _buildScaffold(viewModel),
|
||||||
);
|
);
|
||||||
|
|
||||||
Widget _buildScaffold(LearnProgramViewModel viewModel) =>
|
Widget _buildScaffold(LearnProgramViewModel viewModel) =>
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,6 @@ import 'package:yimaru_app/models/learn_program.dart';
|
||||||
|
|
||||||
import '../../../app/app.locator.dart';
|
import '../../../app/app.locator.dart';
|
||||||
import '../../../models/user.dart';
|
import '../../../models/user.dart';
|
||||||
import '../../../services/api_service.dart';
|
|
||||||
import '../../../services/authentication_service.dart';
|
import '../../../services/authentication_service.dart';
|
||||||
import '../../../services/learn_service.dart';
|
import '../../../services/learn_service.dart';
|
||||||
import '../../../services/status_checker_service.dart';
|
import '../../../services/status_checker_service.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/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_form_screen.dart';
|
||||||
import 'package:yimaru_app/ui/views/learn_subscription/screens/learn_subscription_package_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 '../../common/validators/form_validator.dart';
|
||||||
import '../../widgets/custom_elevated_button.dart';
|
|
||||||
import '../../widgets/small_app_bar.dart';
|
|
||||||
import 'learn_subscription_viewmodel.dart';
|
import 'learn_subscription_viewmodel.dart';
|
||||||
|
|
||||||
@FormView(fields: [
|
@FormView(fields: [
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,6 @@ import 'package:stacked/stacked.dart';
|
||||||
import 'package:stacked_services/stacked_services.dart';
|
import 'package:stacked_services/stacked_services.dart';
|
||||||
import 'package:yimaru_app/app/app.router.dart';
|
import 'package:yimaru_app/app/app.router.dart';
|
||||||
import 'package:yimaru_app/models/learn_subscription.dart';
|
import 'package:yimaru_app/models/learn_subscription.dart';
|
||||||
import 'package:yimaru_app/models/learn_subscription_request.dart';
|
|
||||||
|
|
||||||
import '../../../app/app.locator.dart';
|
import '../../../app/app.locator.dart';
|
||||||
import '../../../services/api_service.dart';
|
import '../../../services/api_service.dart';
|
||||||
|
|
|
||||||
|
|
@ -3,13 +3,10 @@ import 'package:flutter/services.dart';
|
||||||
import 'package:stacked/stacked.dart';
|
import 'package:stacked/stacked.dart';
|
||||||
import 'package:yimaru_app/ui/views/learn_subscription/learn_subscription_viewmodel.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/phone_number_prefix.dart';
|
||||||
import 'package:yimaru_app/ui/widgets/speaking_partner_image.dart';
|
|
||||||
|
|
||||||
import '../../../common/app_colors.dart';
|
import '../../../common/app_colors.dart';
|
||||||
import '../../../common/ui_helpers.dart';
|
import '../../../common/ui_helpers.dart';
|
||||||
import '../../../widgets/small_app_bar.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 '../../../widgets/custom_elevated_button.dart';
|
||||||
import '../learn_subscription_view.form.dart';
|
import '../learn_subscription_view.form.dart';
|
||||||
|
|
||||||
|
|
@ -29,7 +26,13 @@ class LearnSubscriptionFormScreen
|
||||||
Widget _buildScaffoldWrapper(LearnSubscriptionViewModel viewModel) =>
|
Widget _buildScaffoldWrapper(LearnSubscriptionViewModel viewModel) =>
|
||||||
Scaffold(
|
Scaffold(
|
||||||
backgroundColor: kcBackgroundColor,
|
backgroundColor: kcBackgroundColor,
|
||||||
body: _buildScaffold(viewModel),
|
body: _buildScaffoldContainer(viewModel),
|
||||||
|
);
|
||||||
|
|
||||||
|
Widget _buildScaffoldContainer(LearnSubscriptionViewModel viewModel) =>
|
||||||
|
Container(
|
||||||
|
decoration: bgDecoration,
|
||||||
|
child: _buildScaffold(viewModel),
|
||||||
);
|
);
|
||||||
|
|
||||||
Widget _buildScaffold(LearnSubscriptionViewModel viewModel) =>
|
Widget _buildScaffold(LearnSubscriptionViewModel viewModel) =>
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,13 @@ class LearnSubscriptionPackageScreen
|
||||||
Widget _buildScaffoldWrapper(LearnSubscriptionViewModel viewModel) =>
|
Widget _buildScaffoldWrapper(LearnSubscriptionViewModel viewModel) =>
|
||||||
Scaffold(
|
Scaffold(
|
||||||
backgroundColor: kcBackgroundColor,
|
backgroundColor: kcBackgroundColor,
|
||||||
body: _buildScaffoldState(viewModel),
|
body: _buildScaffoldContainer(viewModel),
|
||||||
|
);
|
||||||
|
|
||||||
|
Widget _buildScaffoldContainer(LearnSubscriptionViewModel viewModel) =>
|
||||||
|
Container(
|
||||||
|
decoration: bgDecoration,
|
||||||
|
child: _buildScaffoldState(viewModel),
|
||||||
);
|
);
|
||||||
|
|
||||||
Widget _buildScaffoldState(LearnSubscriptionViewModel viewModel) =>
|
Widget _buildScaffoldState(LearnSubscriptionViewModel viewModel) =>
|
||||||
|
|
|
||||||
|
|
@ -30,7 +30,8 @@ class LoginViewModel extends ReactiveViewModel
|
||||||
final _authenticationService = locator<AuthenticationService>();
|
final _authenticationService = locator<AuthenticationService>();
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<ListenableServiceMixin> get listenableServices => [_googleAuthService,_localizationService];
|
List<ListenableServiceMixin> get listenableServices =>
|
||||||
|
[_googleAuthService, _localizationService];
|
||||||
|
|
||||||
// Google user
|
// Google user
|
||||||
GoogleSignInAccount? get _googleUser => _googleAuthService.googleUser;
|
GoogleSignInAccount? get _googleUser => _googleAuthService.googleUser;
|
||||||
|
|
@ -38,7 +39,8 @@ class LoginViewModel extends ReactiveViewModel
|
||||||
GoogleSignInAccount? get googleUser => _googleUser;
|
GoogleSignInAccount? get googleUser => _googleUser;
|
||||||
|
|
||||||
// Languages
|
// Languages
|
||||||
Map<String, dynamic> get _selectedLanguage => _localizationService.selectedLanguage;
|
Map<String, dynamic> get _selectedLanguage =>
|
||||||
|
_localizationService.selectedLanguage;
|
||||||
|
|
||||||
Map<String, dynamic> get selectedLanguage => _selectedLanguage;
|
Map<String, dynamic> get selectedLanguage => _selectedLanguage;
|
||||||
|
|
||||||
|
|
@ -172,8 +174,6 @@ class LoginViewModel extends ReactiveViewModel
|
||||||
Future<void> navigateToForgetPassword() async =>
|
Future<void> navigateToForgetPassword() async =>
|
||||||
await _navigationService.navigateToForgetPasswordView();
|
await _navigationService.navigateToForgetPasswordView();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Future<void> replaceWithStartUp() async =>
|
Future<void> replaceWithStartUp() async =>
|
||||||
await _navigationService.clearStackAndShow(Routes.startupView);
|
await _navigationService.clearStackAndShow(Routes.startupView);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,11 @@
|
||||||
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_timer_countdown/flutter_timer_countdown.dart';
|
import 'package:flutter_timer_countdown/flutter_timer_countdown.dart';
|
||||||
import 'package:pinput/pinput.dart';
|
import 'package:pinput/pinput.dart';
|
||||||
import 'package:stacked/stacked.dart';
|
import 'package:stacked/stacked.dart';
|
||||||
import 'package:yimaru_app/app/app.locator.dart';
|
import 'package:yimaru_app/app/app.locator.dart';
|
||||||
import 'package:yimaru_app/services/smart_auth_service.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 'package:yimaru_app/ui/widgets/custom_cursor.dart';
|
||||||
|
|
||||||
import '../../../common/app_colors.dart';
|
import '../../../common/app_colors.dart';
|
||||||
|
|
@ -52,7 +54,14 @@ class LoginOtpScreen extends ViewModelWidget<LoginViewModel> {
|
||||||
{required BuildContext context, required LoginViewModel viewModel}) =>
|
{required BuildContext context, required LoginViewModel viewModel}) =>
|
||||||
Scaffold(
|
Scaffold(
|
||||||
backgroundColor: kcBackgroundColor,
|
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(
|
Widget _buildScaffoldStack(
|
||||||
|
|
@ -80,14 +89,12 @@ class LoginOtpScreen extends ViewModelWidget<LoginViewModel> {
|
||||||
_buildExpandedBody(context: context, viewModel: viewModel)
|
_buildExpandedBody(context: context, viewModel: viewModel)
|
||||||
];
|
];
|
||||||
|
|
||||||
Widget _buildAppBar(LoginViewModel viewModel) => LargeAppBar(
|
Widget _buildAppBar(LoginViewModel viewModel) => LargeAppBar(
|
||||||
showBackButton: false,
|
showBackButton: false,
|
||||||
showLanguageSelection: true,
|
showLanguageSelection: true,
|
||||||
language: viewModel.selectedLanguage['code'],
|
language: viewModel.selectedLanguage['code'],
|
||||||
|
onLanguage: () async => await viewModel.navigateToLanguage(),
|
||||||
onLanguage: ()async => await viewModel.navigateToLanguage(),
|
);
|
||||||
|
|
||||||
);
|
|
||||||
|
|
||||||
Widget _buildExpandedBody(
|
Widget _buildExpandedBody(
|
||||||
{required BuildContext context, required LoginViewModel viewModel}) =>
|
{required BuildContext context, required LoginViewModel viewModel}) =>
|
||||||
|
|
@ -145,7 +152,7 @@ class LoginOtpScreen extends ViewModelWidget<LoginViewModel> {
|
||||||
];
|
];
|
||||||
|
|
||||||
Widget _buildTitle() => Text(
|
Widget _buildTitle() => Text(
|
||||||
'Verification Code',
|
LocaleKeys.verification_code.tr(),
|
||||||
style: style25DG600,
|
style: style25DG600,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
@ -153,7 +160,7 @@ class LoginOtpScreen extends ViewModelWidget<LoginViewModel> {
|
||||||
phoneNumberController.text.length == 9 ? _buildSubtitle() : Container();
|
phoneNumberController.text.length == 9 ? _buildSubtitle() : Container();
|
||||||
|
|
||||||
Widget _buildSubtitle() => Text(
|
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,
|
style: style14DG400,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
@ -199,7 +206,7 @@ class LoginOtpScreen extends ViewModelWidget<LoginViewModel> {
|
||||||
child: _buildResendText());
|
child: _buildResendText());
|
||||||
|
|
||||||
Widget _buildResendText() => Text(
|
Widget _buildResendText() => Text(
|
||||||
'Resend code',
|
LocaleKeys.reset_code.tr(),
|
||||||
style: style14P600.copyWith(fontStyle: FontStyle.italic),
|
style: style14P600.copyWith(fontStyle: FontStyle.italic),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
@ -211,7 +218,8 @@ class LoginOtpScreen extends ViewModelWidget<LoginViewModel> {
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
|
|
||||||
Widget _buildCountdownText() => Text('Resend code in ', style: style14DG400);
|
Widget _buildCountdownText() =>
|
||||||
|
Text('${LocaleKeys.resend_code_in.tr()} ', style: style14DG400);
|
||||||
|
|
||||||
Widget _buildTimer(LoginViewModel viewModel) => TimerCountdown(
|
Widget _buildTimer(LoginViewModel viewModel) => TimerCountdown(
|
||||||
enableDescriptions: false,
|
enableDescriptions: false,
|
||||||
|
|
@ -229,9 +237,9 @@ class LoginOtpScreen extends ViewModelWidget<LoginViewModel> {
|
||||||
|
|
||||||
Widget _buildContinueButton(LoginViewModel viewModel) => CustomElevatedButton(
|
Widget _buildContinueButton(LoginViewModel viewModel) => CustomElevatedButton(
|
||||||
height: 55,
|
height: 55,
|
||||||
text: 'Continue',
|
|
||||||
borderRadius: 12,
|
borderRadius: 12,
|
||||||
foregroundColor: kcWhite,
|
foregroundColor: kcWhite,
|
||||||
|
text: LocaleKeys.cont.tr(),
|
||||||
backgroundColor:
|
backgroundColor:
|
||||||
otpController.text.length == 6 && !viewModel.hasOtpValidationMessage
|
otpController.text.length == 6 && !viewModel.hasOtpValidationMessage
|
||||||
? kcPrimaryColor
|
? kcPrimaryColor
|
||||||
|
|
|
||||||
|
|
@ -51,7 +51,14 @@ class LoginWithEmailScreen extends ViewModelWidget<LoginViewModel> {
|
||||||
{required BuildContext context, required LoginViewModel viewModel}) =>
|
{required BuildContext context, required LoginViewModel viewModel}) =>
|
||||||
Scaffold(
|
Scaffold(
|
||||||
backgroundColor: kcBackgroundColor,
|
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(
|
Widget _buildScaffoldStack(
|
||||||
|
|
@ -260,15 +267,14 @@ class LoginWithEmailScreen extends ViewModelWidget<LoginViewModel> {
|
||||||
|
|
||||||
Widget _buildLoginWithPhoneButton(LoginViewModel viewModel) =>
|
Widget _buildLoginWithPhoneButton(LoginViewModel viewModel) =>
|
||||||
CustomElevatedButton(
|
CustomElevatedButton(
|
||||||
height: 55,
|
height: 55,
|
||||||
borderRadius: 12,
|
borderRadius: 12,
|
||||||
backgroundColor: kcWhite,
|
backgroundColor: kcWhite,
|
||||||
leadingIcon: Icons.phone,
|
leadingIcon: Icons.phone,
|
||||||
borderColor: kcPrimaryColor,
|
borderColor: kcPrimaryColor,
|
||||||
onTap: () => viewModel.goTo(1),
|
onTap: () => viewModel.goTo(1),
|
||||||
foregroundColor: kcPrimaryColor,
|
foregroundColor: kcPrimaryColor,
|
||||||
text: LocaleKeys.login_with_phone.tr()
|
text: LocaleKeys.login_with_phone.tr());
|
||||||
);
|
|
||||||
|
|
||||||
Widget _buildLoginWithEmailState(LoginViewModel viewModel) =>
|
Widget _buildLoginWithEmailState(LoginViewModel viewModel) =>
|
||||||
viewModel.busy(StateObjects.loginWithEmail)
|
viewModel.busy(StateObjects.loginWithEmail)
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,8 @@
|
||||||
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
import 'package:stacked/stacked.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/views/login/login_viewmodel.dart';
|
||||||
import 'package:yimaru_app/ui/widgets/option_text_divider.dart';
|
import 'package:yimaru_app/ui/widgets/option_text_divider.dart';
|
||||||
import 'package:yimaru_app/ui/widgets/register_for_account.dart';
|
import 'package:yimaru_app/ui/widgets/register_for_account.dart';
|
||||||
|
|
@ -46,7 +48,14 @@ class LoginWithPhoneNumberScreen extends ViewModelWidget<LoginViewModel> {
|
||||||
{required BuildContext context, required LoginViewModel viewModel}) =>
|
{required BuildContext context, required LoginViewModel viewModel}) =>
|
||||||
Scaffold(
|
Scaffold(
|
||||||
backgroundColor: kcBackgroundColor,
|
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(
|
Widget _buildScaffoldStack(
|
||||||
|
|
@ -76,11 +85,9 @@ class LoginWithPhoneNumberScreen extends ViewModelWidget<LoginViewModel> {
|
||||||
showBackButton: true,
|
showBackButton: true,
|
||||||
showLanguageSelection: true,
|
showLanguageSelection: true,
|
||||||
onPop: () => viewModel.goTo(0),
|
onPop: () => viewModel.goTo(0),
|
||||||
language: viewModel.selectedLanguage['code'],
|
language: viewModel.selectedLanguage['code'],
|
||||||
|
onLanguage: () async => await viewModel.navigateToLanguage(),
|
||||||
onLanguage: ()async => await viewModel.navigateToLanguage(),
|
);
|
||||||
|
|
||||||
);
|
|
||||||
|
|
||||||
Widget _buildExpandedBody(
|
Widget _buildExpandedBody(
|
||||||
{required BuildContext context, required LoginViewModel viewModel}) =>
|
{required BuildContext context, required LoginViewModel viewModel}) =>
|
||||||
|
|
@ -138,7 +145,7 @@ class LoginWithPhoneNumberScreen extends ViewModelWidget<LoginViewModel> {
|
||||||
];
|
];
|
||||||
|
|
||||||
Widget _buildTitle() => Text(
|
Widget _buildTitle() => Text(
|
||||||
'Welcome Back',
|
LocaleKeys.welcome_back.tr(),
|
||||||
style: style25DG600,
|
style: style25DG600,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
@ -147,7 +154,7 @@ class LoginWithPhoneNumberScreen extends ViewModelWidget<LoginViewModel> {
|
||||||
);
|
);
|
||||||
|
|
||||||
Widget _buildSubtitle() => Text(
|
Widget _buildSubtitle() => Text(
|
||||||
'Enter your phone number. We will send you a confirmation code there',
|
LocaleKeys.enter_phone_number.tr(),
|
||||||
style: style14MG400,
|
style: style14MG400,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
@ -205,9 +212,9 @@ class LoginWithPhoneNumberScreen extends ViewModelWidget<LoginViewModel> {
|
||||||
|
|
||||||
Widget _buildContinueButton(LoginViewModel viewModel) => CustomElevatedButton(
|
Widget _buildContinueButton(LoginViewModel viewModel) => CustomElevatedButton(
|
||||||
height: 55,
|
height: 55,
|
||||||
text: 'Continue',
|
|
||||||
borderRadius: 12,
|
borderRadius: 12,
|
||||||
foregroundColor: kcWhite,
|
foregroundColor: kcWhite,
|
||||||
|
text: LocaleKeys.cont.tr(),
|
||||||
onTap: phoneNumberController.text.isNotEmpty
|
onTap: phoneNumberController.text.isNotEmpty
|
||||||
? () async => await _login(viewModel)
|
? () async => await _login(viewModel)
|
||||||
: null,
|
: null,
|
||||||
|
|
@ -220,12 +227,12 @@ class LoginWithPhoneNumberScreen extends ViewModelWidget<LoginViewModel> {
|
||||||
CustomElevatedButton(
|
CustomElevatedButton(
|
||||||
height: 55,
|
height: 55,
|
||||||
borderRadius: 12,
|
borderRadius: 12,
|
||||||
text: 'Login with Email',
|
|
||||||
backgroundColor: kcWhite,
|
backgroundColor: kcWhite,
|
||||||
leadingIcon: Icons.email,
|
leadingIcon: Icons.email,
|
||||||
borderColor: kcPrimaryColor,
|
borderColor: kcPrimaryColor,
|
||||||
foregroundColor: kcPrimaryColor,
|
|
||||||
onTap: () => viewModel.goTo(0),
|
onTap: () => viewModel.goTo(0),
|
||||||
|
foregroundColor: kcPrimaryColor,
|
||||||
|
text: LocaleKeys.login_with_email.tr(),
|
||||||
);
|
);
|
||||||
|
|
||||||
Widget _buildLoginWithPhoneNumber(LoginViewModel viewModel) =>
|
Widget _buildLoginWithPhoneNumber(LoginViewModel viewModel) =>
|
||||||
|
|
|
||||||
|
|
@ -17,19 +17,18 @@ class OnboardingViewModel extends ReactiveViewModel
|
||||||
|
|
||||||
final _localizationService = locator<LocalizationService>();
|
final _localizationService = locator<LocalizationService>();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<ListenableServiceMixin> get listenableServices => [_googleAuthService,_localizationService];
|
List<ListenableServiceMixin> get listenableServices =>
|
||||||
|
[_googleAuthService, _localizationService];
|
||||||
|
|
||||||
// Google user
|
// Google user
|
||||||
GoogleSignInAccount? get _googleUser => _googleAuthService.googleUser;
|
GoogleSignInAccount? get _googleUser => _googleAuthService.googleUser;
|
||||||
|
|
||||||
GoogleSignInAccount? get googleUser => _googleUser;
|
GoogleSignInAccount? get googleUser => _googleUser;
|
||||||
|
|
||||||
|
|
||||||
// Languages
|
// Languages
|
||||||
Map<String, dynamic> get _selectedLanguage => _localizationService.selectedLanguage;
|
Map<String, dynamic> get _selectedLanguage =>
|
||||||
|
_localizationService.selectedLanguage;
|
||||||
|
|
||||||
Map<String, dynamic> get selectedLanguage => _selectedLanguage;
|
Map<String, dynamic> get selectedLanguage => _selectedLanguage;
|
||||||
|
|
||||||
|
|
@ -218,7 +217,6 @@ class OnboardingViewModel extends ReactiveViewModel
|
||||||
|
|
||||||
List<String> get topics => _topics;
|
List<String> get topics => _topics;
|
||||||
|
|
||||||
|
|
||||||
// User data
|
// User data
|
||||||
final Map<String, dynamic> _userData = {};
|
final Map<String, dynamic> _userData = {};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -88,9 +88,8 @@ class AgeGroupFormScreen extends ViewModelWidget<OnboardingViewModel> {
|
||||||
showBackButton: true,
|
showBackButton: true,
|
||||||
showLanguageSelection: true,
|
showLanguageSelection: true,
|
||||||
onPop: () => _pop(viewModel),
|
onPop: () => _pop(viewModel),
|
||||||
language: viewModel.selectedLanguage['code'],
|
language: viewModel.selectedLanguage['code'],
|
||||||
|
onLanguage: () async => await viewModel.navigateToLanguage(),
|
||||||
onLanguage: () async => await viewModel.navigateToLanguage(),
|
|
||||||
);
|
);
|
||||||
|
|
||||||
Widget _buildTitle() => Text(
|
Widget _buildTitle() => Text(
|
||||||
|
|
|
||||||
|
|
@ -102,9 +102,8 @@ class ChallengeFormScreen extends ViewModelWidget<OnboardingViewModel> {
|
||||||
showBackButton: true,
|
showBackButton: true,
|
||||||
showLanguageSelection: true,
|
showLanguageSelection: true,
|
||||||
onPop: () => _pop(viewModel),
|
onPop: () => _pop(viewModel),
|
||||||
language: viewModel.selectedLanguage['code'],
|
language: viewModel.selectedLanguage['code'],
|
||||||
|
onLanguage: () async => await viewModel.navigateToLanguage(),
|
||||||
onLanguage: () async => await viewModel.navigateToLanguage(),
|
|
||||||
);
|
);
|
||||||
|
|
||||||
Widget _buildTitle() => Text(
|
Widget _buildTitle() => Text(
|
||||||
|
|
|
||||||
|
|
@ -112,8 +112,8 @@ class CountryRegionFormScreen extends ViewModelWidget<OnboardingViewModel> {
|
||||||
showBackButton: true,
|
showBackButton: true,
|
||||||
showLanguageSelection: true,
|
showLanguageSelection: true,
|
||||||
onPop: () => _pop(viewModel),
|
onPop: () => _pop(viewModel),
|
||||||
language: viewModel.selectedLanguage['code'],
|
language: viewModel.selectedLanguage['code'],
|
||||||
onLanguage: () async => await viewModel.navigateToLanguage(),
|
onLanguage: () async => await viewModel.navigateToLanguage(),
|
||||||
);
|
);
|
||||||
|
|
||||||
Widget _buildTitle() => Text(
|
Widget _buildTitle() => Text(
|
||||||
|
|
|
||||||
|
|
@ -88,8 +88,8 @@ class EducationalBackgroundFormScreen
|
||||||
showBackButton: true,
|
showBackButton: true,
|
||||||
showLanguageSelection: true,
|
showLanguageSelection: true,
|
||||||
onPop: () => _pop(viewModel),
|
onPop: () => _pop(viewModel),
|
||||||
language: viewModel.selectedLanguage['code'],
|
language: viewModel.selectedLanguage['code'],
|
||||||
onLanguage: () async => await viewModel.navigateToLanguage(),
|
onLanguage: () async => await viewModel.navigateToLanguage(),
|
||||||
);
|
);
|
||||||
|
|
||||||
Widget _buildTitle() => const Text(
|
Widget _buildTitle() => const Text(
|
||||||
|
|
|
||||||
|
|
@ -88,8 +88,8 @@ class FullNameFormScreen extends ViewModelWidget<OnboardingViewModel> {
|
||||||
Widget _buildAppBar(OnboardingViewModel viewModel) => LargeAppBar(
|
Widget _buildAppBar(OnboardingViewModel viewModel) => LargeAppBar(
|
||||||
showBackButton: false,
|
showBackButton: false,
|
||||||
showLanguageSelection: true,
|
showLanguageSelection: true,
|
||||||
language: viewModel.selectedLanguage['code'],
|
language: viewModel.selectedLanguage['code'],
|
||||||
onLanguage: () async => await viewModel.navigateToLanguage(),
|
onLanguage: () async => await viewModel.navigateToLanguage(),
|
||||||
);
|
);
|
||||||
|
|
||||||
Widget _buildTitle() => const Text(
|
Widget _buildTitle() => const Text(
|
||||||
|
|
|
||||||
|
|
@ -80,9 +80,8 @@ class GenderFormScreen extends ViewModelWidget<OnboardingViewModel> {
|
||||||
showBackButton: true,
|
showBackButton: true,
|
||||||
showLanguageSelection: true,
|
showLanguageSelection: true,
|
||||||
onPop: () => _pop(viewModel),
|
onPop: () => _pop(viewModel),
|
||||||
language: viewModel.selectedLanguage['code'],
|
language: viewModel.selectedLanguage['code'],
|
||||||
|
onLanguage: () async => await viewModel.navigateToLanguage(),
|
||||||
onLanguage: () async => await viewModel.navigateToLanguage(),
|
|
||||||
);
|
);
|
||||||
|
|
||||||
Widget _buildTitle() => Text(
|
Widget _buildTitle() => Text(
|
||||||
|
|
|
||||||
|
|
@ -103,8 +103,8 @@ class LanguageGoalFormScreen extends ViewModelWidget<OnboardingViewModel> {
|
||||||
showBackButton: true,
|
showBackButton: true,
|
||||||
showLanguageSelection: true,
|
showLanguageSelection: true,
|
||||||
onPop: () => _pop(viewModel),
|
onPop: () => _pop(viewModel),
|
||||||
language: viewModel.selectedLanguage['code'],
|
language: viewModel.selectedLanguage['code'],
|
||||||
onLanguage: () async => await viewModel.navigateToLanguage(),
|
onLanguage: () async => await viewModel.navigateToLanguage(),
|
||||||
);
|
);
|
||||||
|
|
||||||
Widget _buildTitle() => Text(
|
Widget _buildTitle() => Text(
|
||||||
|
|
|
||||||
|
|
@ -98,9 +98,8 @@ class LearningGoalFormScreen extends ViewModelWidget<OnboardingViewModel> {
|
||||||
showBackButton: true,
|
showBackButton: true,
|
||||||
showLanguageSelection: true,
|
showLanguageSelection: true,
|
||||||
onPop: () => _pop(viewModel),
|
onPop: () => _pop(viewModel),
|
||||||
language: viewModel.selectedLanguage['code'],
|
language: viewModel.selectedLanguage['code'],
|
||||||
|
onLanguage: () async => await viewModel.navigateToLanguage(),
|
||||||
onLanguage: () async => await viewModel.navigateToLanguage(),
|
|
||||||
);
|
);
|
||||||
|
|
||||||
Widget _buildTitle(OnboardingViewModel viewModel) => Text.rich(
|
Widget _buildTitle(OnboardingViewModel viewModel) => Text.rich(
|
||||||
|
|
|
||||||
|
|
@ -86,9 +86,8 @@ class OccupationFormScreen extends ViewModelWidget<OnboardingViewModel> {
|
||||||
showBackButton: true,
|
showBackButton: true,
|
||||||
showLanguageSelection: true,
|
showLanguageSelection: true,
|
||||||
onPop: () => _pop(viewModel),
|
onPop: () => _pop(viewModel),
|
||||||
language: viewModel.selectedLanguage['code'],
|
language: viewModel.selectedLanguage['code'],
|
||||||
|
onLanguage: () async => await viewModel.navigateToLanguage(),
|
||||||
onLanguage: () async => await viewModel.navigateToLanguage(),
|
|
||||||
);
|
);
|
||||||
|
|
||||||
Widget _buildTitle() => Text(
|
Widget _buildTitle() => Text(
|
||||||
|
|
|
||||||
|
|
@ -58,9 +58,8 @@ class TopicFormScreen extends ViewModelWidget<OnboardingViewModel> {
|
||||||
showBackButton: true,
|
showBackButton: true,
|
||||||
showLanguageSelection: true,
|
showLanguageSelection: true,
|
||||||
onPop: () => _pop(viewModel),
|
onPop: () => _pop(viewModel),
|
||||||
language: viewModel.selectedLanguage['code'],
|
language: viewModel.selectedLanguage['code'],
|
||||||
|
onLanguage: () async => await viewModel.navigateToLanguage(),
|
||||||
onLanguage: () async => await viewModel.navigateToLanguage(),
|
|
||||||
);
|
);
|
||||||
|
|
||||||
Widget _buildExpandedBody(OnboardingViewModel viewModel) =>
|
Widget _buildExpandedBody(OnboardingViewModel viewModel) =>
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_html/flutter_html.dart';
|
||||||
import 'package:stacked/stacked.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 'package:yimaru_app/ui/widgets/privacy_policy_tile.dart';
|
||||||
|
|
||||||
import '../../common/app_colors.dart';
|
import '../../common/app_colors.dart';
|
||||||
|
|
@ -22,7 +24,7 @@ class PrivacyPolicyView extends StackedView<PrivacyPolicyViewModel> {
|
||||||
) =>
|
) =>
|
||||||
_buildScaffoldWrapper(viewModel);
|
_buildScaffoldWrapper(viewModel);
|
||||||
|
|
||||||
Widget _buildScaffoldWrapper(PrivacyPolicyViewModel viewModel) => Scaffold(
|
/* Widget _buildScaffoldWrapper(PrivacyPolicyViewModel viewModel) => Scaffold(
|
||||||
backgroundColor: kcBackgroundColor,
|
backgroundColor: kcBackgroundColor,
|
||||||
body: _buildScaffold(viewModel),
|
body: _buildScaffold(viewModel),
|
||||||
);
|
);
|
||||||
|
|
@ -91,4 +93,62 @@ class PrivacyPolicyView extends StackedView<PrivacyPolicyViewModel> {
|
||||||
);
|
);
|
||||||
|
|
||||||
Widget _buildTile(String title) => PrivacyPolicyTile(title: title);
|
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<Widget> _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,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -30,7 +30,8 @@ class RegisterViewModel extends ReactiveViewModel
|
||||||
final _authenticationService = locator<AuthenticationService>();
|
final _authenticationService = locator<AuthenticationService>();
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<ListenableServiceMixin> get listenableServices => [_googleAuthService,_localizationService];
|
List<ListenableServiceMixin> get listenableServices =>
|
||||||
|
[_googleAuthService, _localizationService];
|
||||||
|
|
||||||
// Google user
|
// Google user
|
||||||
GoogleSignInAccount? get _googleUser => _googleAuthService.googleUser;
|
GoogleSignInAccount? get _googleUser => _googleAuthService.googleUser;
|
||||||
|
|
@ -38,11 +39,11 @@ class RegisterViewModel extends ReactiveViewModel
|
||||||
GoogleSignInAccount? get googleUser => _googleUser;
|
GoogleSignInAccount? get googleUser => _googleUser;
|
||||||
|
|
||||||
// Languages
|
// Languages
|
||||||
Map<String, dynamic> get _selectedLanguage => _localizationService.selectedLanguage;
|
Map<String, dynamic> get _selectedLanguage =>
|
||||||
|
_localizationService.selectedLanguage;
|
||||||
|
|
||||||
Map<String, dynamic> get selectedLanguage => _selectedLanguage;
|
Map<String, dynamic> get selectedLanguage => _selectedLanguage;
|
||||||
|
|
||||||
|
|
||||||
// Navigation
|
// Navigation
|
||||||
int _currentPage = 0;
|
int _currentPage = 0;
|
||||||
|
|
||||||
|
|
@ -275,11 +276,9 @@ class RegisterViewModel extends ReactiveViewModel
|
||||||
Future<void> navigateToLanguage() async =>
|
Future<void> navigateToLanguage() async =>
|
||||||
await _navigationService.navigateToLanguageView();
|
await _navigationService.navigateToLanguageView();
|
||||||
|
|
||||||
|
|
||||||
Future<void> navigateToPrivacyPolicy() async =>
|
Future<void> navigateToPrivacyPolicy() async =>
|
||||||
await _navigationService.navigateToPrivacyPolicyView();
|
await _navigationService.navigateToPrivacyPolicyView();
|
||||||
|
|
||||||
|
|
||||||
Future<void> navigateToTermsAndConditions() async =>
|
Future<void> navigateToTermsAndConditions() async =>
|
||||||
await _navigationService.navigateToTermsAndConditionsView();
|
await _navigationService.navigateToTermsAndConditionsView();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
import 'package:flutter/gestures.dart';
|
import 'package:flutter/gestures.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:stacked/stacked.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/app_colors.dart';
|
||||||
import '../../../common/enmus.dart';
|
import '../../../common/enmus.dart';
|
||||||
|
import '../../../common/translations/locale_keys.g.dart';
|
||||||
import '../../../common/ui_helpers.dart';
|
import '../../../common/ui_helpers.dart';
|
||||||
import '../../../widgets/custom_elevated_button.dart';
|
import '../../../widgets/custom_elevated_button.dart';
|
||||||
import '../../../widgets/large_app_bar.dart';
|
import '../../../widgets/large_app_bar.dart';
|
||||||
|
|
@ -43,7 +45,12 @@ class CreatePasswordScreen extends ViewModelWidget<RegisterViewModel> {
|
||||||
|
|
||||||
Widget _buildScaffoldWrapper(RegisterViewModel viewModel) => Scaffold(
|
Widget _buildScaffoldWrapper(RegisterViewModel viewModel) => Scaffold(
|
||||||
backgroundColor: kcBackgroundColor,
|
backgroundColor: kcBackgroundColor,
|
||||||
body: _buildScaffoldStack(viewModel),
|
body: _buildScaffoldContainer(viewModel),
|
||||||
|
);
|
||||||
|
|
||||||
|
Widget _buildScaffoldContainer(RegisterViewModel viewModel) => Container(
|
||||||
|
decoration: bgDecoration,
|
||||||
|
child: _buildScaffoldStack(viewModel),
|
||||||
);
|
);
|
||||||
|
|
||||||
Widget _buildScaffoldStack(RegisterViewModel viewModel) => Stack(
|
Widget _buildScaffoldStack(RegisterViewModel viewModel) => Stack(
|
||||||
|
|
@ -68,11 +75,9 @@ class CreatePasswordScreen extends ViewModelWidget<RegisterViewModel> {
|
||||||
showBackButton: true,
|
showBackButton: true,
|
||||||
onPop: viewModel.goBack,
|
onPop: viewModel.goBack,
|
||||||
showLanguageSelection: true,
|
showLanguageSelection: true,
|
||||||
language: viewModel.selectedLanguage['code'],
|
language: viewModel.selectedLanguage['code'],
|
||||||
|
onLanguage: () async => await viewModel.navigateToLanguage(),
|
||||||
onLanguage: ()async => await viewModel.navigateToLanguage(),
|
);
|
||||||
|
|
||||||
);
|
|
||||||
|
|
||||||
Widget _buildExpandedBody(RegisterViewModel viewModel) =>
|
Widget _buildExpandedBody(RegisterViewModel viewModel) =>
|
||||||
Expanded(child: _buildColumnScroller(viewModel));
|
Expanded(child: _buildColumnScroller(viewModel));
|
||||||
|
|
@ -97,7 +102,7 @@ class CreatePasswordScreen extends ViewModelWidget<RegisterViewModel> {
|
||||||
verticalSpaceMedium,
|
verticalSpaceMedium,
|
||||||
_buildTitle(),
|
_buildTitle(),
|
||||||
verticalSpaceMedium,
|
verticalSpaceMedium,
|
||||||
_buildPasswordLabel('Password'),
|
_buildPasswordLabel(LocaleKeys.password.tr()),
|
||||||
verticalSpaceSmall,
|
verticalSpaceSmall,
|
||||||
_buildPasswordFormField(viewModel),
|
_buildPasswordFormField(viewModel),
|
||||||
if (viewModel.hasPasswordValidationMessage && viewModel.focusPassword)
|
if (viewModel.hasPasswordValidationMessage && viewModel.focusPassword)
|
||||||
|
|
@ -105,7 +110,7 @@ class CreatePasswordScreen extends ViewModelWidget<RegisterViewModel> {
|
||||||
if (viewModel.hasPasswordValidationMessage && viewModel.focusPassword)
|
if (viewModel.hasPasswordValidationMessage && viewModel.focusPassword)
|
||||||
_buildPasswordValidationWrapper(viewModel),
|
_buildPasswordValidationWrapper(viewModel),
|
||||||
verticalSpaceMedium,
|
verticalSpaceMedium,
|
||||||
_buildPasswordLabel('Confirm Password'),
|
_buildPasswordLabel(LocaleKeys.confirm_password.tr()),
|
||||||
verticalSpaceSmall,
|
verticalSpaceSmall,
|
||||||
_buildConfirmPasswordFormField(viewModel),
|
_buildConfirmPasswordFormField(viewModel),
|
||||||
if (viewModel.hasConfirmPasswordValidationMessage &&
|
if (viewModel.hasConfirmPasswordValidationMessage &&
|
||||||
|
|
@ -125,13 +130,9 @@ class CreatePasswordScreen extends ViewModelWidget<RegisterViewModel> {
|
||||||
verticalSpaceMedium
|
verticalSpaceMedium
|
||||||
];
|
];
|
||||||
|
|
||||||
Widget _buildTitle() => const Text(
|
Widget _buildTitle() => Text(
|
||||||
'Create Password',
|
LocaleKeys.create_password.tr(),
|
||||||
style: TextStyle(
|
style: style25DG600,
|
||||||
fontSize: 25,
|
|
||||||
color: kcDarkGrey,
|
|
||||||
fontWeight: FontWeight.w600,
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
|
|
||||||
Widget _buildPasswordLabel(String label) => CustomFormLabel(
|
Widget _buildPasswordLabel(String label) => CustomFormLabel(
|
||||||
|
|
@ -144,7 +145,7 @@ class CreatePasswordScreen extends ViewModelWidget<RegisterViewModel> {
|
||||||
onTap: viewModel.setPasswordFocus,
|
onTap: viewModel.setPasswordFocus,
|
||||||
obscureText: viewModel.obscurePassword,
|
obscureText: viewModel.obscurePassword,
|
||||||
decoration: inputDecoration(
|
decoration: inputDecoration(
|
||||||
hint: 'Password',
|
hint: LocaleKeys.password.tr(),
|
||||||
focus: viewModel.focusPassword,
|
focus: viewModel.focusPassword,
|
||||||
suffix: _buildObscurePassword(viewModel),
|
suffix: _buildObscurePassword(viewModel),
|
||||||
filled: passwordController.text.isNotEmpty),
|
filled: passwordController.text.isNotEmpty),
|
||||||
|
|
@ -166,11 +167,7 @@ class CreatePasswordScreen extends ViewModelWidget<RegisterViewModel> {
|
||||||
|
|
||||||
Widget _buildPasswordValidator(RegisterViewModel viewModel) => Text(
|
Widget _buildPasswordValidator(RegisterViewModel viewModel) => Text(
|
||||||
viewModel.passwordValidationMessage!,
|
viewModel.passwordValidationMessage!,
|
||||||
style: const TextStyle(
|
style: style12R700,
|
||||||
fontSize: 12,
|
|
||||||
color: Colors.red,
|
|
||||||
fontWeight: FontWeight.w700,
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
|
|
||||||
Widget _buildConfirmPasswordFormField(RegisterViewModel viewModel) =>
|
Widget _buildConfirmPasswordFormField(RegisterViewModel viewModel) =>
|
||||||
|
|
@ -182,8 +179,8 @@ class CreatePasswordScreen extends ViewModelWidget<RegisterViewModel> {
|
||||||
password: passwordController.text,
|
password: passwordController.text,
|
||||||
confirmPassword: confirmPasswordController.text),
|
confirmPassword: confirmPasswordController.text),
|
||||||
decoration: inputDecoration(
|
decoration: inputDecoration(
|
||||||
hint: 'Confirm Password',
|
|
||||||
focus: viewModel.focusConfirmPassword,
|
focus: viewModel.focusConfirmPassword,
|
||||||
|
hint: LocaleKeys.confirm_password.tr(),
|
||||||
suffix: _buildObscureConfirmPassword(viewModel),
|
suffix: _buildObscureConfirmPassword(viewModel),
|
||||||
filled: confirmPasswordController.text.isNotEmpty),
|
filled: confirmPasswordController.text.isNotEmpty),
|
||||||
);
|
);
|
||||||
|
|
@ -214,14 +211,15 @@ class CreatePasswordScreen extends ViewModelWidget<RegisterViewModel> {
|
||||||
|
|
||||||
Widget _buildCharLengthValidator(RegisterViewModel viewModel) =>
|
Widget _buildCharLengthValidator(RegisterViewModel viewModel) =>
|
||||||
ValidatorListTile(
|
ValidatorListTile(
|
||||||
backgroundColor: viewModel.length ? kcPrimaryColor : kcLightGrey,
|
label: LocaleKeys.eight_character_minimum.tr(),
|
||||||
label: '8 characters minimum');
|
backgroundColor: viewModel.length ? kcPrimaryColor : kcLightGrey,
|
||||||
|
);
|
||||||
|
|
||||||
Widget _buildPasswordMatchValidator(RegisterViewModel viewModel) =>
|
Widget _buildPasswordMatchValidator(RegisterViewModel viewModel) =>
|
||||||
ValidatorListTile(
|
ValidatorListTile(
|
||||||
backgroundColor:
|
label: LocaleKeys.password_match.tr(),
|
||||||
viewModel.passwordMatch ? kcPrimaryColor : kcLightGrey,
|
backgroundColor: viewModel.passwordMatch ? kcPrimaryColor : kcLightGrey,
|
||||||
label: 'password match');
|
);
|
||||||
|
|
||||||
Widget _buildCheckBox(RegisterViewModel viewMode) => CheckboxListTile(
|
Widget _buildCheckBox(RegisterViewModel viewMode) => CheckboxListTile(
|
||||||
value: viewMode.agree,
|
value: viewMode.agree,
|
||||||
|
|
@ -232,18 +230,18 @@ class CreatePasswordScreen extends ViewModelWidget<RegisterViewModel> {
|
||||||
|
|
||||||
Widget _buildCheckBoxTitle(RegisterViewModel viewMode) => Text.rich(
|
Widget _buildCheckBoxTitle(RegisterViewModel viewMode) => Text.rich(
|
||||||
TextSpan(
|
TextSpan(
|
||||||
text: 'By clicking "Sign Up", you agree to our',
|
text: LocaleKeys.sign_up_agreement.tr(),
|
||||||
style: style14DG400,
|
style: style14DG400,
|
||||||
children: [
|
children: [
|
||||||
TextSpan(
|
TextSpan(
|
||||||
text: ' Terms of Service',
|
text: ' ${LocaleKeys.terms_of_services.tr()}',
|
||||||
style: style14P600,
|
style: style14P600,
|
||||||
recognizer: TapGestureRecognizer()
|
recognizer: TapGestureRecognizer()
|
||||||
..onTap = () => viewMode.navigateToTermsAndConditions()),
|
..onTap = () => viewMode.navigateToTermsAndConditions()),
|
||||||
TextSpan(text: ' and ', style: style14DG400),
|
TextSpan(text: ' ${LocaleKeys.and.tr()} ', style: style14DG400),
|
||||||
TextSpan(
|
TextSpan(
|
||||||
text: 'Privacy Policy',
|
|
||||||
style: style14P600,
|
style: style14P600,
|
||||||
|
text: LocaleKeys.privacy_policy.tr(),
|
||||||
recognizer: TapGestureRecognizer()
|
recognizer: TapGestureRecognizer()
|
||||||
..onTap = () => viewMode.navigateToPrivacyPolicy()),
|
..onTap = () => viewMode.navigateToPrivacyPolicy()),
|
||||||
]),
|
]),
|
||||||
|
|
@ -252,9 +250,9 @@ class CreatePasswordScreen extends ViewModelWidget<RegisterViewModel> {
|
||||||
Widget _buildSignUpButton(RegisterViewModel viewModel) =>
|
Widget _buildSignUpButton(RegisterViewModel viewModel) =>
|
||||||
CustomElevatedButton(
|
CustomElevatedButton(
|
||||||
height: 55,
|
height: 55,
|
||||||
text: 'Sign Up',
|
|
||||||
borderRadius: 12,
|
borderRadius: 12,
|
||||||
foregroundColor: kcWhite,
|
foregroundColor: kcWhite,
|
||||||
|
text: LocaleKeys.register.tr(),
|
||||||
onTap: passwordController.text.isNotEmpty &&
|
onTap: passwordController.text.isNotEmpty &&
|
||||||
confirmPasswordController.text.isNotEmpty &&
|
confirmPasswordController.text.isNotEmpty &&
|
||||||
viewModel.length &&
|
viewModel.length &&
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,11 @@
|
||||||
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:stacked/stacked.dart';
|
import 'package:stacked/stacked.dart';
|
||||||
import 'package:yimaru_app/ui/common/enmus.dart';
|
import 'package:yimaru_app/ui/common/enmus.dart';
|
||||||
import 'package:yimaru_app/ui/widgets/login_account.dart';
|
import 'package:yimaru_app/ui/widgets/login_account.dart';
|
||||||
|
|
||||||
import '../../../common/app_colors.dart';
|
import '../../../common/app_colors.dart';
|
||||||
|
import '../../../common/translations/locale_keys.g.dart';
|
||||||
import '../../../common/ui_helpers.dart';
|
import '../../../common/ui_helpers.dart';
|
||||||
import '../../../widgets/custom_elevated_button.dart';
|
import '../../../widgets/custom_elevated_button.dart';
|
||||||
import '../../../widgets/large_app_bar.dart';
|
import '../../../widgets/large_app_bar.dart';
|
||||||
|
|
@ -46,7 +48,15 @@ class RegisterWithEmailScreen extends ViewModelWidget<RegisterViewModel> {
|
||||||
required RegisterViewModel viewModel}) =>
|
required RegisterViewModel viewModel}) =>
|
||||||
Scaffold(
|
Scaffold(
|
||||||
backgroundColor: kcBackgroundColor,
|
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(
|
Widget _buildScaffoldStack(
|
||||||
|
|
@ -81,11 +91,9 @@ class RegisterWithEmailScreen extends ViewModelWidget<RegisterViewModel> {
|
||||||
showBackButton: true,
|
showBackButton: true,
|
||||||
onPop: viewModel.goBack,
|
onPop: viewModel.goBack,
|
||||||
showLanguageSelection: true,
|
showLanguageSelection: true,
|
||||||
language: viewModel.selectedLanguage['code'],
|
language: viewModel.selectedLanguage['code'],
|
||||||
|
onLanguage: () async => await viewModel.navigateToLanguage(),
|
||||||
onLanguage: ()async => await viewModel.navigateToLanguage(),
|
);
|
||||||
|
|
||||||
);
|
|
||||||
|
|
||||||
Widget _buildExpandedBody(
|
Widget _buildExpandedBody(
|
||||||
{required BuildContext context,
|
{required BuildContext context,
|
||||||
|
|
@ -144,13 +152,9 @@ class RegisterWithEmailScreen extends ViewModelWidget<RegisterViewModel> {
|
||||||
_buildEmailValidatorWrapper(viewModel),
|
_buildEmailValidatorWrapper(viewModel),
|
||||||
];
|
];
|
||||||
|
|
||||||
Widget _buildTitle() => const Text(
|
Widget _buildTitle() => Text(
|
||||||
'Create an Account',
|
LocaleKeys.create_account.tr(),
|
||||||
style: TextStyle(
|
style: style25DG600,
|
||||||
fontSize: 25,
|
|
||||||
color: kcDarkGrey,
|
|
||||||
fontWeight: FontWeight.w600,
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
|
|
||||||
Widget _buildSubtitleWrapper(RegisterViewModel viewModel) => LoginAccount(
|
Widget _buildSubtitleWrapper(RegisterViewModel viewModel) => LoginAccount(
|
||||||
|
|
@ -159,10 +163,10 @@ class RegisterWithEmailScreen extends ViewModelWidget<RegisterViewModel> {
|
||||||
|
|
||||||
Widget _buildEmailFormField(RegisterViewModel viewModel) => TextFormField(
|
Widget _buildEmailFormField(RegisterViewModel viewModel) => TextFormField(
|
||||||
controller: emailController,
|
controller: emailController,
|
||||||
keyboardType: TextInputType.emailAddress,
|
|
||||||
onTap: viewModel.setEmailFocus,
|
onTap: viewModel.setEmailFocus,
|
||||||
|
keyboardType: TextInputType.emailAddress,
|
||||||
decoration: inputDecoration(
|
decoration: inputDecoration(
|
||||||
hint: 'Email',
|
hint: LocaleKeys.email.tr(),
|
||||||
focus: viewModel.focusEmail,
|
focus: viewModel.focusEmail,
|
||||||
filled: emailController.text.isNotEmpty),
|
filled: emailController.text.isNotEmpty),
|
||||||
);
|
);
|
||||||
|
|
@ -174,11 +178,7 @@ class RegisterWithEmailScreen extends ViewModelWidget<RegisterViewModel> {
|
||||||
|
|
||||||
Widget _buildEmailValidator(RegisterViewModel viewModel) => Text(
|
Widget _buildEmailValidator(RegisterViewModel viewModel) => Text(
|
||||||
viewModel.emailValidationMessage!,
|
viewModel.emailValidationMessage!,
|
||||||
style: const TextStyle(
|
style: style12R700,
|
||||||
fontSize: 12,
|
|
||||||
color: Colors.red,
|
|
||||||
fontWeight: FontWeight.w700,
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
|
|
||||||
Widget _buildLowerColumn(RegisterViewModel viewModel) => Column(
|
Widget _buildLowerColumn(RegisterViewModel viewModel) => Column(
|
||||||
|
|
@ -198,9 +198,9 @@ class RegisterWithEmailScreen extends ViewModelWidget<RegisterViewModel> {
|
||||||
CustomElevatedButton(
|
CustomElevatedButton(
|
||||||
height: 55,
|
height: 55,
|
||||||
safe: false,
|
safe: false,
|
||||||
text: 'Continue',
|
|
||||||
borderRadius: 12,
|
borderRadius: 12,
|
||||||
foregroundColor: kcWhite,
|
foregroundColor: kcWhite,
|
||||||
|
text: LocaleKeys.cont.tr(),
|
||||||
onTap: emailController.text.isNotEmpty &&
|
onTap: emailController.text.isNotEmpty &&
|
||||||
!viewModel.hasEmailValidationMessage
|
!viewModel.hasEmailValidationMessage
|
||||||
? () => _addUserData(viewModel)
|
? () => _addUserData(viewModel)
|
||||||
|
|
@ -216,9 +216,9 @@ class RegisterWithEmailScreen extends ViewModelWidget<RegisterViewModel> {
|
||||||
height: 55,
|
height: 55,
|
||||||
borderRadius: 12,
|
borderRadius: 12,
|
||||||
backgroundColor: kcWhite,
|
backgroundColor: kcWhite,
|
||||||
text: 'Login with Google',
|
|
||||||
borderColor: kcPrimaryColor,
|
borderColor: kcPrimaryColor,
|
||||||
foregroundColor: kcPrimaryColor,
|
foregroundColor: kcPrimaryColor,
|
||||||
|
text: LocaleKeys.register_with_google.tr(),
|
||||||
leadingImage: 'assets/icons/google.png',
|
leadingImage: 'assets/icons/google.png',
|
||||||
onTap: () async => await viewModel.registerWithGoogle(),
|
onTap: () async => await viewModel.registerWithGoogle(),
|
||||||
);
|
);
|
||||||
|
|
@ -233,8 +233,8 @@ class RegisterWithEmailScreen extends ViewModelWidget<RegisterViewModel> {
|
||||||
leadingIcon: Icons.phone,
|
leadingIcon: Icons.phone,
|
||||||
borderColor: kcPrimaryColor,
|
borderColor: kcPrimaryColor,
|
||||||
foregroundColor: kcPrimaryColor,
|
foregroundColor: kcPrimaryColor,
|
||||||
text: 'Register with Phone Number',
|
|
||||||
onTap: () => viewModel.goTo(page: 1),
|
onTap: () => viewModel.goTo(page: 1),
|
||||||
|
text: LocaleKeys.register_with_phone.tr(),
|
||||||
);
|
);
|
||||||
|
|
||||||
Widget _buildRegisterWithEmailState(RegisterViewModel viewModel) =>
|
Widget _buildRegisterWithEmailState(RegisterViewModel viewModel) =>
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,8 @@
|
||||||
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
import 'package:stacked/stacked.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/login_account.dart';
|
||||||
import 'package:yimaru_app/ui/widgets/option_text_divider.dart';
|
import 'package:yimaru_app/ui/widgets/option_text_divider.dart';
|
||||||
|
|
||||||
|
|
@ -49,7 +51,15 @@ class RegisterWithPhoneNumberScreen extends ViewModelWidget<RegisterViewModel> {
|
||||||
required RegisterViewModel viewModel}) =>
|
required RegisterViewModel viewModel}) =>
|
||||||
Scaffold(
|
Scaffold(
|
||||||
backgroundColor: kcBackgroundColor,
|
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(
|
Widget _buildScaffoldStack(
|
||||||
|
|
@ -84,11 +94,9 @@ class RegisterWithPhoneNumberScreen extends ViewModelWidget<RegisterViewModel> {
|
||||||
showBackButton: true,
|
showBackButton: true,
|
||||||
onPop: viewModel.goBack,
|
onPop: viewModel.goBack,
|
||||||
showLanguageSelection: true,
|
showLanguageSelection: true,
|
||||||
language: viewModel.selectedLanguage['code'],
|
language: viewModel.selectedLanguage['code'],
|
||||||
|
onLanguage: () async => await viewModel.navigateToLanguage(),
|
||||||
onLanguage: ()async => await viewModel.navigateToLanguage(),
|
);
|
||||||
|
|
||||||
);
|
|
||||||
|
|
||||||
Widget _buildExpandedBody(
|
Widget _buildExpandedBody(
|
||||||
{required BuildContext context,
|
{required BuildContext context,
|
||||||
|
|
@ -152,7 +160,7 @@ class RegisterWithPhoneNumberScreen extends ViewModelWidget<RegisterViewModel> {
|
||||||
];
|
];
|
||||||
|
|
||||||
Widget _buildTitle() => Text(
|
Widget _buildTitle() => Text(
|
||||||
'Create an Account',
|
LocaleKeys.create_account.tr(),
|
||||||
style: style25DG600,
|
style: style25DG600,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
@ -161,7 +169,7 @@ class RegisterWithPhoneNumberScreen extends ViewModelWidget<RegisterViewModel> {
|
||||||
);
|
);
|
||||||
|
|
||||||
Widget _buildSubtitle() => Text(
|
Widget _buildSubtitle() => Text(
|
||||||
'Enter your phone number. We will send you a confirmation code there',
|
LocaleKeys.enter_phone_number.tr(),
|
||||||
style: style14MG400,
|
style: style14MG400,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
@ -221,9 +229,9 @@ class RegisterWithPhoneNumberScreen extends ViewModelWidget<RegisterViewModel> {
|
||||||
Widget _buildContinueButton(RegisterViewModel viewModel) =>
|
Widget _buildContinueButton(RegisterViewModel viewModel) =>
|
||||||
CustomElevatedButton(
|
CustomElevatedButton(
|
||||||
height: 55,
|
height: 55,
|
||||||
text: 'Continue',
|
|
||||||
borderRadius: 12,
|
borderRadius: 12,
|
||||||
foregroundColor: kcWhite,
|
foregroundColor: kcWhite,
|
||||||
|
text: LocaleKeys.cont.tr(),
|
||||||
onTap: phoneNumberController.text.isNotEmpty
|
onTap: phoneNumberController.text.isNotEmpty
|
||||||
? () async => await _addUserData(viewModel)
|
? () async => await _addUserData(viewModel)
|
||||||
: null,
|
: null,
|
||||||
|
|
@ -239,9 +247,9 @@ class RegisterWithPhoneNumberScreen extends ViewModelWidget<RegisterViewModel> {
|
||||||
backgroundColor: kcWhite,
|
backgroundColor: kcWhite,
|
||||||
leadingIcon: Icons.email,
|
leadingIcon: Icons.email,
|
||||||
borderColor: kcPrimaryColor,
|
borderColor: kcPrimaryColor,
|
||||||
text: 'Register with Email',
|
|
||||||
foregroundColor: kcPrimaryColor,
|
foregroundColor: kcPrimaryColor,
|
||||||
onTap: () => viewModel.goTo(page: 0),
|
onTap: () => viewModel.goTo(page: 0),
|
||||||
|
text: LocaleKeys.register_with_email.tr(),
|
||||||
);
|
);
|
||||||
|
|
||||||
Widget _buildRegisterWithPhoneState(RegisterViewModel viewModel) =>
|
Widget _buildRegisterWithPhoneState(RegisterViewModel viewModel) =>
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,9 @@
|
||||||
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_timer_countdown/flutter_timer_countdown.dart';
|
import 'package:flutter_timer_countdown/flutter_timer_countdown.dart';
|
||||||
import 'package:pinput/pinput.dart';
|
import 'package:pinput/pinput.dart';
|
||||||
import 'package:stacked/stacked.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/views/register/register_viewmodel.dart';
|
||||||
import 'package:yimaru_app/ui/widgets/custom_cursor.dart';
|
import 'package:yimaru_app/ui/widgets/custom_cursor.dart';
|
||||||
|
|
||||||
|
|
@ -60,7 +62,15 @@ class RegistrationOtpScreen extends ViewModelWidget<RegisterViewModel> {
|
||||||
required RegisterViewModel viewModel}) =>
|
required RegisterViewModel viewModel}) =>
|
||||||
Scaffold(
|
Scaffold(
|
||||||
backgroundColor: kcBackgroundColor,
|
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(
|
Widget _buildScaffoldStack(
|
||||||
|
|
@ -160,7 +170,7 @@ class RegistrationOtpScreen extends ViewModelWidget<RegisterViewModel> {
|
||||||
];
|
];
|
||||||
|
|
||||||
Widget _buildTitle() => Text(
|
Widget _buildTitle() => Text(
|
||||||
'Verification Code',
|
LocaleKeys.verification_code.tr(),
|
||||||
style: style25DG600,
|
style: style25DG600,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
@ -174,7 +184,7 @@ class RegistrationOtpScreen extends ViewModelWidget<RegisterViewModel> {
|
||||||
: Container();
|
: Container();
|
||||||
|
|
||||||
Widget _buildPhoneSubtitle() => Text(
|
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,
|
softWrap: false,
|
||||||
style: style14DG400,
|
style: style14DG400,
|
||||||
);
|
);
|
||||||
|
|
@ -183,7 +193,7 @@ class RegistrationOtpScreen extends ViewModelWidget<RegisterViewModel> {
|
||||||
emailController.text.isNotEmpty ? _buildEmailSubtitle() : Container();
|
emailController.text.isNotEmpty ? _buildEmailSubtitle() : Container();
|
||||||
|
|
||||||
Widget _buildEmailSubtitle() => Text(
|
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,
|
softWrap: false,
|
||||||
style: style14DG400,
|
style: style14DG400,
|
||||||
);
|
);
|
||||||
|
|
@ -229,7 +239,7 @@ class RegistrationOtpScreen extends ViewModelWidget<RegisterViewModel> {
|
||||||
child: _buildResendText());
|
child: _buildResendText());
|
||||||
|
|
||||||
Widget _buildResendText() => Text(
|
Widget _buildResendText() => Text(
|
||||||
'Resend code',
|
LocaleKeys.resend_code.tr(),
|
||||||
style: style14P600.copyWith(fontStyle: FontStyle.italic),
|
style: style14P600.copyWith(fontStyle: FontStyle.italic),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
@ -241,7 +251,8 @@ class RegistrationOtpScreen extends ViewModelWidget<RegisterViewModel> {
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
|
|
||||||
Widget _buildCountdownText() => Text('Resend code in ', style: style14DG400);
|
Widget _buildCountdownText() =>
|
||||||
|
Text('${LocaleKeys.resend_code_in.tr()} ', style: style14DG400);
|
||||||
|
|
||||||
Widget _buildTimer(RegisterViewModel viewModel) => TimerCountdown(
|
Widget _buildTimer(RegisterViewModel viewModel) => TimerCountdown(
|
||||||
enableDescriptions: false,
|
enableDescriptions: false,
|
||||||
|
|
@ -260,9 +271,9 @@ class RegistrationOtpScreen extends ViewModelWidget<RegisterViewModel> {
|
||||||
Widget _buildContinueButton(RegisterViewModel viewModel) =>
|
Widget _buildContinueButton(RegisterViewModel viewModel) =>
|
||||||
CustomElevatedButton(
|
CustomElevatedButton(
|
||||||
height: 55,
|
height: 55,
|
||||||
text: 'Continue',
|
|
||||||
borderRadius: 12,
|
borderRadius: 12,
|
||||||
foregroundColor: kcWhite,
|
foregroundColor: kcWhite,
|
||||||
|
text: LocaleKeys.cont.tr(),
|
||||||
backgroundColor:
|
backgroundColor:
|
||||||
otpController.text.length == 6 && !viewModel.hasOtpValidationMessage
|
otpController.text.length == 6 && !viewModel.hasOtpValidationMessage
|
||||||
? kcPrimaryColor
|
? kcPrimaryColor
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/scheduler.dart';
|
import 'package:flutter/scheduler.dart';
|
||||||
import 'package:flutter_svg/svg.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/app_colors.dart';
|
||||||
import '../../common/enmus.dart';
|
import '../../common/enmus.dart';
|
||||||
|
import '../../common/translations/locale_keys.g.dart';
|
||||||
import 'startup_viewmodel.dart';
|
import 'startup_viewmodel.dart';
|
||||||
|
|
||||||
class StartupView extends StackedView<StartupViewModel> {
|
class StartupView extends StackedView<StartupViewModel> {
|
||||||
final String label;
|
final String? label;
|
||||||
const StartupView({Key? key, this.label = 'Loading'}) : super(key: key);
|
const StartupView({Key? key, this.label}) : super(key: key);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget builder(
|
Widget builder(
|
||||||
|
|
@ -31,7 +33,8 @@ class StartupView extends StackedView<StartupViewModel> {
|
||||||
? _buildStartUpView()
|
? _buildStartUpView()
|
||||||
: _buildScaffold();
|
: _buildScaffold();
|
||||||
|
|
||||||
Widget _buildStartUpView() => const StartupView(label: 'Checking user info');
|
Widget _buildStartUpView() =>
|
||||||
|
StartupView(label: LocaleKeys.checking_user_info.tr());
|
||||||
|
|
||||||
Widget _buildScaffold() => Stack(
|
Widget _buildScaffold() => Stack(
|
||||||
children: _buildScaffoldChildren(),
|
children: _buildScaffoldChildren(),
|
||||||
|
|
@ -78,7 +81,8 @@ class StartupView extends StackedView<StartupViewModel> {
|
||||||
_buildIndicatorWrapper(),
|
_buildIndicatorWrapper(),
|
||||||
];
|
];
|
||||||
|
|
||||||
Widget _buildLoadingText() => Text('$label ...', style: style16W600);
|
Widget _buildLoadingText() =>
|
||||||
|
Text('${label ?? LocaleKeys.loading.tr()} ...', style: style16W600);
|
||||||
|
|
||||||
Widget _buildIndicatorWrapper() => SizedBox(
|
Widget _buildIndicatorWrapper() => SizedBox(
|
||||||
width: 16,
|
width: 16,
|
||||||
|
|
|
||||||
|
|
@ -34,7 +34,7 @@ class StartupViewModel extends ReactiveViewModel {
|
||||||
final firstTimeInstall = await _authenticationService.isFirstTimeInstall();
|
final firstTimeInstall = await _authenticationService.isFirstTimeInstall();
|
||||||
|
|
||||||
if (firstTimeInstall) {
|
if (firstTimeInstall) {
|
||||||
await _navigationService.replaceWithWelcomeView();
|
await _navigationService.replaceWithLandingView();
|
||||||
} else {
|
} else {
|
||||||
if (loggedIn) {
|
if (loggedIn) {
|
||||||
await _authenticationService.getUser();
|
await _authenticationService.getUser();
|
||||||
|
|
@ -56,12 +56,9 @@ class StartupViewModel extends ReactiveViewModel {
|
||||||
label: 'Check you internet connection',
|
label: 'Check you internet connection',
|
||||||
onTap: () async => await _getProfileStatus());
|
onTap: () async => await _getProfileStatus());
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Future<void> replaceWithOnboarding() async =>
|
Future<void> replaceWithOnboarding() async =>
|
||||||
await _navigationService.replaceWithOnboardingView();
|
await _navigationService.replaceWithOnboardingView();
|
||||||
|
|
||||||
|
|
||||||
// Remote api calls
|
// Remote api calls
|
||||||
|
|
||||||
// Get profile status
|
// Get profile status
|
||||||
|
|
|
||||||
|
|
@ -73,38 +73,12 @@ class TermsAndConditionsView extends StackedView<TermsAndConditionsViewModel> {
|
||||||
|
|
||||||
Widget _buildMenuColumnScrollView(TermsAndConditionsViewModel viewModel) =>
|
Widget _buildMenuColumnScrollView(TermsAndConditionsViewModel viewModel) =>
|
||||||
SingleChildScrollView(
|
SingleChildScrollView(
|
||||||
child: _buildContentColumn(),
|
child: _buildContent(),
|
||||||
);
|
);
|
||||||
|
|
||||||
Widget _buildContentColumn() => Column(
|
|
||||||
mainAxisSize: MainAxisSize.min,
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
children: _buildContentColumnChildren(),
|
|
||||||
);
|
|
||||||
|
|
||||||
List<Widget> _buildContentColumnChildren() => [
|
|
||||||
_buildContent(),
|
|
||||||
verticalSpaceMedium,
|
|
||||||
// _buildDownloadButtonWrapper(),
|
|
||||||
];
|
|
||||||
|
|
||||||
Widget _buildContent() => Html(
|
Widget _buildContent() => Html(
|
||||||
data: ksTerms,
|
data: ksTerms,
|
||||||
shrinkWrap: true,
|
shrinkWrap: true,
|
||||||
style: htmlStyle,
|
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,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,6 @@ import 'package:flutter/material.dart';
|
||||||
import 'package:yimaru_app/ui/common/helper_functions.dart';
|
import 'package:yimaru_app/ui/common/helper_functions.dart';
|
||||||
|
|
||||||
import '../common/app_colors.dart';
|
import '../common/app_colors.dart';
|
||||||
import '../common/app_strings.dart';
|
|
||||||
import '../common/ui_helpers.dart';
|
import '../common/ui_helpers.dart';
|
||||||
import 'custom_elevated_button.dart';
|
import 'custom_elevated_button.dart';
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:stacked/stacked.dart';
|
import 'package:stacked/stacked.dart';
|
||||||
import 'package:yimaru_app/models/course_unit.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/common/enmus.dart';
|
||||||
import 'package:yimaru_app/ui/widgets/course_module_tile_small.dart';
|
import 'package:yimaru_app/ui/widgets/course_module_tile_small.dart';
|
||||||
import 'package:yimaru_app/ui/widgets/custom_linear_progress_indicator.dart';
|
import 'package:yimaru_app/ui/widgets/custom_linear_progress_indicator.dart';
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
import '../common/app_colors.dart';
|
import '../common/translations/locale_keys.g.dart';
|
||||||
import '../common/ui_helpers.dart';
|
import '../common/ui_helpers.dart';
|
||||||
|
|
||||||
class LoginAccount extends StatelessWidget {
|
class LoginAccount extends StatelessWidget {
|
||||||
|
|
@ -18,9 +19,9 @@ class LoginAccount extends StatelessWidget {
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
|
|
||||||
Widget _buildLeadingText() => const Text(
|
Widget _buildLeadingText() => Text(
|
||||||
'Already have an account? ',
|
LocaleKeys.already_have_account.tr(),
|
||||||
style: TextStyle(color: kcMediumGrey),
|
style: style14MG400,
|
||||||
);
|
);
|
||||||
|
|
||||||
Widget _buildRegisterTextButton() => TextButton(
|
Widget _buildRegisterTextButton() => TextButton(
|
||||||
|
|
@ -31,8 +32,8 @@ class LoginAccount extends StatelessWidget {
|
||||||
child: _buildRegisterText(),
|
child: _buildRegisterText(),
|
||||||
);
|
);
|
||||||
|
|
||||||
Widget _buildRegisterText() => const Text(
|
Widget _buildRegisterText() => Text(
|
||||||
'Login',
|
LocaleKeys.login.tr(),
|
||||||
style: TextStyle(color: kcPrimaryColor),
|
style: style14P400,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:yimaru_app/ui/common/app_colors.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 'package:yimaru_app/ui/common/ui_helpers.dart';
|
||||||
|
|
||||||
import 'custom_circular_progress_indicator.dart';
|
import 'custom_circular_progress_indicator.dart';
|
||||||
|
|
@ -53,8 +55,8 @@ class PageLoadingIndicator extends StatelessWidget {
|
||||||
child: CustomCircularProgressIndicator(color: kcPrimaryColor),
|
child: CustomCircularProgressIndicator(color: kcPrimaryColor),
|
||||||
);
|
);
|
||||||
|
|
||||||
Widget _buildText() => const Text(
|
Widget _buildText() => Text(
|
||||||
'Please wait',
|
LocaleKeys.please_wait.tr(),
|
||||||
style: TextStyle(color: kcPrimaryColor),
|
style: style14P400,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:iconsax/iconsax.dart';
|
import 'package:iconsax/iconsax.dart';
|
||||||
import 'package:yimaru_app/ui/common/app_strings.dart';
|
import 'package:yimaru_app/ui/common/app_strings.dart';
|
||||||
|
import 'package:yimaru_app/ui/common/ui_helpers.dart';
|
||||||
|
|
||||||
import '../common/app_colors.dart';
|
import '../common/app_colors.dart';
|
||||||
|
|
||||||
|
|
@ -64,17 +65,11 @@ class PrivacyPolicyTile extends StatelessWidget {
|
||||||
|
|
||||||
Widget _buildTitle() => Text(
|
Widget _buildTitle() => Text(
|
||||||
title,
|
title,
|
||||||
style: const TextStyle(
|
style: style16DG600,
|
||||||
fontSize: 16,
|
|
||||||
color: kcDarkGrey,
|
|
||||||
fontWeight: FontWeight.w600,
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
|
|
||||||
Widget _buildContent() => const Text(
|
Widget _buildContent() => Text(
|
||||||
ksPrivacyPolicy,
|
ksPrivacyPolicy,
|
||||||
style: TextStyle(
|
style: style14DG400,
|
||||||
color: kcDarkGrey,
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,6 @@ import 'package:easy_localization/easy_localization.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:yimaru_app/ui/common/translations/locale_keys.g.dart';
|
import 'package:yimaru_app/ui/common/translations/locale_keys.g.dart';
|
||||||
|
|
||||||
import '../common/app_colors.dart';
|
|
||||||
import '../common/ui_helpers.dart';
|
import '../common/ui_helpers.dart';
|
||||||
|
|
||||||
class RegisterForAccount extends StatelessWidget {
|
class RegisterForAccount extends StatelessWidget {
|
||||||
|
|
@ -20,7 +19,7 @@ class RegisterForAccount extends StatelessWidget {
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
|
|
||||||
Widget _buildLeadingText() => Text(
|
Widget _buildLeadingText() => Text(
|
||||||
'${LocaleKeys.dont_have_account.tr()} ',
|
'${LocaleKeys.dont_have_account.tr()} ',
|
||||||
style: style14MG400,
|
style: style14MG400,
|
||||||
);
|
);
|
||||||
|
|
@ -33,8 +32,8 @@ class RegisterForAccount extends StatelessWidget {
|
||||||
child: _buildRegisterText(),
|
child: _buildRegisterText(),
|
||||||
);
|
);
|
||||||
|
|
||||||
Widget _buildRegisterText() => Text(
|
Widget _buildRegisterText() => Text(
|
||||||
LocaleKeys.register.tr(),
|
LocaleKeys.register.tr(),
|
||||||
style:style14P400 ,
|
style: style14P400,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
name: yimaru_app
|
name: yimaru_app
|
||||||
version: 0.1.16+18
|
version: 0.1.17+19
|
||||||
publish_to: 'none'
|
publish_to: 'none'
|
||||||
description: A new Flutter project.
|
description: A new Flutter project.
|
||||||
|
|
||||||
|
|
|
||||||
11
test/viewmodels/landing_viewmodel_test.dart
Normal file
11
test/viewmodels/landing_viewmodel_test.dart
Normal file
|
|
@ -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());
|
||||||
|
});
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user