From a45c5a0f36962a1de61a4243287f62076f760581 Mon Sep 17 00:00:00 2001 From: leeyjwinter Date: Mon, 11 Jul 2022 20:21:52 +0900 Subject: [PATCH 1/4] =?UTF-8?q?=EC=B9=B4=EC=B9=B4=EC=98=A4=ED=86=A1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- android/app/build.gradle | 2 +- android/app/src/main/AndroidManifest.xml | 13 ++ lib/main.dart | 2 + lib/pages/login_email_page.dart | 2 +- lib/pages/login_page.dart | 192 ++++++++++++----------- lib/pages/start_loading_page.dart | 2 +- lib/widgets/kakao_login.dart | 39 +++++ lib/widgets/main_view_model.dart | 24 +++ lib/widgets/social_login.dart | 4 + pubspec.yaml | 1 + 10 files changed, 189 insertions(+), 92 deletions(-) create mode 100644 lib/widgets/kakao_login.dart create mode 100644 lib/widgets/main_view_model.dart create mode 100644 lib/widgets/social_login.dart diff --git a/android/app/build.gradle b/android/app/build.gradle index ba1667b..6f94273 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -47,7 +47,7 @@ android { applicationId "com.example.cs496_2nd_week" // You can update the following values to match your application needs. // For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-build-configuration. - minSdkVersion flutter.minSdkVersion + minSdkVersion 21 targetSdkVersion flutter.targetSdkVersion versionCode flutterVersionCode.toInteger() versionName flutterVersionName diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index 48a1f92..b035a9c 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -4,6 +4,19 @@ android:label="cs496_2nd_week" android:name="${applicationName}" android:icon="@mipmap/ic_launcher"> + + + + + + + + + + + + + { key: 'token', value: jsonDecode(response.body)['token'], ); //storage.delete(key: "login"); - Navigator.pushReplacement(context, FadePageRoute(MainPage(token: '${idController.text}.${passController.text}'))); + Navigator.pushReplacement(context, FadePageRoute(MainPage(token: jsonDecode(response.body)['token']))); } else { print('wrong id or password'); diff --git a/lib/pages/login_page.dart b/lib/pages/login_page.dart index fd6c0f3..091e4b2 100644 --- a/lib/pages/login_page.dart +++ b/lib/pages/login_page.dart @@ -2,117 +2,131 @@ import 'package:cs496_2nd_week/pages/login_email_page.dart'; import 'package:cs496_2nd_week/pages/main_page.dart'; import 'package:cs496_2nd_week/pages/signup_page.dart'; import 'package:cs496_2nd_week/utils/fade_page_route.dart'; +import 'package:cs496_2nd_week/widgets/kakao_login.dart'; +import 'package:cs496_2nd_week/widgets/main_view_model.dart'; import 'package:flutter/gestures.dart'; import 'package:flutter/material.dart'; import 'package:flutter/src/foundation/key.dart'; import 'package:flutter/src/widgets/framework.dart'; import 'dart:developer'; - import 'package:flutter_secure_storage/flutter_secure_storage.dart'; +import 'package:cs496_2nd_week/widgets/main_view_model.dart'; + +class LoginPage extends StatefulWidget { + LoginPage({Key? key}) : super(key: key); + final viewModel = MainViewModel(KakaoLogin()); + static const storage = FlutterSecureStorage(); -class LoginPage extends StatelessWidget { - const LoginPage({Key? key}) : super(key: key); + @override + State createState() => _LoginPageState(); +} +class _LoginPageState extends State { @override Widget build(BuildContext context) { return Scaffold( - body: Center( - child: SingleChildScrollView( - scrollDirection: Axis.vertical, - child: ConstrainedBox( - constraints: BoxConstraints( - maxWidth: MediaQuery.of(context).size.width * 0.8 < 500 ? MediaQuery.of(context).size.width * 0.8 : 500, - ), - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - const Align( - alignment: Alignment.centerLeft, - child: Text('Welcome to App!', style: TextStyle(fontWeight: FontWeight.bold, fontSize: 28), ), - ), - const SizedBox(height: 10,), - const Align( - alignment: Alignment.centerLeft, - child: Text('App은 자신이 만든 프로젝트를 공유하고 발전시킬 수 있는 플랫폼입니다', style: TextStyle(fontSize: 16), ), - ), - const SizedBox(height: 10,), - OutlinedButton( - onPressed: () {}, - style: ElevatedButton.styleFrom( - minimumSize: const Size.fromHeight(40) - ), - child: Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Image.asset('assets/images/login_googleIcon.png', width: 20, height: 20, ), - const SizedBox(width: 8), - const Text('Continue with Google', style: TextStyle(color: Color.fromARGB(255, 66, 66, 66)), ) - ], + body: Center( + child: SingleChildScrollView( + scrollDirection: Axis.vertical, + child: ConstrainedBox( + constraints: BoxConstraints( + maxWidth: MediaQuery.of(context).size.width * 0.8 < 500 ? MediaQuery.of(context).size.width * 0.8 : 500, + ), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + const Align( + alignment: Alignment.centerLeft, + child: Text('Welcome to App!', style: TextStyle(fontWeight: FontWeight.bold, fontSize: 28), ), ), - ), - OutlinedButton( - onPressed: () {}, - style: ElevatedButton.styleFrom( - minimumSize: const Size.fromHeight(40) + const SizedBox(height: 10,), + const Align( + alignment: Alignment.centerLeft, + child: Text('App은 자신이 만든 프로젝트를 공유하고 발전시킬 수 있는 플랫폼입니다', style: TextStyle(fontSize: 16), ), ), - child: Row( - mainAxisAlignment: MainAxisAlignment.center, - children: const [ - Icon(Icons.facebook, color: Colors.blue), - SizedBox(width: 8), - Text('Continue with Facebook', style: TextStyle(color: Color.fromARGB(255, 66, 66, 66)), ) - ], + const SizedBox(height: 10,), + OutlinedButton( + onPressed: () async { + await widget.viewModel.login(); + setState((){}); + print("email is ${widget.viewModel.user?.kakaoAccount?.email}"); + Navigator.pushReplacement(context, FadePageRoute(MainPage(token: widget.viewModel.user?.kakaoAccount?.email))); + }, + style: ElevatedButton.styleFrom( + minimumSize: const Size.fromHeight(40) + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Image.asset('assets/images/login_googleIcon.png', width: 20, height: 20, ), + const SizedBox(width: 8), + const Text('Continue with Kakao', style: TextStyle(color: Color.fromARGB(255, 66, 66, 66)), ) + ], + ), ), - ), - const SizedBox(height: 8,), - Row( - children: const [ - Expanded( - child: Divider(color: Colors.black54,) + OutlinedButton( + onPressed: () {}, + style: ElevatedButton.styleFrom( + minimumSize: const Size.fromHeight(40) ), - SizedBox(width:8, ), - Text("OR"), - SizedBox(width:8, ), - Expanded( - child: Divider(color: Colors.black54,) + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: const [ + Icon(Icons.facebook, color: Colors.blue), + SizedBox(width: 8), + Text('Continue with Facebook', style: TextStyle(color: Color.fromARGB(255, 66, 66, 66)), ) + ], ), - ], - ), - const SizedBox(height: 8,), - OutlinedButton( - onPressed: () { - Navigator.push(context, MaterialPageRoute(builder: (context) => const LoginEmailPage()),); - }, - style: ElevatedButton.styleFrom( - minimumSize: const Size.fromHeight(40), ), - child: Row( - mainAxisAlignment: MainAxisAlignment.center, - children: const [ - Icon(Icons.mail_outlined, color: Color.fromARGB(255, 66, 66, 66),), - SizedBox(width: 8), - Text('Continue with Email', style: TextStyle(color: Color.fromARGB(255, 66, 66, 66)), ) + const SizedBox(height: 8,), + Row( + children: const [ + Expanded( + child: Divider(color: Colors.black54,) + ), + SizedBox(width:8, ), + Text("OR"), + SizedBox(width:8, ), + Expanded( + child: Divider(color: Colors.black54,) + ), ], ), - ), - SizedBox(height: 2,), - Align( - alignment: Alignment.centerRight, - child: RichText( - text: TextSpan( - text: 'Register as New Email User', - style: const TextStyle(color: Color.fromARGB(255, 66, 66, 66), decoration: TextDecoration.underline), - recognizer: TapGestureRecognizer()..onTap = () { - Navigator.push(context, MaterialPageRoute(builder: (context) => const SignupPage()),); - }, + const SizedBox(height: 8,), + OutlinedButton( + onPressed: () { + Navigator.push(context, MaterialPageRoute(builder: (context) => const LoginEmailPage()),); + }, + style: ElevatedButton.styleFrom( + minimumSize: const Size.fromHeight(40), + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: const [ + Icon(Icons.mail_outlined, color: Color.fromARGB(255, 66, 66, 66),), + SizedBox(width: 8), + Text('Continue with Email', style: TextStyle(color: Color.fromARGB(255, 66, 66, 66)), ) + ], + ), + ), + SizedBox(height: 2,), + Align( + alignment: Alignment.centerRight, + child: RichText( + text: TextSpan( + text: 'Register as New Email User', + style: const TextStyle(color: Color.fromARGB(255, 66, 66, 66), decoration: TextDecoration.underline), + recognizer: TapGestureRecognizer()..onTap = () { + Navigator.push(context, MaterialPageRoute(builder: (context) => const SignupPage()),); + }, + ), ), ), - ), - ], + ], + ), ), ), - ), - ) + ) ); } -} \ No newline at end of file +} diff --git a/lib/pages/start_loading_page.dart b/lib/pages/start_loading_page.dart index 67ded96..12eb140 100644 --- a/lib/pages/start_loading_page.dart +++ b/lib/pages/start_loading_page.dart @@ -45,7 +45,7 @@ class _StartLoadingPageState extends State { Navigator.pushReplacement(context, FadePageRoute(MainPage(token: token))); } else { - Navigator.pushReplacement(context, FadePageRoute(const LoginPage())); + Navigator.pushReplacement(context, FadePageRoute(LoginPage())); } } return; diff --git a/lib/widgets/kakao_login.dart b/lib/widgets/kakao_login.dart new file mode 100644 index 0000000..ac06787 --- /dev/null +++ b/lib/widgets/kakao_login.dart @@ -0,0 +1,39 @@ +import 'package:cs496_2nd_week/widgets/social_login.dart'; +import 'package:flutter/material.dart'; +import 'package:kakao_flutter_sdk_user/kakao_flutter_sdk_user.dart'; + +class KakaoLogin implements SocialLogin { + @override + Future login() async { + try { + bool isInstalled = await isKakaoTalkInstalled(); + if (isInstalled) { + try { + await UserApi.instance.loginWithKakaoTalk(); + return true; + } catch (e) { + return false; + } + } else { + try { + await UserApi.instance.loginWithKakaoAccount(); + return true; + } catch (e) { + return false; + } + } + } catch (e) { + return false; + } + } + + @override + Future logout() async { + try { + await UserApi.instance.unlink(); + return true; + } catch (error) { + return false; + } + } +} diff --git a/lib/widgets/main_view_model.dart b/lib/widgets/main_view_model.dart new file mode 100644 index 0000000..fd60f9c --- /dev/null +++ b/lib/widgets/main_view_model.dart @@ -0,0 +1,24 @@ +import 'package:kakao_flutter_sdk_user/kakao_flutter_sdk_user.dart'; + +import 'social_login.dart'; + +class MainViewModel{ + final SocialLogin _socialLogin; + bool isLogined = false; + User? user; + + MainViewModel(this._socialLogin); + + Future login() async{ + isLogined = await _socialLogin.login(); + if (isLogined) { + user = await UserApi.instance.me(); + } + } + + Future logout() async{ + await _socialLogin.logout(); + isLogined = false; + user = null; + } +} \ No newline at end of file diff --git a/lib/widgets/social_login.dart b/lib/widgets/social_login.dart new file mode 100644 index 0000000..65b749e --- /dev/null +++ b/lib/widgets/social_login.dart @@ -0,0 +1,4 @@ +abstract class SocialLogin{ + Future login(); + Future logout(); +} \ No newline at end of file diff --git a/pubspec.yaml b/pubspec.yaml index 70d3679..432a6b7 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -44,6 +44,7 @@ dependencies: getwidget: ^3.0.1 video_player: ^2.4.5 flutter_markdown: ^0.6.10+2 + kakao_flutter_sdk_user: ^1.2.1 dev_dependencies: flutter_test: From b1d9477bbd20a7735038326de2a04a071e74072f Mon Sep 17 00:00:00 2001 From: leeyjwinter Date: Mon, 11 Jul 2022 20:52:18 +0900 Subject: [PATCH 2/4] =?UTF-8?q?=EC=B9=B4=EC=B9=B4=EC=98=A4=ED=86=A1=20?= =?UTF-8?q?=EB=A1=9C=EA=B7=B8=EC=95=84=EC=9B=83?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/pages/login_page.dart | 2 - lib/pages/my_info.dart | 175 +++++++++++++++++++++++++++++++++++--- 2 files changed, 162 insertions(+), 15 deletions(-) diff --git a/lib/pages/login_page.dart b/lib/pages/login_page.dart index 091e4b2..4ad0b6c 100644 --- a/lib/pages/login_page.dart +++ b/lib/pages/login_page.dart @@ -8,9 +8,7 @@ import 'package:flutter/gestures.dart'; import 'package:flutter/material.dart'; import 'package:flutter/src/foundation/key.dart'; import 'package:flutter/src/widgets/framework.dart'; -import 'dart:developer'; import 'package:flutter_secure_storage/flutter_secure_storage.dart'; -import 'package:cs496_2nd_week/widgets/main_view_model.dart'; class LoginPage extends StatefulWidget { LoginPage({Key? key}) : super(key: key); diff --git a/lib/pages/my_info.dart b/lib/pages/my_info.dart index 946cba9..604a624 100644 --- a/lib/pages/my_info.dart +++ b/lib/pages/my_info.dart @@ -2,24 +2,27 @@ import 'package:cs496_2nd_week/pages/start_loading_page.dart'; import 'package:cs496_2nd_week/utils/fade_page_route.dart'; import 'package:flutter/material.dart'; import 'package:flutter_secure_storage/flutter_secure_storage.dart'; +import 'package:cs496_2nd_week/widgets/kakao_login.dart'; +import 'package:cs496_2nd_week/widgets/main_view_model.dart'; +import 'package:flutter/src/widgets/framework.dart'; -class MyinfoPage extends StatelessWidget { - const MyinfoPage({Key? key}) : super(key: key); +class MyinfoPage extends StatefulWidget { + MyinfoPage({Key? key}) : super(key: key); + + @override + State createState() => _MyinfoPageState(); +} + +class _MyinfoPageState extends State { + + final viewModel = MainViewModel(KakaoLogin()); static const storage = FlutterSecureStorage(); + + @override Widget build(BuildContext context) { return Scaffold( - // appBar: PreferredSize( - // preferredSize: Size.fromHeight(20), - // child: AppBar( - // title: '', - // backgroundColor: Color(0xFF7C74E9), - // automaticallyImplyLeading: true, - // actions: [], - // elevation: 2, - // ), - // ), backgroundColor: Colors.white, body: SafeArea( child: GestureDetector( @@ -116,8 +119,11 @@ class MyinfoPage extends StatelessWidget { shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(20)), color: Color(0xFFF5F6F9), - onPressed: () { + onPressed: () async{ storage.delete(key: 'token'); + print('logged in = ${widget}'); + await viewModel.logout(); + setState(() {}); Navigator.pushReplacement(context, MaterialPageRoute(builder: (context) => const StartLoadingPage()),); }, child: Row(children: [ @@ -140,3 +146,146 @@ class MyinfoPage extends StatelessWidget { ); } } +// +// class MyinfoPage extends StatelessWidget { +// MyinfoPage({Key? key}) : super(key: key); +// +// final viewModel = MainViewModel(KakaoLogin()); +// static const storage = FlutterSecureStorage(); +// @override +// Widget build(BuildContext context) { +// return Scaffold( +// // appBar: PreferredSize( +// // preferredSize: Size.fromHeight(20), +// // child: AppBar( +// // title: '', +// // backgroundColor: Color(0xFF7C74E9), +// // automaticallyImplyLeading: true, +// // actions: [], +// // elevation: 2, +// // ), +// // ), +// backgroundColor: Colors.white, +// body: SafeArea( +// child: GestureDetector( +// onTap: () => FocusScope.of(context).unfocus(), +// child: Container( +// width: double.infinity, +// height: double.infinity, +// decoration: BoxDecoration( +// color: Colors.white, +// ), +// child: Column( +// mainAxisSize: MainAxisSize.max, +// children: [ +// Padding( +// padding: EdgeInsetsDirectional.fromSTEB(50, 50, 50, 50), +// child: Container( +// width: 100, +// height: 100, +// decoration: BoxDecoration( +// color: Color(0xFFEEEEEE), +// image: DecorationImage( +// fit: BoxFit.cover, +// image: Image.network( +// 'https://static.vecteezy.com/system/resources/previews/001/188/566/original/fire-png.png', +// ).image, +// ), +// shape: BoxShape.circle, +// ), +// ), +// ), +// Padding( +// padding: EdgeInsets.symmetric(horizontal: 20, vertical: 10), +// child: FlatButton( +// padding: EdgeInsets.all(20), +// shape: RoundedRectangleBorder( +// borderRadius: BorderRadius.circular(20)), +// color: Color(0xFFF5F6F9), +// onPressed: () {}, +// child: Row(children: [ +// Icon( +// Icons.account_circle_outlined, +// size: 40, +// color: Colors.purple, +// ), +// SizedBox(width: 20,), +// Expanded(child: Text("User Name" , style: Theme.of(context).textTheme.bodyText1)), +// Icon(Icons.arrow_forward_ios) +// ]), +// ), +// ), +// Padding( +// padding: EdgeInsets.symmetric(horizontal: 20, vertical: 10), +// child: FlatButton( +// padding: EdgeInsets.all(20), +// shape: RoundedRectangleBorder( +// borderRadius: BorderRadius.circular(20)), +// color: Color(0xFFF5F6F9), +// onPressed: () {}, +// child: Row(children: [ +// Icon( +// Icons.school_outlined, +// size: 40, +// color: Colors.purple, +// ), +// SizedBox(width: 20,), +// Expanded(child: Text("School" , style: Theme.of(context).textTheme.bodyText1)), +// Icon(Icons.arrow_forward_ios) +// ]), +// ), +// ), +// Padding( +// padding: EdgeInsets.symmetric(horizontal: 20, vertical: 10), +// child: FlatButton( +// padding: EdgeInsets.all(20), +// shape: RoundedRectangleBorder( +// borderRadius: BorderRadius.circular(20)), +// color: Color(0xFFF5F6F9), +// onPressed: () {}, +// child: Row(children: [ +// Icon( +// Icons.emoji_events_outlined, +// size: 40, +// color: Colors.purple, +// ), +// SizedBox(width: 20,), +// Expanded(child: Text("My Score" , style: Theme.of(context).textTheme.bodyText1)), +// Icon(Icons.arrow_forward_ios) +// ]), +// ), +// ),Padding( +// padding: EdgeInsets.symmetric(horizontal: 20, vertical: 10), +// child: FlatButton( +// padding: EdgeInsets.all(20), +// shape: RoundedRectangleBorder( +// borderRadius: BorderRadius.circular(20)), +// color: Color(0xFFF5F6F9), +// onPressed: () async{ +// storage.delete(key: 'token'); +// if(viewModel.isLogined==true){ +// await viewModel.logout(); +// setState(() {}); +// } +// Navigator.pushReplacement(context, MaterialPageRoute(builder: (context) => const StartLoadingPage()),); +// }, +// child: Row(children: [ +// Icon( +// Icons.logout_outlined, +// size: 40, +// color: Colors.purple, +// ), +// SizedBox(width: 20,), +// Expanded(child: Text("Log Out" , style: Theme.of(context).textTheme.bodyText1)), +// Icon(Icons.arrow_forward_ios) +// ]), +// ), +// ) +// ], +// ), +// ), +// ), +// ), +// ); +// } +// } From 0752f3f4c974a077ab4993517644b61135e4f24c Mon Sep 17 00:00:00 2001 From: leeyjwinter Date: Mon, 11 Jul 2022 21:01:16 +0900 Subject: [PATCH 3/4] =?UTF-8?q?=EC=B9=B4=EC=B9=B4=EC=98=A4=ED=86=A1=20?= =?UTF-8?q?=EC=82=AC=EC=A7=84=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- assets/images/kakaotalk.png | Bin 0 -> 8140 bytes lib/pages/login_page.dart | 7 ++++--- 2 files changed, 4 insertions(+), 3 deletions(-) create mode 100644 assets/images/kakaotalk.png diff --git a/assets/images/kakaotalk.png b/assets/images/kakaotalk.png new file mode 100644 index 0000000000000000000000000000000000000000..3b03cab4e7053efa3b6cbcb58da1e745ee3f48b0 GIT binary patch literal 8140 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 b { onPressed: () async { await widget.viewModel.login(); setState((){}); - print("email is ${widget.viewModel.user?.kakaoAccount?.email}"); - Navigator.pushReplacement(context, FadePageRoute(MainPage(token: widget.viewModel.user?.kakaoAccount?.email))); + if(widget.viewModel.user?.kakaoAccount?.email != null) + Navigator.pushReplacement(context, FadePageRoute(MainPage(token: widget.viewModel.user?.kakaoAccount?.email))); }, style: ElevatedButton.styleFrom( minimumSize: const Size.fromHeight(40) @@ -56,7 +56,8 @@ class _LoginPageState extends State { child: Row( mainAxisAlignment: MainAxisAlignment.center, children: [ - Image.asset('assets/images/login_googleIcon.png', width: 20, height: 20, ), + // Image.asset('assets/images/login_googleIcon.png', width: 20, height: 20, ), + Image.asset('assets/images/kakaotalk.png',width:20, height: 20,), const SizedBox(width: 8), const Text('Continue with Kakao', style: TextStyle(color: Color.fromARGB(255, 66, 66, 66)), ) ], From ace4466f589359ecad9acbfef8960f58164dea65 Mon Sep 17 00:00:00 2001 From: leeyjwinter Date: Mon, 11 Jul 2022 21:10:47 +0900 Subject: [PATCH 4/4] =?UTF-8?q?=EB=8F=84=EC=A0=84=EA=B3=BC=EC=A0=9C=20?= =?UTF-8?q?=ED=83=AD=20=EB=A0=88=EC=9D=B4=EC=95=84=EC=9B=83?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/widgets/challenges.dart | 417 ++++++++++++++++++++++++++++++++++++ 1 file changed, 417 insertions(+) create mode 100644 lib/widgets/challenges.dart diff --git a/lib/widgets/challenges.dart b/lib/widgets/challenges.dart new file mode 100644 index 0000000..b5e34f1 --- /dev/null +++ b/lib/widgets/challenges.dart @@ -0,0 +1,417 @@ +import 'package:flutter/material.dart'; +import 'package:http/http.dart' as http; + +void main() { + runApp(const MyApp()); +} + +class MyApp extends StatelessWidget { + const MyApp({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return MaterialApp( + home: const Challenges(), + ); + } +} + +class Challenges extends StatefulWidget { + const Challenges({Key? key}) : super(key: key); + + @override + State createState() => _ChallengesState(); +} + +_getSize(GlobalKey key) { + if (key.currentContext != null) { + final RenderBox renderBox = + key.currentContext!.findRenderObject() as RenderBox; + Size size = renderBox.size; + return size; + } +} + +GlobalKey _cardSizeKey = GlobalKey(); +final cardWidth = _getSize(_cardSizeKey).width; + +class _ChallengesState extends State { + @override + Widget build(BuildContext context) { + return Scaffold( + body: GridView.count( + padding: const EdgeInsets.all(10), + crossAxisCount: 2, + children: [ + Card(shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(16.0)), + elevation: 5, + color: Color(0xffD9E5FF), + child: Row( + children: [ + Expanded( + flex: 1, + child: Image.network( + "https://cdn-icons-png.flaticon.com/512/3621/3621723.png", + ), + ), + Expanded( + flex: 1, + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + SizedBox( + height: 10, + ), + Container( + width: 70, + child: Text('첫 프로젝트\n 등록'), + ), + SizedBox( + height: 10, + ), + Container( + width: 70, + child: Text( + '현재 프로젝트 수 : ', + style: TextStyle(fontSize: 10), + ), + ), + ], + ), + ) + ], + )), + Card( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(16.0)), + elevation: 5, + color: Colors.amber.shade200, + child: Row( + children: [ + Expanded( + flex: 1, + child: Image.network( + "https://cdn-icons-png.flaticon.com/512/329/329588.png", + )), + Expanded( + flex: 1, + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + SizedBox( + height: 10, + ), + Container( + width: 70, + child: Text('조회 수\n5개 이상'), + ), + SizedBox( + height: 10, + ), + Container( + width: 70, + child: Text( + '현재 조회수 : ', + style: TextStyle(fontSize: 10), + ), + ), + ], + ), + ) + ], + )), + Card( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(16.0)), + elevation: 5, + color: Colors.blue.shade300, + child: Row( + children: [ + Expanded( + flex: 1, + child: Image.network( + "https://cdn-icons-png.flaticon.com/512/408/408472.png", + ), + ), + Expanded( + flex: 1, + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + SizedBox( + height: 10, + ), + Container( + width: 70, + child: Text('추천 수\n5개 이상'), + ), + SizedBox( + height: 10, + ), + Container( + width: 70, + child: Text( + '현재 추천수 : ', + style: TextStyle(fontSize: 10), + ), + ), + ], + ), + ) + ], + )), + Card(shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(16.0)), + elevation: 5, + color: Colors.pink.shade200, + child: Row( + children: [ + Expanded( + flex: 1, + child: Image.network( + "https://cdn-icons-png.flaticon.com/512/905/905750.png", + ), + ), + Expanded( + flex: 1, + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + SizedBox( + height: 10, + ), + Container( + width: 70, + child: Text('프로젝트 수\n2개 이상'), + ), + SizedBox( + height: 10, + ), + Container( + width: 70, + child: Text( + '현재 프로젝트 수 : ', + style: TextStyle(fontSize: 10), + ), + ), + ], + ), + ) + ], + )), + Card(shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(16.0)), + elevation: 5, + color: Color(0xffD9E5FF), + child: Row( + children: [ + Expanded( + flex: 1, + child: Image.network( + "https://cdn-icons-png.flaticon.com/512/3621/3621723.png", + ), + ), + Expanded( + flex: 1, + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + SizedBox( + height: 10, + ), + Container( + width: 70, + child: Text('조회수 5개 이상 달성!'), + ), + SizedBox( + height: 10, + ), + Container( + width: 70, + child: Text( + '현재 조회수 : ', + style: TextStyle(fontSize: 10), + ), + ), + ], + ), + ) + ], + )), + Card( + key: _cardSizeKey, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(16.0)), + elevation: 5, + color: Colors.amber.shade200, + child: Row( + children: [ + Expanded( + flex: 1, + child: Image.network( + "https://cdn-icons-png.flaticon.com/512/329/329588.png", + )), + Expanded( + flex: 1, + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + SizedBox( + height: 10, + ), + Container( + width: 70, + child: Text('조회수 5개 이상 달성!'), + ), + SizedBox( + height: 10, + ), + Container( + width: 70, + child: Text( + '현재 조회수 : ', + style: TextStyle(fontSize: 10), + ), + ), + ], + ), + ) + ], + )), + Card( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(16.0)), + elevation: 5, + color: Colors.blue.shade300, + child: Row( + children: [ + Expanded( + flex: 1, + child: Image.network( + "https://cdn-icons-png.flaticon.com/512/408/408472.png", + ), + ), + Expanded( + flex: 1, + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + SizedBox( + height: 10, + ), + Container( + width: 70, + child: Text('조회수 5개 이상 달성!'), + ), + SizedBox( + height: 10, + ), + Container( + width: 70, + child: Text( + '현재 조회수 : ', + style: TextStyle(fontSize: 10), + ), + ), + ], + ), + ) + ], + )), + Card(shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(16.0)), + elevation: 5, + color: Colors.pink.shade200, + child: Row( + children: [ + Expanded( + flex: 1, + child: Image.network( + "https://cdn-icons-png.flaticon.com/512/905/905750.png", + ), + ), + Expanded( + flex: 1, + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + SizedBox( + height: 10, + ), + Container( + width: 70, + child: Text('조회수 5개 이상 달성!'), + ), + SizedBox( + height: 10, + ), + Container( + width: 70, + child: Text( + '현재 조회수 : ', + style: TextStyle(fontSize: 10), + ), + ), + ], + ), + ) + ], + )), + Card(shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(16.0)), + elevation: 5, + color: Color(0xffD9E5FF), + child: Row( + children: [ + Expanded( + flex: 1, + child: Image.network( + "https://cdn-icons-png.flaticon.com/512/3621/3621723.png", + ), + ), + Expanded( + flex: 1, + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + SizedBox( + height: 10, + ), + Container( + width: 70, + child: Text('조회수 5개 이상 달성!'), + ), + SizedBox( + height: 10, + ), + Container( + width: 70, + child: Text( + '현재 조회수 : ', + style: TextStyle(fontSize: 10), + ), + ), + ], + ), + ) + ], + )), + Card( + color: Colors.red.shade200, + ), + Card( + color: Colors.purple.shade300, + ), + Card(color: Colors.green.shade400), + Card( + color: Colors.teal.shade200, + ), + Card( + color: Colors.green.shade300, + ), + Card(color: Colors.indigo.shade400), + ], + )); + } +}