diff --git a/android/app/build.gradle b/android/app/build.gradle index 7baa21e..a5c8cfa 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -26,7 +26,7 @@ apply plugin: 'kotlin-android' apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" android { - compileSdkVersion 30 + compileSdkVersion 31 sourceSets { main.java.srcDirs += 'src/main/kotlin' @@ -36,7 +36,7 @@ android { // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). applicationId "com.example.my_side_client" minSdkVersion 16 - targetSdkVersion 30 + targetSdkVersion 31 versionCode flutterVersionCode.toInteger() versionName flutterVersionName } diff --git a/android/build.gradle b/android/build.gradle index c505a86..714549c 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -1,5 +1,5 @@ buildscript { - ext.kotlin_version = '1.3.50' + ext.kotlin_version = '1.6.10' repositories { google() jcenter() diff --git a/assets/arrow2down.svg b/assets/arrow2down.svg new file mode 100644 index 0000000..b9c55ac --- /dev/null +++ b/assets/arrow2down.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/arrow2up.svg b/assets/arrow2up.svg new file mode 100644 index 0000000..1089162 --- /dev/null +++ b/assets/arrow2up.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/play_big.svg b/assets/play_big.svg new file mode 100644 index 0000000..a184cde --- /dev/null +++ b/assets/play_big.svg @@ -0,0 +1,4 @@ + + + + diff --git a/assets/recipe_sample_imgs/01.png b/assets/recipe_sample_imgs/01.png new file mode 100644 index 0000000..e863bf0 Binary files /dev/null and b/assets/recipe_sample_imgs/01.png differ diff --git a/assets/recipe_sample_imgs/04.png b/assets/recipe_sample_imgs/04.png new file mode 100644 index 0000000..8f5c0b3 Binary files /dev/null and b/assets/recipe_sample_imgs/04.png differ diff --git a/assets/sample_ingred/01.png b/assets/sample_ingred/01.png new file mode 100644 index 0000000..8ea1c38 Binary files /dev/null and b/assets/sample_ingred/01.png differ diff --git a/assets/sample_ingred/02.png b/assets/sample_ingred/02.png new file mode 100644 index 0000000..e900c3b Binary files /dev/null and b/assets/sample_ingred/02.png differ diff --git a/assets/sample_ingred/03.png b/assets/sample_ingred/03.png new file mode 100644 index 0000000..344c5ef Binary files /dev/null and b/assets/sample_ingred/03.png differ diff --git a/lib/TabRecipe/RecipeDetailPage.dart b/lib/TabRecipe/RecipeDetailPage.dart index 91cfb11..f265846 100644 --- a/lib/TabRecipe/RecipeDetailPage.dart +++ b/lib/TabRecipe/RecipeDetailPage.dart @@ -1,8 +1,15 @@ import 'package:flutter/material.dart'; import 'package:flutter_svg/svg.dart'; +import 'package:get/get.dart'; +import 'package:my_side_client/constantsList.dart'; +import 'package:my_side_client/controllers/RecipeControllers/RecipeDetailController.dart'; import 'package:my_side_client/wigets/etcwidgets/starRating.dart'; class RecipeDetailPage extends StatelessWidget { + final bool hasVideo = true; + final bool hasVideoComment = true; + final RegisterDetailController registerDetailController = + Get.put(RegisterDetailController()); @override Widget build(BuildContext context) { return Stack( @@ -11,32 +18,102 @@ class RecipeDetailPage extends StatelessWidget { Scaffold( backgroundColor: Colors.transparent, appBar: buildRecipDetailAppbar(), - body: SingleChildScrollView( - child: Column( - children: [ - SizedBox(height: 220), - buildFoodTypeContainer('양식'), - SizedBox(height: 8), - buildRecipeDetailContainer( - '올리브유로 만든 뽀빠이 감바스', - ['위암', '대장암', '새우', '마늘'], - [false, false, true, true], - [1, 25, 2], - '바다의 채소라 불리는 미역은 칼슘이 풍부해서 뼈를 튼튼하게 해준다. 식이섬유가 풍부해 포만감을 주며, 장운동을 도와 변비를 예방한다.', - '생새우는 위험하기 때문에 충분히 익혀주세요.', - '102동 옆집', - ['갑상선암', '수술후'], - [123, 22, 94, 22], + body: GetBuilder( + builder: (controller) { + return SingleChildScrollView( + child: Column( + children: [ + hasVideo + ? Column( + children: [ + SizedBox(height: 59), + SvgPicture.asset('assets/play_big.svg'), + SizedBox(height: 105), + ], + ) + : SizedBox(height: 220), + buildFoodTypeContainer('양식', hasVideo, 15, 24), + SizedBox(height: 8), + buildRecipeDetailContainer( + '올리브유로 만든 뽀빠이 감바스', + [1, 25, 2], + '바다의 채소라 불리는 미역은 칼슘이 풍부해서 뼈를 튼튼하게 해준다. 식이섬유가 풍부해 포만감을 주며, 장운동을 도와 변비를 예방한다.', + '생새우는 위험하기 때문에 충분히 익혀주세요.', + '102동 옆집', + ['갑상선암', '수술후'], + [123, 22, 94, 22], + controller.ingredInfoExpanded, + controller.expandIngredInfo, + ), + !hasVideoComment && hasVideo + ? SizedBox() + : tapBarRow(controller.belowType, + controller.setBelowType, hasVideo), + buildDetailBelowContainer(controller.belowType, hasVideo), + ], ), - buildDetailBelowContainer(1), - ], - ), + ); + }, ), ) ], ); } + Widget tapBarRow(int curType, Function tapFunc, bool hasVideo) { + return Container( + color: Colors.white, + child: Row( + children: [ + selectType( + '재료', + curType == 1, + tapFunc, + 1, + ), + selectType( + hasVideo ? '영상설명' : '요리순서', + curType == 2, + tapFunc, + 2, + ), + ], + ), + ); + } + + Widget selectType( + String typeString, bool isSelected, Function tapFunc, int id) { + return Expanded( + child: InkWell( + child: Column( + children: [ + Text( + typeString, + style: TextStyle( + color: isSelected ? Color(0xFF3BD7E2) : Color(0xFF666666), + fontSize: 16, + fontWeight: FontWeight.w500, + ), + ), + SizedBox(height: 9), + Container( + height: 3, + color: isSelected ? Color(0xFF3BD7E2) : Colors.white, + ), + ], + ), + onTap: () { + if (id == 1) { + tapFunc(1); + } else { + tapFunc(2); + } + }, + ), + ); + } + Widget buildGuideButton() { return Container( padding: EdgeInsets.symmetric( @@ -62,14 +139,18 @@ class RecipeDetailPage extends StatelessWidget { ); } - Widget buildDetailBelowTitle(int titleType) { + Widget buildDetailBelowTitle(int titleType, bool hasVideo) { return SizedBox( width: double.infinity, child: Stack( alignment: Alignment.bottomCenter, children: [ Text( - titleType == 1 ? '재료' : '요리순서', + titleType == 1 + ? '재료' + : hasVideo + ? '영상설명' + : '요리순서', style: TextStyle( color: Color(0xFF111111), fontWeight: FontWeight.w500, @@ -120,6 +201,7 @@ class RecipeDetailPage extends StatelessWidget { Widget buildDetailBelowContainer( int containerType, + bool hasVideo, ) { return Container( width: double.infinity, @@ -138,39 +220,81 @@ class RecipeDetailPage extends StatelessWidget { Stack( alignment: Alignment.bottomRight, children: [ - buildDetailBelowTitle(containerType), + buildDetailBelowTitle(containerType, hasVideo), containerType == 1 ? buildGuideButton() : SizedBox(), ], ), SizedBox(height: 24), - // TODO : 이부분도 subtitle list, subtile 안의 재료 list따로 받아햐함. - Row( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - buildDetailBelowSubtitle('기본재료'), - SizedBox( - width: 16, - ), - Expanded( - child: Column( - children: [ - const Divider( - thickness: 1.5, - color: Color(0xFFDDDDDD), - ), - buildIngredientDetail('마늘 3개'), - buildIngredientDetail('새우 12마리'), - buildIngredientDetail('시금치 200g'), - ], - ), + containerType == 1 + ? buildIngreDetailTiles() + : hasVideo + ? buildVideoCommentTile() + : buildRecipeOrderTiles() + ], + ), + ), + ); + } + + Widget buildVideoCommentTile() { + return Text( + '올리브유는 엑스트라버진 올리브유가 좋아요~!\n 추가로 방울 토마토도 넣으면 더 양양가 있는 감바스가 탄생할거예요~ 🤗', + style: const TextStyle( + color: Color(0xFF666666), + fontWeight: FontWeight.w300, + fontSize: 16, + ), + ); + } + + Widget buildRecipeOrderTiles() { + List widgetList = []; + for (var i = 0; i < recipeOrderContent.length; i++) { + widgetList.add( + SizedBox( + width: double.infinity, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + buildDetailBelowSubtitle('# 0${i + 1}'), + SizedBox(height: 8), + recipeOrderHasPhoto[i] + ? Column( + children: [ + Image.asset(recipeOrderPhoto[i]), + SizedBox(height: 8), + ], + ) + : SizedBox(), + Text( + recipeOrderContent[i], + style: const TextStyle( + color: Color(0xFF666666), + fontWeight: FontWeight.w300, + fontSize: 16, ), - ], - ), - SizedBox(height: 24), + ), + i == recipeOrderContent.length - 1 + ? SizedBox() + : SizedBox(height: 24) + ], + ), + ), + ); + } + return Column(children: widgetList); + } + + Widget buildIngreDetailTiles() { + List widgetList = []; + for (var i = 0; i < ingreTitleList.length; i++) { + widgetList.add( + Column( + children: [ Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ - buildDetailBelowSubtitle('양념장 소스 재료'), + buildDetailBelowSubtitle(ingreTitleList[i]), SizedBox( width: 16, ), @@ -181,17 +305,19 @@ class RecipeDetailPage extends StatelessWidget { thickness: 1.5, color: Color(0xFFDDDDDD), ), - buildIngredientDetail('소금 1/2 컵'), - buildIngredientDetail('올리브유 1컵'), + for (var j = 0; j < detailIngreList[i].length; j++) + buildIngredientDetail(detailIngreList[i][j]), ], ), ), ], ), + i == ingreTitleList.length - 1 ? SizedBox() : SizedBox(height: 24) ], ), - ), - ); + ); + } + return Column(children: widgetList); } Widget buildIngredientDetail(String ingreDetail) { @@ -214,14 +340,14 @@ class RecipeDetailPage extends StatelessWidget { //TODO : 이부분 class로 가져오면 쉽게 할수 있음, model이 정해지면 그때수정 Widget buildRecipeDetailContainer( String recipeName, - List cancerIngredInfo, - List cancerIngredInfoType, List recipeInfoNumbers, String recipeExplain, String recipeCaution, String nickName, List usrInfos, List iconsRowNumbers, + bool isIngredInfoExpanded, + Function expandFunc, ) { return Container( width: double.infinity, @@ -243,19 +369,97 @@ class RecipeDetailPage extends StatelessWidget { fontSize: 24, ), ), - buildFoodInfoRow( - cancerIngredInfo, - cancerIngredInfoType, + SizedBox(height: 10), + buildIngredRelatedCancerNComponentColumns(isIngredInfoExpanded), + InkWell( + child: Center( + child: isIngredInfoExpanded + ? SvgPicture.asset('assets/arrow2up.svg') + : SvgPicture.asset('assets/arrow2down.svg'), + ), + onTap: expandFunc, ), + SizedBox(height: 32), buildRecipeInfoRow(recipeInfoNumbers), buildRecipeTextBox(recipeExplain, recipeCaution), buildUsrInfoBox(nickName, usrInfos[0], usrInfos[1]), buildRecipeIconsRow(iconsRowNumbers), + SizedBox(height: 25), + ], + ), + ); + } + + Widget buildIngredRelatedCancerNComponentColumns(bool isExpanded) { + List widgetList = []; + int colNum = isExpanded ? ingredImgs.length : 1; + for (var i = 0; i < colNum; i++) { + widgetList.add( + buildIngredRelatedCancerNComponent( + imgContainerColor[i], + ingredImgs[i], + ingredRelatedCancer[i], + ingredRelatedComponent[i], + ), + ); + } + return SizedBox( + height: isExpanded ? 145 : 50, + child: ListView( + scrollDirection: Axis.horizontal, + children: [ + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: widgetList, + ), ], ), ); } + Widget buildIngredRelatedCancerNComponent( + Color imgContColor, + String imgPth, + List ingredRelatedCancers, + List ingredRelatedComponents, + ) { + return Column( + children: [ + Row( + children: [ + Container( + height: 35, + width: 35, + decoration: BoxDecoration( + color: imgContColor, + borderRadius: BorderRadius.all(Radius.circular(50)), + ), + child: Image.asset( + imgPth, + height: 25, + ), + ), + SizedBox(width: 8), + for (var i = 0; i < ingredRelatedCancers.length; i++) + buildIngredInfoRow(ingredRelatedCancers[i], false), + for (var i = 0; i < ingredRelatedComponents.length; i++) + buildIngredInfoRow(ingredRelatedComponents[i], true) + ], + ), + SizedBox(height: 8), + ], + ); + } + + Widget buildIngredInfoRow(String infoText, bool isIngred) { + return Row( + children: [ + buildRoundFoodInfo(infoText, isIngred), + SizedBox(width: 8), + ], + ); + } + Widget buildIconAndNumber(String number, String icon, bool isLast) { return Row( children: [ @@ -507,31 +711,6 @@ class RecipeDetailPage extends StatelessWidget { ); } - //TODO : container가 여러개로 늘경우 wrap으로 바꿔줘야함 - Widget buildFoodInfoRow(List infos, List infoTypes) { - return Column( - children: [ - SizedBox( - height: 11, - ), - Row( - children: [ - buildRoundFoodInfo(infos[0], infoTypes[0]), - SizedBox(width: 8), - buildRoundFoodInfo(infos[1], infoTypes[1]), - SizedBox(width: 8), - buildRoundFoodInfo(infos[2], infoTypes[2]), - SizedBox(width: 8), - buildRoundFoodInfo(infos[3], infoTypes[3]), - ], - ), - SizedBox( - height: 32, - ), - ], - ); - } - Widget buildRoundFoodInfo(String infoText, bool isIngrediant) { return Container( padding: EdgeInsets.symmetric( @@ -592,7 +771,12 @@ class RecipeDetailPage extends StatelessWidget { ); } - Widget buildFoodTypeContainer(String foodType) { + Widget buildFoodTypeContainer( + String foodType, + bool hasVideo, + int durationMin, + int durationSec, + ) { return Padding( padding: EdgeInsets.symmetric(horizontal: 17), child: Row( @@ -618,6 +802,28 @@ class RecipeDetailPage extends StatelessWidget { ), ), const Spacer(), + hasVideo + ? Container( + padding: EdgeInsets.symmetric( + vertical: 8, + horizontal: 12, + ), + decoration: BoxDecoration( + color: Colors.black.withOpacity(0.5), + borderRadius: const BorderRadius.all( + Radius.circular(30), + ), + ), + child: Text( + '$durationMin:$durationSec', + style: const TextStyle( + color: Colors.white, + fontWeight: FontWeight.w300, + fontSize: 14, + ), + ), + ) + : SizedBox(), ], ), ); diff --git a/lib/TabRecipe/RecipeMain.dart b/lib/TabRecipe/RecipeMain.dart index 6800399..b083492 100644 --- a/lib/TabRecipe/RecipeMain.dart +++ b/lib/TabRecipe/RecipeMain.dart @@ -110,7 +110,7 @@ class _RecipeMainState extends State { itemBuilder: (BuildContext context, int index) { return RecipeTileType1Widget( recipeTile: recipeTiles[index], - tileHeight: 164, + tileHeight: 170, ); }, separatorBuilder: (BuildContext context, int index) => diff --git a/lib/constantsList.dart b/lib/constantsList.dart index ec43f48..6a1f624 100644 --- a/lib/constantsList.dart +++ b/lib/constantsList.dart @@ -1,3 +1,5 @@ +import 'package:flutter/material.dart'; + final List cancerType = [ '위암', '폐암', @@ -81,4 +83,55 @@ final List foodAmountList = [ '2인분', '3인분', '4인분', -]; \ No newline at end of file +]; +//재료 +final List ingreTitleList = [ + '기본 재료', + '양념장 소스 재료', +]; + +final List> detailIngreList = [ + ['마늘 3개', '새우 12마리', '시금치 200g'], + ['소금1/2 컵', '올리브유 1컵'], +]; +//요리순서부분 +final List recipeOrderHasPhoto = [true, false, false, true, false]; +final List recipeOrderContent = [ + '시금치의 밑단을 자르고 손질합니다.', + '새우는 껍질을 까고 소금 밑간을 합니다.', + '마늘을 편썰어 줍니다.', + '마늘을 올리브유에 볶아줍니다.', + '손질한 시금치를 넣어 함께 볶아주면 완성!' +]; + +final List recipeOrderPhoto = [ + 'assets/recipe_sample_imgs/01.png', + '', + '', + 'assets/recipe_sample_imgs/04.png', + '', +]; + +final List ingredImgs = [ + 'assets/sample_ingred/01.png', + 'assets/sample_ingred/02.png', + 'assets/sample_ingred/03.png', +]; + +final List> ingredRelatedCancer = [ + ['갑상선암'], + ['위암', '간암', '대장암'], + ['유방암', '대장암', '위암'], +]; + +final List> ingredRelatedComponent = [ + ['요오드', '아연', '칼슘', '단백질'], + ['셀레늄', '알리신', '핵산', '비타민B'], + ['베타카로틴', '비타민A', '엽산', '철분'], +]; + +final List imgContainerColor = [ + Color(0xFFFFE5D9), + Color(0xFFF4F4F4), + Color(0xFFEAEED2), +]; diff --git a/lib/controllers/RecipeControllers/RecipeDetailController.dart b/lib/controllers/RecipeControllers/RecipeDetailController.dart new file mode 100644 index 0000000..36a4b28 --- /dev/null +++ b/lib/controllers/RecipeControllers/RecipeDetailController.dart @@ -0,0 +1,16 @@ +import 'package:get/get.dart'; + +class RegisterDetailController extends GetxController { + int belowType = 1; + bool ingredInfoExpanded = false; + + void setBelowType(int type) { + belowType = type; + update(); + } + + void expandIngredInfo() { + ingredInfoExpanded = !ingredInfoExpanded; + update(); + } +} diff --git a/lib/controllers/RecipeControllers/RecipeRegisterController.dart b/lib/controllers/RecipeControllers/RecipeRegisterController.dart index 915bbe1..6d2786f 100644 --- a/lib/controllers/RecipeControllers/RecipeRegisterController.dart +++ b/lib/controllers/RecipeControllers/RecipeRegisterController.dart @@ -88,4 +88,4 @@ class RecipeRegisterController extends GetxController { starRating > 0 && (hours > 0 || minutes > 0); } -} \ No newline at end of file +} diff --git a/lib/controllers/loginMainController.dart b/lib/controllers/loginMainController.dart index 7d3d3c6..5007369 100644 --- a/lib/controllers/loginMainController.dart +++ b/lib/controllers/loginMainController.dart @@ -29,11 +29,6 @@ class LoginMainController extends GetxController { //자동로그인 var loginStorage = GetStorage(); - void fistTimeRunning() { - loginStorage.write('isFirstRunApp', false); - update(); - } - @override void onInit() { emailTextField.tec.addListener(onListenEmail); @@ -48,6 +43,11 @@ class LoginMainController extends GetxController { super.onClose(); } + void fistTimeRunning() { + loginStorage.write('isFirstRunApp', false); + update(); + } + void onListenEmail() { emailTextField.onListenTextFieldType1(); update(); diff --git a/lib/main.dart b/lib/main.dart index bd587c2..cd82668 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -65,6 +65,7 @@ void main() async { scrollbarTheme: ScrollbarThemeData( thumbColor: MaterialStateProperty.all(Color(0xFF3BD7E2)), trackColor: MaterialStateProperty.all(Color(0xFFF4F4F4)), + //trackColor: MaterialStateProperty.all(Colors.red), ), primaryColor: Color(Constants.primaryColorInt), visualDensity: VisualDensity.adaptivePlatformDensity, @@ -80,8 +81,8 @@ void main() async { // : autoLoginFlag // ? '/MainTab' // : '/', - ? '/RecipeDetailPage' - : '/RecipeDetailPage', + ? '/' + : '/', // home: LoginMainPage())); // home: MainTab(), getPages: [ diff --git a/pubspec.yaml b/pubspec.yaml index acd5373..a3c6b9c 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -69,6 +69,8 @@ flutter: - assets/food_img/ - assets/icons/ - assets/profile_img/ + - assets/recipe_sample_imgs/ + - assets/sample_ingred/