diff --git a/lib/router.dart b/lib/router.dart index 74802fac7..268a2a807 100644 --- a/lib/router.dart +++ b/lib/router.dart @@ -65,6 +65,7 @@ import 'package:cake_wallet/wallet_types.g.dart'; import 'package:cake_wallet/src/screens/dashboard/widgets/address_page.dart'; import 'package:cake_wallet/src/screens/receive/fullscreen_qr_page.dart'; import 'package:cake_wallet/src/screens/cake_phone/cake_phone_welcome_page.dart'; +import 'package:cake_wallet/src/screens/cake_phone/cake_phone_verification_page.dart'; RouteSettings currentRouteSettings; @@ -415,6 +416,11 @@ Route createRoute(RouteSettings settings) { builder: (_) => CakePhoneAuthPage(isLogin: isLogin), ); + case Routes.cakePhoneVerification: + return MaterialPageRoute( + builder: (_) => CakePhoneVerificationPage(), + ); + default: return MaterialPageRoute( builder: (_) => Scaffold( diff --git a/lib/routes.dart b/lib/routes.dart index e61a9a0c1..706daabbc 100644 --- a/lib/routes.dart +++ b/lib/routes.dart @@ -62,4 +62,5 @@ class Routes { static const fullscreenQR = '/fullscreen_qr'; static const cakePhoneWelcome = '/cake_phone_welcome'; static const cakePhoneAuth = '/cake_phone_auth'; + static const cakePhoneVerification = '/cake_phone_verification'; } \ No newline at end of file diff --git a/lib/src/screens/cake_phone/cake_phone_auth_page.dart b/lib/src/screens/cake_phone/cake_phone_auth_page.dart index a9ccc2904..9b36ee72a 100644 --- a/lib/src/screens/cake_phone/cake_phone_auth_page.dart +++ b/lib/src/screens/cake_phone/cake_phone_auth_page.dart @@ -50,13 +50,19 @@ class CakePhoneAuthBodyState extends State { controller: _emailController, keyboardType: TextInputType.emailAddress, maxLines: 1, - hintText: S.of(context).emailAddress, + hintText: S.of(context).email_address, ), bottomSectionPadding: EdgeInsets.only(bottom: 24, right: 24, left: 24), bottomSection: Column( children: [ PrimaryButton( - onPressed: () {}, + onPressed: () { + if (widget.isLogin) { + _loginCakePhone(); + } else { + _registerCakePhone(); + } + }, text: widget.isLogin ? S.of(context).login : S.of(context).create_account, color: Theme.of(context).accentTextTheme.body2.color, textColor: Colors.white, @@ -105,4 +111,14 @@ class CakePhoneAuthBodyState extends State { ), ); } + + void _registerCakePhone() { + // TODO: Add Registration logic + Navigator.pushNamed(context, Routes.cakePhoneVerification); + } + + void _loginCakePhone() { + // TODO: Add Login logic + Navigator.pushNamed(context, Routes.cakePhoneVerification); + } } diff --git a/lib/src/screens/cake_phone/cake_phone_verification_page.dart b/lib/src/screens/cake_phone/cake_phone_verification_page.dart new file mode 100644 index 000000000..5936d0ae3 --- /dev/null +++ b/lib/src/screens/cake_phone/cake_phone_verification_page.dart @@ -0,0 +1,151 @@ +import 'dart:async'; + +import 'package:cake_wallet/src/widgets/base_text_form_field.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:cake_wallet/routes.dart'; +import 'package:cake_wallet/generated/i18n.dart'; +import 'package:cake_wallet/src/widgets/primary_button.dart'; +import 'package:cake_wallet/src/screens/base_page.dart'; +import 'package:cake_wallet/src/widgets/scollable_with_bottom_section.dart'; + +class CakePhoneVerificationPage extends BasePage { + CakePhoneVerificationPage(); + + @override + Widget body(BuildContext context) => CakePhoneVerificationBody(); + + @override + Widget middle(BuildContext context) { + return Text( + S.of(context).email_verification, + style: TextStyle( + fontSize: 22, + fontWeight: FontWeight.w600, + fontFamily: 'Lato', + color: titleColor ?? Theme.of(context).primaryTextTheme.title.color), + ); + } +} + +class CakePhoneVerificationBody extends StatefulWidget { + CakePhoneVerificationBody(); + + @override + CakePhoneVerificationBodyState createState() => CakePhoneVerificationBodyState(); +} + +class CakePhoneVerificationBodyState extends State { + final _codeController = TextEditingController(); + + int resendCount = 0; + int timeLeft = 0; + + @override + void initState() { + super.initState(); + + _startTimer(); + } + + @override + Widget build(BuildContext context) { + return Container( + padding: EdgeInsets.only(top: 16), + child: ScrollableWithBottomSection( + contentPadding: EdgeInsets.fromLTRB(24, 100, 24, 20), + content: Column( + children: [ + Padding( + padding: const EdgeInsets.symmetric(horizontal: 50), + child: Text( + S.of(context).fill_verification_code, + style: TextStyle( + fontSize: 16, + color: Theme.of(context).primaryTextTheme.title.color, + fontFamily: 'Lato', + ), + textAlign: TextAlign.center, + ), + ), + Padding( + padding: const EdgeInsets.symmetric(vertical: 25), + child: BaseTextFormField( + controller: _codeController, + maxLines: 1, + hintText: S.of(context).verification_code, + suffixIcon: timeLeft > 0 + ? null + : InkWell( + onTap: _startTimer, + child: Container( + padding: EdgeInsets.symmetric(vertical: 8, horizontal: 12), + margin: EdgeInsets.only(bottom: 12), + decoration: BoxDecoration( + color: Theme.of(context).accentTextTheme.caption.color, + borderRadius: BorderRadius.circular(6), + ), + child: Text( + S.of(context).get_code, + style: TextStyle( + color: Theme.of(context).primaryTextTheme.title.color, + fontWeight: FontWeight.w900, + ), + )), + ), + ), + ), + if (timeLeft > 0) + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + S.of(context).did_not_get_code, + style: TextStyle( + fontSize: 12, + color: Theme.of(context).hintColor, + ), + ), + Text( + S.of(context).resend_code_in + " ${timeLeft ~/ 60}:" + (timeLeft % 60).toString().padLeft(2, '0'), + style: TextStyle( + fontSize: 12, + fontWeight: FontWeight.w700, + color: Theme.of(context).textTheme.subtitle.color, + ), + ), + ], + ), + ], + ), + bottomSectionPadding: EdgeInsets.only(bottom: 24, right: 24, left: 24), + bottomSection: Column( + children: [ + PrimaryButton( + onPressed: () {}, + text: S.of(context).continue_text, + color: Theme.of(context).accentTextTheme.body2.color, + textColor: Colors.white, + isDisabled: _codeController.text.isEmpty, + ), + ], + ), + ), + ); + } + + void _startTimer() { + resendCount++; + timeLeft = (resendCount * 30); + setState(() {}); + Timer.periodic(const Duration(seconds: 1), (timer) { + timeLeft--; + if (mounted) { + setState(() {}); + } + if (timeLeft <= 0) { + timer.cancel(); + } + }); + } +} diff --git a/lib/src/screens/cake_phone/cake_phone_welcome_page.dart b/lib/src/screens/cake_phone/cake_phone_welcome_page.dart index 474b634fb..0f32f15b6 100644 --- a/lib/src/screens/cake_phone/cake_phone_welcome_page.dart +++ b/lib/src/screens/cake_phone/cake_phone_welcome_page.dart @@ -41,9 +41,7 @@ class CakePhoneWelcomeBodyState extends State { child: ScrollableWithBottomSection( contentPadding: EdgeInsets.fromLTRB(24, 100, 24, 20), content: Text( - '''Cake Phone allows you to purchase virtual phone numbers with digital assets! - -Only an email is required.''', + S.of(context).cake_phone_introduction, style: TextStyle( fontSize: 16, color: Theme.of(context).primaryTextTheme.title.color, diff --git a/lib/src/screens/dashboard/wallet_menu.dart b/lib/src/screens/dashboard/wallet_menu.dart index 704ddb2a6..556c87a6f 100644 --- a/lib/src/screens/dashboard/wallet_menu.dart +++ b/lib/src/screens/dashboard/wallet_menu.dart @@ -80,6 +80,12 @@ class WalletMenu { image: Image.asset('assets/images/question_mark.png', height: 16, width: 16, color: Palette.darkBlue), handler: () => Navigator.of(context).pushNamed(Routes.support)), + // TODO: Move this to marketplace screen when ready + WalletMenuItem( + title: S.current.settings_support, + image: Image.asset('assets/images/question_mark.png', + height: 16, width: 16, color: Palette.darkBlue), + handler: () => Navigator.of(context).pushNamed(Routes.cakePhoneWelcome)), ]); } diff --git a/res/values/strings_en.arb b/res/values/strings_en.arb index f5f4bc8cf..96309e88e 100644 --- a/res/values/strings_en.arb +++ b/res/values/strings_en.arb @@ -544,5 +544,12 @@ "cake_phone_terms_conditions_second_section": "of Cake Phone, which indicates you will receive all account notices and information electronically to the email address provided", "privacy_policy": "Privacy Policy", "and": "and", - "emailAddress": "Email Address" + "email_address": "Email Address", + "email_verification": "Email Verification", + "fill_verification_code": "Please fill in the verification code provided to your email:", + "verification_code": "Verification code", + "did_not_get_code": "Didn't get the code?", + "resend_code_in": "Resend code in", + "get_code": "Get Code", + "cake_phone_introduction": "Cake Phone allows you to purchase virtual phone numbers with digital assets!\n\nOnly an email is required." }