From 6a70546b18cba2d4f6e6cc0adf40e6bf38284d59 Mon Sep 17 00:00:00 2001 From: boroboro01 Date: Fri, 30 Aug 2024 16:19:06 +0900 Subject: [PATCH 1/2] design: New welcome screen animation and design --- assets/images/LogoBig.png | Bin 6022 -> 0 bytes assets/images/LogoBig.svg | 7 + lib/screens/welcome/welcome_screen.dart | 268 +++++++++++++++--------- lib/utils/colors.dart | 1 + lib/widgets/login_button.dart | 1 - pubspec.lock | 72 +++++-- pubspec.yaml | 38 ++-- 7 files changed, 256 insertions(+), 131 deletions(-) delete mode 100644 assets/images/LogoBig.png create mode 100644 assets/images/LogoBig.svg diff --git a/assets/images/LogoBig.png b/assets/images/LogoBig.png deleted file mode 100644 index 15d933e7155bb0491acf83b804601c6559d82935..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6022 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 + + + + + + diff --git a/lib/screens/welcome/welcome_screen.dart b/lib/screens/welcome/welcome_screen.dart index ae66782..e30bbe7 100644 --- a/lib/screens/welcome/welcome_screen.dart +++ b/lib/screens/welcome/welcome_screen.dart @@ -1,6 +1,7 @@ import 'dart:convert'; import 'package:flutter/material.dart'; +import 'package:flutter_svg/flutter_svg.dart'; import 'package:google_sign_in/google_sign_in.dart'; import 'package:kakao_flutter_sdk_user/kakao_flutter_sdk_user.dart'; import 'package:saphy/models/loginInfo.dart'; @@ -15,6 +16,7 @@ import 'package:saphy/utils/colors.dart'; import 'package:saphy/utils/log.dart'; import 'package:saphy/screens/screen_controller.dart'; import 'package:saphy/widgets/login_button.dart'; +import 'package:simple_shadow/simple_shadow.dart'; class WelcomeScreen extends StatefulWidget { static String id = 'welcome_screen'; @@ -24,15 +26,58 @@ class WelcomeScreen extends StatefulWidget { State createState() => _WelcomeScreenState(); } -class _WelcomeScreenState extends State { +class _WelcomeScreenState extends State + with TickerProviderStateMixin { bool _isLoading = true; final kakaoViewModel = MainViewModel(KakaoLoginController()); final googleViewModel = MainViewModel(GoogleLoginController()); + late AnimationController _logoController; + late Animation _logoAnimation; + + final double _imageWidth = 1600.0; + final double _startPadding = 72.0; + @override void initState() { super.initState(); _autoLogin(); + + _logoController = AnimationController( + duration: const Duration(seconds: 150), + vsync: this, + )..repeat(); + + WidgetsBinding.instance.addPostFrameCallback((_) { + double screenWidth = MediaQuery.of(context).size.width; + _logoAnimation = TweenSequence([ + TweenSequenceItem( + tween: Tween( + begin: _startPadding, + end: -_imageWidth, + ), + weight: 1, + ), + TweenSequenceItem( + tween: Tween( + begin: screenWidth, + end: -_imageWidth, + ), + weight: 1, + ), + ]).animate( + CurvedAnimation( + parent: _logoController, + curve: Curves.linear, + ), + ); + }); + } + + @override + void dispose() { + _logoController.dispose(); + super.dispose(); } Future _autoLogin() async { @@ -68,110 +113,139 @@ class _WelcomeScreenState extends State { } return Scaffold( + backgroundColor: newGray, body: Column( children: [ Expanded( - flex: 2, - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Center(child: Image.asset('assets/images/LogoBig.png')), - const SizedBox( - height: 10.0, - ), - const Text( - 'electronics flea-market', - style: TextStyle( - fontFamily: 'Prompt-Thin', - fontSize: 20.0, - fontWeight: FontWeight.w100, - color: altBlack, - ), - ), - ], - )), - Expanded( - flex: 1, - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - LoginButton( - title: '구글 로그인', - logo: Image.asset( - 'assets/images/Google.png', - width: 20.0, - ), - color: white, - onTap: () async { - final GoogleSignInAccount user = - await googleViewModel.login(); - - final code = await loginService('GOOGLE', user.email); - - if (code == 200) { - Navigator.of(context).pushReplacement(MaterialPageRoute( - builder: (context) => const ScreenController(), - )); - } else if (code == 300) { - Navigator.of(context).pushReplacement( - MaterialPageRoute( - builder: (context) => SignupScreen( - socialType: 'GOOGLE', - userName: user.displayName, - userEmail: user.email, - userPhotoUrl: user.photoUrl, - ), + child: Stack( + children: [ + AnimatedBuilder( + animation: _logoAnimation, + builder: (context, child) { + return Positioned( + left: _logoAnimation.value, + top: 150.0, + child: SimpleShadow( + opacity: 0.25, + offset: const Offset(8, 15), + child: SvgPicture.asset( + 'assets/images/LogoBig.svg', + width: _imageWidth, + ), + ), + ); + }, + ), + Column( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + const Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text( + 'electronics flea-market, ', + style: TextStyle( + fontFamily: 'Prompt-Thin', + fontSize: 20.0, + fontWeight: FontWeight.w100, + color: white, ), - ); - } - }, - ), - const SizedBox(height: 5.0), - LoginButton( - title: '카카오 로그인', - logo: Image.asset( - 'assets/images/Kakao.png', + ), + Text( + ' Saphy', + style: TextStyle( + fontFamily: 'Prompt', + fontSize: 20.0, + fontWeight: FontWeight.w900, + color: white, + ), + ), + ], ), - color: systemKakao, - onTap: () async { - final User user = await kakaoViewModel.login(); - final code = await loginService( - 'KAKAO', - user.kakaoAccount!.email!, - ); - if (code == 200) { - //Login Success - Navigator.of(context).pushReplacement(MaterialPageRoute( - builder: (context) => const ScreenController(), - )); - } else if (code == 300) { - //Navigate register screen - Navigator.of(context).pushReplacement( - MaterialPageRoute( - builder: (context) => SignupScreen( - socialType: 'KAKAO', - userName: user.kakaoAccount?.profile?.nickname, - userEmail: user.kakaoAccount?.email, - userPhotoUrl: - user.kakaoAccount?.profile?.thumbnailImageUrl, + const SizedBox(height: 5.0), + LoginButton( + title: '구글 로그인', + logo: Image.asset( + 'assets/images/Google.png', + width: 20.0, + ), + color: white, + onTap: () async { + final GoogleSignInAccount user = + await googleViewModel.login(); + + final code = await loginService('GOOGLE', user.email); + + if (code == 200) { + Navigator.of(context) + .pushReplacement(MaterialPageRoute( + builder: (context) => const ScreenController(), + )); + } else if (code == 300) { + Navigator.of(context).pushReplacement( + MaterialPageRoute( + builder: (context) => SignupScreen( + socialType: 'GOOGLE', + userName: user.displayName, + userEmail: user.email, + userPhotoUrl: user.photoUrl, + ), ), - ), + ); + } + }, + ), + const SizedBox(height: 5.0), + LoginButton( + title: '카카오 로그인', + logo: Image.asset( + 'assets/images/Kakao.png', + ), + color: systemKakao, + onTap: () async { + final User user = await kakaoViewModel.login(); + final code = await loginService( + 'KAKAO', + user.kakaoAccount!.email!, ); - } - }, - ), - const SizedBox(height: 10.0), - const Text( - 'By tapping Sign in and using Saphy, \n you agree to our Terms and Privacy Policy.', - style: TextStyle( - fontFamily: 'Prompt-Regular', - fontWeight: FontWeight.w200, - color: altBlack, + if (code == 200) { + //Login Success + Navigator.of(context) + .pushReplacement(MaterialPageRoute( + builder: (context) => const ScreenController(), + )); + } else if (code == 300) { + //Navigate register screen + Navigator.of(context).pushReplacement( + MaterialPageRoute( + builder: (context) => SignupScreen( + socialType: 'KAKAO', + userName: user.kakaoAccount?.profile?.nickname, + userEmail: user.kakaoAccount?.email, + userPhotoUrl: user + .kakaoAccount?.profile?.thumbnailImageUrl, + ), + ), + ); + } + }, ), - textAlign: TextAlign.center, - ), - ], - )) + const SizedBox(height: 10.0), + const Text( + 'By tapping Sign in and using Saphy, \n you agree to our Terms and Privacy Policy.', + style: TextStyle( + fontFamily: 'Prompt-Regular', + fontWeight: FontWeight.w200, + color: white, + ), + textAlign: TextAlign.center, + ), + const SizedBox(height: 40.0), + ], + ) + ], + ), + ), ], ), ); diff --git a/lib/utils/colors.dart b/lib/utils/colors.dart index 02e2040..b7a984c 100644 --- a/lib/utils/colors.dart +++ b/lib/utils/colors.dart @@ -1,6 +1,7 @@ import 'package:flutter/material.dart'; // GrayScale +const Color newGray = Color(0xff404756); const Color txtPrimary = Color(0xff303136); // gray950 const Color gray900 = Color(0xff52535d); const Color gray800 = Color(0xff616272); diff --git a/lib/widgets/login_button.dart b/lib/widgets/login_button.dart index 2571196..b3c00fd 100644 --- a/lib/widgets/login_button.dart +++ b/lib/widgets/login_button.dart @@ -25,7 +25,6 @@ class LoginButton extends StatelessWidget { shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(10.0), ), - side: const BorderSide(color: gray100, width: 1.0), padding: const EdgeInsets.symmetric( horizontal: 15.0, vertical: 15.0, diff --git a/pubspec.lock b/pubspec.lock index 18c8b9f..95d5e0c 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -374,6 +374,14 @@ packages: url: "https://pub.dev" source: hosted version: "3.1.2" + flutter_svg: + dependency: "direct main" + description: + name: flutter_svg + sha256: "7b4ca6cf3304575fe9c8ec64813c8d02ee41d2afe60bcfe0678bcb5375d596a2" + url: "https://pub.dev" + source: hosted + version: "2.0.10+1" flutter_test: dependency: "direct dev" description: flutter @@ -556,18 +564,18 @@ packages: dependency: transitive description: name: leak_tracker - sha256: "7f0df31977cb2c0b88585095d168e689669a2cc9b97c309665e3386f3e9d341a" + sha256: "3f87a60e8c63aecc975dda1ceedbc8f24de75f09e4856ea27daf8958f2f0ce05" url: "https://pub.dev" source: hosted - version: "10.0.4" + version: "10.0.5" leak_tracker_flutter_testing: dependency: transitive description: name: leak_tracker_flutter_testing - sha256: "06e98f569d004c1315b991ded39924b21af84cf14cc94791b8aea337d25b57f8" + sha256: "932549fb305594d82d7183ecd9fa93463e9914e1b67cacc34bc40906594a1806" url: "https://pub.dev" source: hosted - version: "3.0.3" + version: "3.0.5" leak_tracker_testing: dependency: transitive description: @@ -612,18 +620,18 @@ packages: dependency: transitive description: name: material_color_utilities - sha256: "0e0a020085b65b6083975e499759762399b4475f766c21668c4ecca34ea74e5a" + sha256: f7142bb1154231d7ea5f96bc7bde4bda2a0945d2806bb11670e30b850d56bdec url: "https://pub.dev" source: hosted - version: "0.8.0" + version: "0.11.1" meta: dependency: transitive description: name: meta - sha256: "7687075e408b093f36e6bbf6c91878cc0d4cd10f409506f7bc996f68220b9136" + sha256: bdb68674043280c3428e9ec998512fb681678676b3c54e773629ffe74419f8c7 url: "https://pub.dev" source: hosted - version: "1.12.0" + version: "1.15.0" octo_image: dependency: transitive description: @@ -648,6 +656,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.9.0" + path_parsing: + dependency: transitive + description: + name: path_parsing + sha256: e3e67b1629e6f7e8100b367d3db6ba6af4b1f0bb80f64db18ef1fbabd2fa9ccf + url: "https://pub.dev" + source: hosted + version: "1.0.1" path_provider: dependency: transitive description: @@ -832,6 +848,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.4.0" + simple_shadow: + dependency: "direct main" + description: + name: simple_shadow + sha256: "0c0872b2baffaf12fc91416643785a88081120bac61d704f3f9dbd7e712360fa" + url: "https://pub.dev" + source: hosted + version: "0.3.1" sky_engine: dependency: transitive description: flutter @@ -929,10 +953,10 @@ packages: dependency: transitive description: name: test_api - sha256: "9955ae474176f7ac8ee4e989dadfb411a58c30415bcfb648fa04b2b8a03afa7f" + sha256: "5b8a98dafc4d5c4c9c72d8b31ab2b23fc13422348d2997120294d3bac86b4ddb" url: "https://pub.dev" source: hosted - version: "0.7.0" + version: "0.7.2" toggle_list: dependency: "direct main" description: @@ -965,6 +989,30 @@ packages: url: "https://pub.dev" source: hosted version: "4.4.2" + vector_graphics: + dependency: transitive + description: + name: vector_graphics + sha256: "32c3c684e02f9bc0afb0ae0aa653337a2fe022e8ab064bcd7ffda27a74e288e3" + url: "https://pub.dev" + source: hosted + version: "1.1.11+1" + vector_graphics_codec: + dependency: transitive + description: + name: vector_graphics_codec + sha256: c86987475f162fadff579e7320c7ddda04cd2fdeffbe1129227a85d9ac9e03da + url: "https://pub.dev" + source: hosted + version: "1.1.11+1" + vector_graphics_compiler: + dependency: transitive + description: + name: vector_graphics_compiler + sha256: "12faff3f73b1741a36ca7e31b292ddeb629af819ca9efe9953b70bd63fc8cd81" + url: "https://pub.dev" + source: hosted + version: "1.1.11+1" vector_math: dependency: transitive description: @@ -977,10 +1025,10 @@ packages: dependency: transitive description: name: vm_service - sha256: "3923c89304b715fb1eb6423f017651664a03bf5f4b29983627c4da791f74a4ec" + sha256: f652077d0bdf60abe4c1f6377448e8655008eef28f128bc023f7b5e8dfeb48fc url: "https://pub.dev" source: hosted - version: "14.2.1" + version: "14.2.4" watcher: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 33d32f2..b73b7f6 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -28,47 +28,44 @@ environment: # the latest version available on pub.dev. To see which dependencies have newer # versions available, run `flutter pub outdated`. dependencies: - flutter: - sdk: flutter - flutter_dotenv: ^5.1.0 - intl: ^0.19.0 cached_network_image: ^3.3.1 + crypto: ^3.0.3 cupertino_icons: ^1.0.6 - google_sign_in: ^6.2.1 dio: ^5.5.0+1 - platform: ^3.1.5 - # shared_preferences: ^2.3.0 - crypto: ^3.0.3 encrypt: ^5.0.3 - kakao_flutter_sdk_user: ^1.9.0 - kakao_flutter_sdk_talk: ^1.9.0 + firebase_auth: ^4.16.0 + firebase_core: ^2.24.2 + flutter: + sdk: flutter + flutter_dotenv: ^5.1.0 + flutter_native_splash: ^2.4.1 flutter_secure_storage: ^9.2.2 - remedi_kopo: ^0.0.2 + flutter_svg: ^2.0.10+1 + font_awesome_flutter: ^10.7.0 + google_sign_in: ^6.2.1 + intl: ^0.19.0 + kakao_flutter_sdk_talk: ^1.9.0 + kakao_flutter_sdk_user: ^1.9.0 logger: ^2.4.0 + platform: ^3.1.5 pretty_dio_logger: ^1.4.0 - firebase_core: ^2.24.2 - firebase_auth: ^4.16.0 - font_awesome_flutter: ^10.7.0 + remedi_kopo: ^0.0.2 + simple_shadow: ^0.3.1 toggle_list: ^0.3.1 - flutter_native_splash: ^2.4.1 dev_dependencies: + flutter_lints: ^4.0.0 flutter_test: sdk: flutter - - - flutter_lints: ^4.0.0 json_serializable: ^6.8.0 flutter: uses-material-design: true - assets: - assets/config/.env - assets/images/ - fonts: - family: Pretendard fonts: @@ -90,6 +87,5 @@ flutter: - asset: assets/fonts/Prompt-Medium.ttf - asset: assets/fonts/Prompt-Regular.ttf - asset: assets/fonts/Prompt-Thin.ttf - # # For details regarding fonts from package dependencies, # see https://flutter.dev/custom-fonts/#from-packages From 5907772142745f5d66400e96741c0b7746b033c0 Mon Sep 17 00:00:00 2001 From: boroboro01 Date: Fri, 30 Aug 2024 17:11:45 +0900 Subject: [PATCH 2/2] design: Apply new desgin to signup and otp screen --- assets/images/LogoFixed.svg | 4 + lib/screens/welcome/otp_screen.dart | 222 +++++++++++++-------- lib/screens/welcome/signup_screen.dart | 266 +++++++++++++------------ lib/utils/otp_form.dart | 6 +- lib/widgets/normal_button.dart | 6 +- lib/widgets/sign_up_form.dart | 4 +- 6 files changed, 292 insertions(+), 216 deletions(-) create mode 100644 assets/images/LogoFixed.svg diff --git a/assets/images/LogoFixed.svg b/assets/images/LogoFixed.svg new file mode 100644 index 0000000..a138088 --- /dev/null +++ b/assets/images/LogoFixed.svg @@ -0,0 +1,4 @@ + + + + diff --git a/lib/screens/welcome/otp_screen.dart b/lib/screens/welcome/otp_screen.dart index d66dc12..0d73127 100644 --- a/lib/screens/welcome/otp_screen.dart +++ b/lib/screens/welcome/otp_screen.dart @@ -2,6 +2,7 @@ import 'package:firebase_auth/firebase_auth.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; +import 'package:flutter_svg/svg.dart'; import 'package:saphy/utils/colors.dart'; import 'package:saphy/utils/log.dart'; import 'package:saphy/utils/otp_form.dart'; @@ -44,93 +45,152 @@ class _OtpScreenState extends State { @override Widget build(BuildContext context) { return Scaffold( + backgroundColor: newGray, resizeToAvoidBottomInset: false, - body: Form( - child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 20.0), - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - const Text( - '안전한 중고거래를 위해서!', - style: TextStyle( - fontFamily: 'Pretendard-Bold', - fontSize: 30.0, - fontWeight: FontWeight.w800, - color: altBlack, + body: Stack( + children: [ + Positioned( + top: 100, + left: -240, + child: Opacity( + opacity: 0.5, + child: SvgPicture.asset( + 'assets/images/LogoFixed.svg', + width: MediaQuery.of(context).size.width + 500.0, ), ), - const SizedBox( - height: 10.0, - ), - Text( - '${widget.phoneNumber}로 인증번호가 전송되었습니다.', - style: const TextStyle( - fontFamily: 'Pretendard-Medium', - fontSize: 20.0, - fontWeight: FontWeight.w400, - color: altBlack, + ), + Form( + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 20.0), + child: Column( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + const SizedBox(height: 10.0), + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const Text( + '안전한 중고거래를 위해서!', + style: TextStyle( + fontFamily: 'Pretendard-Bold', + fontSize: 35.0, + fontWeight: FontWeight.w800, + color: white, + ), + ), + const SizedBox( + height: 10.0, + ), + Text( + '${widget.phoneNumber}로 인증번호가 전송되었습니다.', + style: const TextStyle( + fontFamily: 'Pretendard-Medium', + fontSize: 20.0, + fontWeight: FontWeight.w400, + color: gray100, + ), + ), + const SizedBox( + height: 10.0, + ), + OtpForms( + controller1: _controller1, + controller2: _controller2, + controller3: _controller3, + controller4: _controller4, + controller5: _controller5, + controller6: _controller6), + ], + ), + Padding( + padding: const EdgeInsets.only(bottom: 20.0), + child: NormalButton( + title: "인증하기", + bgColor: mainPrimary, + txtColor: black, + flag: true, + onTap: () async { + logger.i(smsCode); + try { + final credential = PhoneAuthProvider.credential( + verificationId: widget.verificationId, + smsCode: smsCode); + await FirebaseAuth.instance + .signInWithCredential(credential) + .then((_) { + widget.onVerificationSuccess(); + Navigator.of(context).pop(); + }); + } catch (e) { + print(e); + } + }, + ), + ), + ], ), ), - const SizedBox( - height: 10.0, - ), - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - OtpForm( - controller: _controller1, - lastNode: false, - ), - OtpForm( - controller: _controller2, - lastNode: false, - ), - OtpForm( - controller: _controller3, - lastNode: false, - ), - OtpForm( - controller: _controller4, - lastNode: false, - ), - OtpForm( - controller: _controller5, - lastNode: false, - ), - OtpForm( - controller: _controller6, - lastNode: true, - ), - ], - ), - const SizedBox( - height: 20.0, - ), - NormalButton( - title: "인증하기", - bgColor: mainPrimary, - txtColor: black, - flag: true, - onTap: () async { - logger.i(smsCode); - try { - final credential = PhoneAuthProvider.credential( - verificationId: widget.verificationId, smsCode: smsCode); - await FirebaseAuth.instance - .signInWithCredential(credential) - .then((_) { - widget.onVerificationSuccess(); - Navigator.of(context).pop(); - }); - } catch (e) { - print(e); - } - }, - ), - ], + ), + ], + ), + ); + } +} + +class OtpForms extends StatelessWidget { + const OtpForms({ + super.key, + required TextEditingController controller1, + required TextEditingController controller2, + required TextEditingController controller3, + required TextEditingController controller4, + required TextEditingController controller5, + required TextEditingController controller6, + }) : _controller1 = controller1, + _controller2 = controller2, + _controller3 = controller3, + _controller4 = controller4, + _controller5 = controller5, + _controller6 = controller6; + + final TextEditingController _controller1; + final TextEditingController _controller2; + final TextEditingController _controller3; + final TextEditingController _controller4; + final TextEditingController _controller5; + final TextEditingController _controller6; + + @override + Widget build(BuildContext context) { + return Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + OtpForm( + controller: _controller1, + lastNode: false, + ), + OtpForm( + controller: _controller2, + lastNode: false, + ), + OtpForm( + controller: _controller3, + lastNode: false, + ), + OtpForm( + controller: _controller4, + lastNode: false, + ), + OtpForm( + controller: _controller5, + lastNode: false, + ), + OtpForm( + controller: _controller6, + lastNode: true, ), - )), + ], ); } } diff --git a/lib/screens/welcome/signup_screen.dart b/lib/screens/welcome/signup_screen.dart index c03e37f..4bd6778 100644 --- a/lib/screens/welcome/signup_screen.dart +++ b/lib/screens/welcome/signup_screen.dart @@ -2,11 +2,11 @@ import 'package:firebase_auth/firebase_auth.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter/widgets.dart'; +import 'package:flutter_svg/svg.dart'; import 'package:logger/web.dart'; import 'package:saphy/screens/screen_controller.dart'; import 'package:saphy/screens/welcome/otp_screen.dart'; import 'package:saphy/service/auth_service.dart'; -import 'package:saphy/service/authentication/secure_storage.dart'; import 'package:saphy/utils/colors.dart'; import 'package:saphy/utils/phone_input_formatter.dart'; import 'package:saphy/widgets/normal_button.dart'; @@ -67,134 +67,153 @@ class _SignupScreenState extends State { @override Widget build(BuildContext context) { return Scaffold( + backgroundColor: newGray, resizeToAvoidBottomInset: false, - body: Center( - child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 40.0), - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - const Text( - '환영합니다!', - style: TextStyle( - fontFamily: 'Pretendard-Bold', - fontSize: 50.0, - fontWeight: FontWeight.w800, - color: altBlack, - ), + body: Stack( + children: [ + Positioned( + top: 100, + left: -240, + child: Opacity( + opacity: 0.5, + child: SvgPicture.asset( + 'assets/images/LogoFixed.svg', + width: MediaQuery.of(context).size.width + 500.0, ), - const Text( - '서비스 이용에 필요한 정보를 입력해주세요', - style: TextStyle( - fontFamily: 'Pretendard-Medium', - fontSize: 20.0, - fontWeight: FontWeight.w400, - color: altBlack, - ), - ), - const SizedBox( - height: 20.0, - ), - SignUpForm( - textEditingController: _nameController, - readOnly: true, - formatter: const [], - initialValue: userName ?? '', - labelText: '어떻게 불러드릴까요?', - ), - SignUpForm( - textEditingController: _emailController, - readOnly: true, - formatter: const [], - initialValue: userEmail ?? '', - labelText: '이메일을 알려주세요', - ), - SignUpForm( - textEditingController: _phoneController, - readOnly: phoneAuth, - formatter: [ - FilteringTextInputFormatter.digitsOnly, - LengthLimitingTextInputFormatter(11), - PhoneInputFormatter(), - ], - initialValue: userPhoneNumber, - labelText: '전화번호를 알려주세요', - ), - Padding( - padding: const EdgeInsets.symmetric(horizontal: 100.0), - child: NormalButton( - title: "인증번호 전송", - bgColor: phoneAuth ? gray300 : mainPrimary, + ), + ), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 20.0), + child: Column( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + const SizedBox(height: 30.0), + formWidget(context), + Padding( + padding: const EdgeInsets.only(bottom: 20.0), + child: NormalButton( + title: '사피 시작하기', + bgColor: phoneAuth ? mainPrimary : gray400, txtColor: black, - flag: !phoneAuth, + flag: phoneAuth, onTap: () async { - String phoneNumber = _phoneController.text.trim(); - String formattedNumber = ''; - if (phoneNumber.isNotEmpty) { - // '-'를 제거하고, 앞에 +82를 붙임 - formattedNumber = phoneNumber - .replaceAll('-', '') // '-' 제거 - .replaceFirst( - '010', '+8210'); // '010'을 '+8210'으로 변환 + logger.i( + '${_nameController.text} / ${_emailController.text} / ${_phoneController.text} / ${widget.userPhotoUrl} /', + ); + final code = await joinService( + widget.socialType!, + _emailController.text, + _nameController.text, + _phoneController.text, + ); + if (code == 200) { + Navigator.of(context).pushReplacement(MaterialPageRoute( + builder: (context) => const ScreenController(), + )); } - logger.i(formattedNumber); - await FirebaseAuth.instance.verifyPhoneNumber( + }, + ), + ) + ], + ), + ) + ], + ), + ); + } + + Column formWidget(BuildContext context) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const Text( + '안녕하세요!', + style: TextStyle( + fontFamily: 'Pretendard-Bold', + fontSize: 50.0, + fontWeight: FontWeight.w800, + color: white, + ), + ), + const Text( + '서비스 이용에 필요한 정보를 입력해주세요', + style: TextStyle( + fontFamily: 'Pretendard-Medium', + fontSize: 20.0, + fontWeight: FontWeight.w400, + color: gray100, + ), + ), + const SizedBox( + height: 20.0, + ), + SignUpForm( + textEditingController: _nameController, + readOnly: true, + formatter: const [], + initialValue: userName ?? '', + labelText: '어떻게 불러드릴까요?', + ), + SignUpForm( + textEditingController: _emailController, + readOnly: true, + formatter: const [], + initialValue: userEmail ?? '', + labelText: '이메일을 알려주세요', + ), + SignUpForm( + textEditingController: _phoneController, + readOnly: phoneAuth, + formatter: [ + FilteringTextInputFormatter.digitsOnly, + LengthLimitingTextInputFormatter(11), + PhoneInputFormatter(), + ], + initialValue: userPhoneNumber, + labelText: '전화번호를 알려주세요', + ), + NormalButton( + title: "인증번호 전송", + bgColor: phoneAuth ? gray300 : mainPrimary, + txtColor: black, + flag: !phoneAuth, + onTap: () async { + String phoneNumber = _phoneController.text.trim(); + String formattedNumber = ''; + if (phoneNumber.isNotEmpty) { + // '-'를 제거하고, 앞에 +82를 붙임 + formattedNumber = phoneNumber + .replaceAll('-', '') // '-' 제거 + .replaceFirst('010', '+8210'); // '010'을 '+8210'으로 변환 + } + logger.i(formattedNumber); + await FirebaseAuth.instance.verifyPhoneNumber( + phoneNumber: formattedNumber, + verificationCompleted: (PhoneAuthCredential) {}, + verificationFailed: (error) { + logger.i(error); + }, + codeSent: (verificationId, forceResendingToken) { + //if code is send successfully then nevigate to next screen + Navigator.of(context).push( + MaterialPageRoute( + builder: (context) => OtpScreen( + verificationId: verificationId, phoneNumber: formattedNumber, - verificationCompleted: (PhoneAuthCredential) {}, - verificationFailed: (error) { - logger.i(error); + onVerificationSuccess: () { + setState(() { + phoneAuth = true; + userPhoneNumber = _phoneController.text; + }); }, - codeSent: (verificationId, forceResendingToken) { - //if code is send successfully then nevigate to next screen - Navigator.of(context).push( - MaterialPageRoute( - builder: (context) => OtpScreen( - verificationId: verificationId, - phoneNumber: formattedNumber, - onVerificationSuccess: () { - setState(() { - phoneAuth = true; - userPhoneNumber = _phoneController.text; - }); - }, - ), - ), - ); - }, - codeAutoRetrievalTimeout: (verificationId) {}, - ); - }), - ), - const SizedBox( - height: 50.0, - ), - NormalButton( - title: '사피 시작하기', - bgColor: phoneAuth ? mainPrimary : gray400, - txtColor: black, - flag: phoneAuth, - onTap: () async { - logger.i( - '${_nameController.text} / ${_emailController.text} / ${_phoneController.text} / ${widget.userPhotoUrl} /', + ), + ), ); - final code = await joinService( - widget.socialType!, - _emailController.text, - _nameController.text, - _phoneController.text, - ); - if (code == 200) { - Navigator.of(context).pushReplacement(MaterialPageRoute( - builder: (context) => const ScreenController(), - )); - } }, - ) - ], - ), - ), - ), + codeAutoRetrievalTimeout: (verificationId) {}, + ); + }), + ], ); } } @@ -205,13 +224,6 @@ class _SignupScreenState extends State { - - - - - - - // final TextEditingController _postcodeController = TextEditingController(); // final TextEditingController _addressController = TextEditingController(); // final TextEditingController _addressDetailController = diff --git a/lib/utils/otp_form.dart b/lib/utils/otp_form.dart index 528b9a9..ec88118 100644 --- a/lib/utils/otp_form.dart +++ b/lib/utils/otp_form.dart @@ -30,14 +30,14 @@ class OtpForm extends StatelessWidget { }, decoration: InputDecoration( enabledBorder: OutlineInputBorder( - borderSide: const BorderSide(color: mainPrimary, width: 2.0), + borderSide: const BorderSide(color: gray100, width: 2.0), borderRadius: BorderRadius.circular(10.0), ), focusedBorder: OutlineInputBorder( - borderSide: const BorderSide(color: mainPrimary, width: 2.0), + borderSide: const BorderSide(color: gray100, width: 2.0), borderRadius: BorderRadius.circular(10.0), )), - cursorColor: main500, + cursorColor: gray100, cursorHeight: 50.0, textAlign: TextAlign.center, textAlignVertical: TextAlignVertical.center, diff --git a/lib/widgets/normal_button.dart b/lib/widgets/normal_button.dart index 4227e37..0cd4220 100644 --- a/lib/widgets/normal_button.dart +++ b/lib/widgets/normal_button.dart @@ -9,14 +9,12 @@ class NormalButton extends StatelessWidget { required this.txtColor, required this.onTap, required this.flag, - this.fontColor, }); final String title; final Color bgColor; final Color txtColor; final bool flag; - final Color? fontColor; final Function() onTap; @override @@ -27,7 +25,7 @@ class NormalButton extends StatelessWidget { shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(10.0), ), - side: const BorderSide(color: black, width: 1.0), + side: BorderSide(color: bgColor, width: 1.0), padding: const EdgeInsets.symmetric( horizontal: 15.0, vertical: 15.0, @@ -44,7 +42,7 @@ class NormalButton extends StatelessWidget { style: TextStyle( fontFamily: 'Pretendard', fontSize: 20.0, - color: fontColor ?? black, + color: flag ? txtColor : txtSecondary, fontWeight: FontWeight.bold), ), ], diff --git a/lib/widgets/sign_up_form.dart b/lib/widgets/sign_up_form.dart index b95f4cb..c3aa9c3 100644 --- a/lib/widgets/sign_up_form.dart +++ b/lib/widgets/sign_up_form.dart @@ -28,7 +28,9 @@ class SignUpForm extends StatelessWidget { decoration: BoxDecoration( shape: BoxShape.rectangle, borderRadius: BorderRadius.circular(10.0), - color: readOnly ? gray500 : gray200, + color: readOnly + ? const Color.fromARGB(200, 160, 163, 180) + : const Color.fromARGB(200, 223, 225, 230), ), child: Padding( padding: const EdgeInsets.only(left: 10.0),