From f1049447045d5a9d9d9d9636f19a89981ad7cfe6 Mon Sep 17 00:00:00 2001 From: kkosang Date: Fri, 25 Apr 2025 22:02:39 +0900 Subject: [PATCH 1/5] feat: pub add image_picker --- pubspec.lock | 120 +++++++++++++++++++++++++++++++++++++++++++++++++++ pubspec.yaml | 1 + 2 files changed, 121 insertions(+) diff --git a/pubspec.lock b/pubspec.lock index 3f6ba92..b812d99 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -113,6 +113,14 @@ packages: url: "https://pub.dev" source: hosted version: "3.1.2" + cross_file: + dependency: transitive + description: + name: cross_file + sha256: "7caf6a750a0c04effbb52a676dce9a4a592e10ad35c34d6d2d0e4811160d5670" + url: "https://pub.dev" + source: hosted + version: "0.3.4+2" crypto: dependency: transitive description: @@ -185,6 +193,38 @@ packages: url: "https://pub.dev" source: hosted version: "7.0.1" + file_selector_linux: + dependency: transitive + description: + name: file_selector_linux + sha256: "54cbbd957e1156d29548c7d9b9ec0c0ebb6de0a90452198683a7d23aed617a33" + url: "https://pub.dev" + source: hosted + version: "0.9.3+2" + file_selector_macos: + dependency: transitive + description: + name: file_selector_macos + sha256: "271ab9986df0c135d45c3cdb6bd0faa5db6f4976d3e4b437cf7d0f258d941bfc" + url: "https://pub.dev" + source: hosted + version: "0.9.4+2" + file_selector_platform_interface: + dependency: transitive + description: + name: file_selector_platform_interface + sha256: a3994c26f10378a039faa11de174d7b78eb8f79e4dd0af2a451410c1a5c3f66b + url: "https://pub.dev" + source: hosted + version: "2.6.2" + file_selector_windows: + dependency: transitive + description: + name: file_selector_windows + sha256: "320fcfb6f33caa90f0b58380489fc5ac05d99ee94b61aa96ec2bff0ba81d3c2b" + url: "https://pub.dev" + source: hosted + version: "0.9.3+4" firebase_auth: dependency: "direct main" description: @@ -254,6 +294,14 @@ packages: url: "https://pub.dev" source: hosted version: "5.0.0" + flutter_plugin_android_lifecycle: + dependency: transitive + description: + name: flutter_plugin_android_lifecycle + sha256: f948e346c12f8d5480d2825e03de228d0eb8c3a737e4cdaa122267b89c022b5e + url: "https://pub.dev" + source: hosted + version: "2.0.28" flutter_riverpod: dependency: "direct main" description: @@ -304,6 +352,70 @@ packages: url: "https://pub.dev" source: hosted version: "4.1.2" + image_picker: + dependency: "direct main" + description: + name: image_picker + sha256: "021834d9c0c3de46bf0fe40341fa07168407f694d9b2bb18d532dc1261867f7a" + url: "https://pub.dev" + source: hosted + version: "1.1.2" + image_picker_android: + dependency: transitive + description: + name: image_picker_android + sha256: "317a5d961cec5b34e777b9252393f2afbd23084aa6e60fcf601dcf6341b9ebeb" + url: "https://pub.dev" + source: hosted + version: "0.8.12+23" + image_picker_for_web: + dependency: transitive + description: + name: image_picker_for_web + sha256: "717eb042ab08c40767684327be06a5d8dbb341fe791d514e4b92c7bbe1b7bb83" + url: "https://pub.dev" + source: hosted + version: "3.0.6" + image_picker_ios: + dependency: transitive + description: + name: image_picker_ios + sha256: "05da758e67bc7839e886b3959848aa6b44ff123ab4b28f67891008afe8ef9100" + url: "https://pub.dev" + source: hosted + version: "0.8.12+2" + image_picker_linux: + dependency: transitive + description: + name: image_picker_linux + sha256: "34a65f6740df08bbbeb0a1abd8e6d32107941fd4868f67a507b25601651022c9" + url: "https://pub.dev" + source: hosted + version: "0.2.1+2" + image_picker_macos: + dependency: transitive + description: + name: image_picker_macos + sha256: "1b90ebbd9dcf98fb6c1d01427e49a55bd96b5d67b8c67cf955d60a5de74207c1" + url: "https://pub.dev" + source: hosted + version: "0.2.1+2" + image_picker_platform_interface: + dependency: transitive + description: + name: image_picker_platform_interface + sha256: "886d57f0be73c4b140004e78b9f28a8914a09e50c2d816bdd0520051a71236a0" + url: "https://pub.dev" + source: hosted + version: "2.10.1" + image_picker_windows: + dependency: transitive + description: + name: image_picker_windows + sha256: "6ad07afc4eb1bc25f3a01084d28520496c4a3bb0cb13685435838167c9dcedeb" + url: "https://pub.dev" + source: hosted + version: "0.2.1+1" js: dependency: transitive description: @@ -416,6 +528,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.16.0" + mime: + dependency: transitive + description: + name: mime + sha256: "41a20518f0cb1256669420fdba0cd90d21561e560ac240f26ef8322e45bb7ed6" + url: "https://pub.dev" + source: hosted + version: "2.0.0" package_config: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index d867a8a..c1a488b 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -44,6 +44,7 @@ dependencies: kakao_flutter_sdk_user: ^1.9.7+3 flutter_dotenv: ^5.2.1 screen_protector: ^1.4.2+1 + image_picker: ^1.1.2 dev_dependencies: flutter_test: From 93a42b0a22cb795de95537a67eb6efce67a6d4d3 Mon Sep 17 00:00:00 2001 From: kkosang Date: Sat, 26 Apr 2025 00:50:49 +0900 Subject: [PATCH 2/5] =?UTF-8?q?feat:=20=ED=94=84=EB=A1=9C=ED=95=84=20?= =?UTF-8?q?=EC=9D=B4=EB=AF=B8=EC=A7=80=20=EC=9C=84=EC=A0=AF=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ios/Runner.xcodeproj/project.pbxproj | 5 ++ ios/Runner/Runner.entitlements | 5 ++ .../pages/profile_image/providers.dart | 11 ++++ .../widgets/profile_image_add_button.dart | 46 ++++++++++++++++ .../widgets/profile_image_preview.dart | 53 +++++++++++++++++++ 5 files changed, 120 insertions(+) create mode 100644 ios/Runner/Runner.entitlements create mode 100644 lib/sign_up/presentation/pages/profile_image/providers.dart create mode 100644 lib/sign_up/presentation/pages/profile_image/widgets/profile_image_add_button.dart create mode 100644 lib/sign_up/presentation/pages/profile_image/widgets/profile_image_preview.dart diff --git a/ios/Runner.xcodeproj/project.pbxproj b/ios/Runner.xcodeproj/project.pbxproj index d7b0228..ba9988b 100644 --- a/ios/Runner.xcodeproj/project.pbxproj +++ b/ios/Runner.xcodeproj/project.pbxproj @@ -65,6 +65,7 @@ B955AE8AC425CE69815F5900 /* Pods_RunnerTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_RunnerTests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; C7F447F3DE684CF75971C579 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; }; E1FBF0C02DAE7C460017C51F /* GoogleService-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "GoogleService-Info.plist"; sourceTree = ""; }; + E1FBF0C22DBBDA7A0017C51F /* Runner.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Runner.entitlements; sourceTree = ""; }; E6228E8708160B7145026049 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; E771DCC6EFA21C1573E7EC1E /* Pods-RunnerTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.debug.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.debug.xcconfig"; sourceTree = ""; }; /* End PBXFileReference section */ @@ -145,6 +146,7 @@ 97C146F01CF9000F007C117D /* Runner */ = { isa = PBXGroup; children = ( + E1FBF0C22DBBDA7A0017C51F /* Runner.entitlements */, E1FBF0C02DAE7C460017C51F /* GoogleService-Info.plist */, 97C146FA1CF9000F007C117D /* Main.storyboard */, 97C146FD1CF9000F007C117D /* Assets.xcassets */, @@ -473,6 +475,7 @@ buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; + CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements; CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; @@ -660,6 +663,7 @@ buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; + CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements; CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; @@ -687,6 +691,7 @@ buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; + CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements; CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; diff --git a/ios/Runner/Runner.entitlements b/ios/Runner/Runner.entitlements new file mode 100644 index 0000000..0c67376 --- /dev/null +++ b/ios/Runner/Runner.entitlements @@ -0,0 +1,5 @@ + + + + + diff --git a/lib/sign_up/presentation/pages/profile_image/providers.dart b/lib/sign_up/presentation/pages/profile_image/providers.dart new file mode 100644 index 0000000..43cca1e --- /dev/null +++ b/lib/sign_up/presentation/pages/profile_image/providers.dart @@ -0,0 +1,11 @@ +import 'package:code_l/sign_up/presentation/pages/profile_image/profile_image_viewmodel.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:image_picker/image_picker.dart'; + +final profileImagesProvider = StateNotifierProvider>( + (ref) => ProfileImageViewModel(), +); + +final faceImagesProvider = StateNotifierProvider>( + (ref) => ProfileImageViewModel(), +); diff --git a/lib/sign_up/presentation/pages/profile_image/widgets/profile_image_add_button.dart b/lib/sign_up/presentation/pages/profile_image/widgets/profile_image_add_button.dart new file mode 100644 index 0000000..e209909 --- /dev/null +++ b/lib/sign_up/presentation/pages/profile_image/widgets/profile_image_add_button.dart @@ -0,0 +1,46 @@ +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; + +import '../../../../../core/utills/design/app_colors.dart'; + +class ProfileImageAddButton extends StatelessWidget { + final VoidCallback onTap; + + const ProfileImageAddButton({super.key, required this.onTap}); + + @override + Widget build(BuildContext context) { + return GestureDetector( + onTap: onTap, + child: Stack( + clipBehavior: Clip.none, + children: [ + Container( + width: 64, + height: 64, + decoration: BoxDecoration( + color: AppColors.grey100, + borderRadius: BorderRadius.circular(24), + ), + child: const Center( + child: Icon(Icons.add, size: 16, color: AppColors.grey300), + ), + ), + Positioned( + bottom: 0, + right: 0, + child: Container( + width: 24, + height: 24, + decoration: const BoxDecoration( + color: AppColors.grey900, + shape: BoxShape.circle, + ), + child: const Icon(Icons.camera_alt, color: Colors.white, size: 12), + ), + ), + ], + ), + ); + } +} diff --git a/lib/sign_up/presentation/pages/profile_image/widgets/profile_image_preview.dart b/lib/sign_up/presentation/pages/profile_image/widgets/profile_image_preview.dart new file mode 100644 index 0000000..eccc1b4 --- /dev/null +++ b/lib/sign_up/presentation/pages/profile_image/widgets/profile_image_preview.dart @@ -0,0 +1,53 @@ + +import 'dart:io'; + +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:image_picker/image_picker.dart'; + +import '../../../../../core/utills/design/app_colors.dart'; + +class ProfileImagePreview extends StatelessWidget { + final XFile file; + final VoidCallback onDelete; + + const ProfileImagePreview({ + super.key, + required this.file, + required this.onDelete, + }); + + @override + Widget build(BuildContext context) { + return Stack( + clipBehavior: Clip.none, + children: [ + ClipRRect( + borderRadius: BorderRadius.circular(24), + child: Image.file( + File(file.path), + width: 64, + height: 64, + fit: BoxFit.cover, + ), + ), + Positioned( + bottom: 0, + right: 0, + child: GestureDetector( + onTap: onDelete, + child: Container( + width: 24, + height: 24, + decoration: const BoxDecoration( + shape: BoxShape.circle, + color: AppColors.grey900, + ), + child: const Icon(Icons.close, size: 12, color: Colors.white), + ), + ), + ), + ], + ); + } +} From 5f34ee12c19f5e6702c3a9748a58f7d666a6a523 Mon Sep 17 00:00:00 2001 From: kkosang Date: Sat, 26 Apr 2025 00:51:13 +0900 Subject: [PATCH 3/5] =?UTF-8?q?feat:=20=ED=94=84=EB=A1=9C=ED=95=84=20?= =?UTF-8?q?=EC=9D=B4=EB=AF=B8=EC=A7=80=20=ED=8E=98=EC=9D=B4=EC=A7=80=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../profile_image/profile_image_page.dart | 81 +++++++++++++++++++ .../profile_image_viewmodel.dart | 21 +++++ 2 files changed, 102 insertions(+) create mode 100644 lib/sign_up/presentation/pages/profile_image/profile_image_page.dart create mode 100644 lib/sign_up/presentation/pages/profile_image/profile_image_viewmodel.dart diff --git a/lib/sign_up/presentation/pages/profile_image/profile_image_page.dart b/lib/sign_up/presentation/pages/profile_image/profile_image_page.dart new file mode 100644 index 0000000..fbe1cc0 --- /dev/null +++ b/lib/sign_up/presentation/pages/profile_image/profile_image_page.dart @@ -0,0 +1,81 @@ +import 'package:code_l/sign_up/presentation/pages/profile_image/profile_face_image_page.dart'; +import 'package:code_l/sign_up/presentation/pages/profile_image/providers.dart'; +import 'package:code_l/sign_up/presentation/pages/profile_image/widgets/profile_image_add_button.dart'; +import 'package:code_l/sign_up/presentation/pages/profile_image/widgets/profile_image_preview.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; + +import '../../../../core/utills/design/app_colors.dart'; +import '../../../../core/utills/design/app_gaps.dart'; +import '../../../../core/utills/design/app_typography.dart'; +import '../../widgets/sign_up_app_bar.dart'; +import '../../widgets/sign_up_confirm_button.dart'; + +class ProfileImagePage extends ConsumerWidget { + const ProfileImagePage({super.key}); + + @override + Widget build(BuildContext context, WidgetRef ref) { + final images = ref.watch(profileImagesProvider); + final viewModel = ref.read(profileImagesProvider.notifier); + final screenHeight = MediaQuery.of(context).size.height; + + return Scaffold( + appBar: const SignUpAppBar(), + bottomNavigationBar: Padding( + padding: const EdgeInsets.symmetric(horizontal: AppGaps.gap20,vertical: 34), + child: ConfirmButton( + enabled: images.isNotEmpty, + onPressed: () { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => const ProfileFaceImagePage(), + ), + ); + }, + ), + ), + body: SafeArea( + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: AppGaps.gap20), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + SizedBox(height: screenHeight * 0.05), + + Text("프로필 사진을\n등록해주세요", style: AppTypography.header1), + const SizedBox(height: AppGaps.gap12), + Text( + "나를 표현할 수 있는 사진을\n최소 1~최대 3장 등록해주세요", + style: AppTypography.body2.copyWith(color: AppColors.grey600), + ), + const SizedBox(height: AppGaps.gap40), + + Text("사진 첨부 ${images.length} / 3", + style: AppTypography.subtitle3.copyWith(color: AppColors.grey900)), + const SizedBox(height: 10), + + Row( + children: [ + Padding( + padding: const EdgeInsets.only(right: 12), + child: ProfileImageAddButton(onTap: () => viewModel.pickImage()), + ), + ...images + .map((file) => Padding( + padding: const EdgeInsets.only(right: 12), + child: ProfileImagePreview( + file: file, + onDelete: () => viewModel.removeImage(file), + ) + )), + ], + ), + ], + ), + ), + ), + ); + } +} diff --git a/lib/sign_up/presentation/pages/profile_image/profile_image_viewmodel.dart b/lib/sign_up/presentation/pages/profile_image/profile_image_viewmodel.dart new file mode 100644 index 0000000..e980cd3 --- /dev/null +++ b/lib/sign_up/presentation/pages/profile_image/profile_image_viewmodel.dart @@ -0,0 +1,21 @@ +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:image_picker/image_picker.dart'; + +class ProfileImageViewModel extends StateNotifier> { + ProfileImageViewModel() : super([]); + + final _picker = ImagePicker(); + + Future pickImage() async { + final pickedList = await _picker.pickMultiImage(); + if (pickedList.isNotEmpty) { + final maxAllowed = 3 - state.length; + final limited = pickedList.take(maxAllowed).toList(); + state = [...state, ...limited]; + } + } + + void removeImage(XFile file) { + state = [...state]..remove(file); + } +} From 86e9ebef8ae6a6d7af0a16e6e76e83c0fe44fe9d Mon Sep 17 00:00:00 2001 From: kkosang Date: Sat, 26 Apr 2025 00:51:22 +0900 Subject: [PATCH 4/5] =?UTF-8?q?feat:=20=EC=96=BC=EA=B5=B4=20=EC=9D=B4?= =?UTF-8?q?=EB=AF=B8=EC=A7=80=20=EB=93=B1=EB=A1=9D=20=ED=8E=98=EC=9D=B4?= =?UTF-8?q?=EC=A7=80=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../profile_face_image_page.dart | 75 +++++++++++++++++++ 1 file changed, 75 insertions(+) create mode 100644 lib/sign_up/presentation/pages/profile_image/profile_face_image_page.dart diff --git a/lib/sign_up/presentation/pages/profile_image/profile_face_image_page.dart b/lib/sign_up/presentation/pages/profile_image/profile_face_image_page.dart new file mode 100644 index 0000000..42f7f1b --- /dev/null +++ b/lib/sign_up/presentation/pages/profile_image/profile_face_image_page.dart @@ -0,0 +1,75 @@ +import 'package:code_l/sign_up/presentation/pages/profile_image/providers.dart'; +import 'package:code_l/sign_up/presentation/pages/profile_image/widgets/profile_image_add_button.dart'; +import 'package:code_l/sign_up/presentation/pages/profile_image/widgets/profile_image_preview.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; + +import '../../../../core/utills/design/app_colors.dart'; +import '../../../../core/utills/design/app_gaps.dart'; +import '../../../../core/utills/design/app_typography.dart'; +import '../../widgets/sign_up_app_bar.dart'; +import '../../widgets/sign_up_confirm_button.dart'; + +class ProfileFaceImagePage extends ConsumerWidget { + const ProfileFaceImagePage({super.key}); + + @override + Widget build(BuildContext context, WidgetRef ref) { + final images = ref.watch(faceImagesProvider); + final viewModel = ref.read(faceImagesProvider.notifier); + final screenHeight = MediaQuery.of(context).size.height; + + return Scaffold( + appBar: const SignUpAppBar(), + bottomNavigationBar: Padding( + padding: const EdgeInsets.symmetric(horizontal: AppGaps.gap20,vertical: 34), + child: ConfirmButton( + enabled: images.length == 3, + onPressed: () { + // TODO: 업로드 후 다음 페이지 이동 + }, + ), + ), + body: SafeArea( + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: AppGaps.gap20), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + SizedBox(height: screenHeight * 0.05), + + Text("페이스 인증 사진을\n등록해주세요", style: AppTypography.header1), + const SizedBox(height: AppGaps.gap12), + Text( + "신뢰있는 매칭 위한\n얼굴 인증 사진 3장을 올려주세요", + style: AppTypography.body2.copyWith(color: AppColors.grey600), + ), + const SizedBox(height: AppGaps.gap40), + + Text("사진 첨부 ${images.length} / 3", + style: AppTypography.subtitle3.copyWith(color: AppColors.grey900)), + const SizedBox(height: 10), + + Row( + children: [ + Padding( + padding: const EdgeInsets.only(right: 12), + child: ProfileImageAddButton(onTap: () => viewModel.pickImage()), + ), + ...images + .map((file) => Padding( + padding: const EdgeInsets.only(right: 12), + child: ProfileImagePreview( + file: file, + onDelete: () => viewModel.removeImage(file), + ) + )), + ], + ), + ], + ), + ), + ), + ); + } +} From d067775fb1c3b26ddb645d5d058c46a856c5cb86 Mon Sep 17 00:00:00 2001 From: kkosang Date: Sat, 26 Apr 2025 00:54:42 +0900 Subject: [PATCH 5/5] chore: dart format --- .../remote/login_remote_datasource.dart | 4 +- .../pages/login/login_viewmodel.dart | 17 ++-- .../terms_and_condition_page.dart | 28 +++--- .../pages/woman/woman_verification_Page.dart | 14 +-- .../pages/code_job/code_job_page.dart | 75 +++++++------- .../code_lifestyle_drink_page.dart | 18 ++-- .../code_lifestyle_smoke_page.dart | 18 ++-- .../pages/profile_area/profile_area_page.dart | 98 ++++++++++--------- .../profile_face_image_page.dart | 26 +++-- .../profile_image/profile_image_page.dart | 34 ++++--- .../pages/profile_image/providers.dart | 10 +- .../widgets/profile_image_add_button.dart | 6 +- .../widgets/profile_image_preview.dart | 1 - .../profile_intereset_page.dart | 14 +-- .../pages/profile_mbti/profile_mbti_page.dart | 80 ++++++++------- .../pages/profile_mbti/providers.dart | 4 +- 16 files changed, 248 insertions(+), 199 deletions(-) diff --git a/lib/auth/data/datasources/remote/login_remote_datasource.dart b/lib/auth/data/datasources/remote/login_remote_datasource.dart index c1deaf0..cd210f6 100644 --- a/lib/auth/data/datasources/remote/login_remote_datasource.dart +++ b/lib/auth/data/datasources/remote/login_remote_datasource.dart @@ -15,8 +15,8 @@ class LoginRemoteDataSource { } Future loginWithApple() async { - final AuthorizationCredentialAppleID credential = - await SignInWithApple.getAppleIDCredential( + final AuthorizationCredentialAppleID + credential = await SignInWithApple.getAppleIDCredential( scopes: [ AppleIDAuthorizationScopes.email, AppleIDAuthorizationScopes.fullName, diff --git a/lib/auth/presentation/pages/login/login_viewmodel.dart b/lib/auth/presentation/pages/login/login_viewmodel.dart index 4a33a4a..4ca3fa0 100644 --- a/lib/auth/presentation/pages/login/login_viewmodel.dart +++ b/lib/auth/presentation/pages/login/login_viewmodel.dart @@ -16,9 +16,10 @@ class LoginViewModel extends ChangeNotifier { try { bool installed = await isKakaoTalkInstalled(); - OAuthToken token = installed - ? await UserApi.instance.loginWithKakaoTalk() - : await UserApi.instance.loginWithKakaoAccount(); + OAuthToken token = + installed + ? await UserApi.instance.loginWithKakaoTalk() + : await UserApi.instance.loginWithKakaoAccount(); final user = await UserApi.instance.me(); @@ -44,8 +45,9 @@ class LoginViewModel extends ChangeNotifier { // 애플 인증 정보 가져오기 final credential = useCase.callAppleLogin(LoginType.apple); // authorizationCode와 identityToken 확인 - final authorizationCode = - credential.then((value) => value.authorizationCode); + final authorizationCode = credential.then( + (value) => value.authorizationCode, + ); final identityToken = credential.then((value) => value.identityToken); if (authorizationCode == null || identityToken == null) { @@ -56,8 +58,9 @@ class LoginViewModel extends ChangeNotifier { await loginOauth(LoginType.apple, identityToken.toString()); log( - name: 'LoginViewModel::loginWithApple', - 'success: ${identityToken.toString()}'); + name: 'LoginViewModel::loginWithApple', + 'success: ${identityToken.toString()}', + ); } catch (e) { log(name: 'LoginViewModel::loginWithApple', 'error: $e'); } diff --git a/lib/auth/presentation/pages/terms_and_conditions/terms_and_condition_page.dart b/lib/auth/presentation/pages/terms_and_conditions/terms_and_condition_page.dart index 87332b0..4c8c842 100644 --- a/lib/auth/presentation/pages/terms_and_conditions/terms_and_condition_page.dart +++ b/lib/auth/presentation/pages/terms_and_conditions/terms_and_condition_page.dart @@ -73,9 +73,10 @@ class TermsAndConditionPage extends ConsumerWidget { Text( "모두 동의합니다.", style: AppTypography.subtitle2.copyWith( - color: viewmodel.checkState[0] - ? AppColors.grey900 - : AppColors.grey500, + color: + viewmodel.checkState[0] + ? AppColors.grey900 + : AppColors.grey500, ), ), IconButton( @@ -83,9 +84,10 @@ class TermsAndConditionPage extends ConsumerWidget { iconSize: 36, icon: Icon( Icons.check_circle_outline, - color: viewmodel.checkState[0] - ? AppColors.grey900 - : AppColors.grey500, + color: + viewmodel.checkState[0] + ? AppColors.grey900 + : AppColors.grey500, ), ), ], @@ -102,9 +104,10 @@ class TermsAndConditionPage extends ConsumerWidget { getLabel(i), style: AppTypography.body2.copyWith( decoration: TextDecoration.underline, - color: viewmodel.checkState[i] - ? AppColors.grey900 - : AppColors.grey500, + color: + viewmodel.checkState[i] + ? AppColors.grey900 + : AppColors.grey500, ), ), ), @@ -113,9 +116,10 @@ class TermsAndConditionPage extends ConsumerWidget { iconSize: 24, icon: Icon( Icons.check, - color: viewmodel.checkState[i] - ? AppColors.grey900 - : AppColors.grey500, + color: + viewmodel.checkState[i] + ? AppColors.grey900 + : AppColors.grey500, ), ), ], diff --git a/lib/auth/presentation/pages/woman/woman_verification_Page.dart b/lib/auth/presentation/pages/woman/woman_verification_Page.dart index 44cf916..9b45753 100644 --- a/lib/auth/presentation/pages/woman/woman_verification_Page.dart +++ b/lib/auth/presentation/pages/woman/woman_verification_Page.dart @@ -130,9 +130,10 @@ class WomanVerificationPage extends ConsumerWidget { Text( "위 안내사항을 모두 확인하였습니다.", style: AppTypography.subtitle2.copyWith( - color: viewModel.isChecked - ? AppColors.grey800 - : AppColors.grey400, + color: + viewModel.isChecked + ? AppColors.grey800 + : AppColors.grey400, ), ), IconButton( @@ -141,9 +142,10 @@ class WomanVerificationPage extends ConsumerWidget { }, icon: Icon( Icons.check_circle_outline, - color: viewModel.isChecked - ? AppColors.grey800 - : AppColors.grey400, + color: + viewModel.isChecked + ? AppColors.grey800 + : AppColors.grey400, ), ), ], diff --git a/lib/sign_up/presentation/pages/code_job/code_job_page.dart b/lib/sign_up/presentation/pages/code_job/code_job_page.dart index 7fd1d29..fcfa1b4 100644 --- a/lib/sign_up/presentation/pages/code_job/code_job_page.dart +++ b/lib/sign_up/presentation/pages/code_job/code_job_page.dart @@ -63,44 +63,47 @@ class _JobSelectionPageState extends ConsumerState { mainAxisSpacing: 12, crossAxisSpacing: 12, childAspectRatio: 1.1, - children: jobList.map((job) { - final isSelected = selectedJob == job['label']; - return GestureDetector( - onTap: () { - setState(() => selectedJob = job['label']); - }, - child: Container( - decoration: BoxDecoration( - color: isSelected - ? AppColors.primaryLight - : AppColors.grey100, - border: Border.all( - color: isSelected - ? AppColors.primary - : AppColors.grey100, - width: 1.5, - ), - borderRadius: BorderRadius.circular(8), - ), - padding: EdgeInsets.symmetric(vertical: 16), - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Image.asset( - job['image']!, - width: 16, - height: 22, + children: + jobList.map((job) { + final isSelected = selectedJob == job['label']; + return GestureDetector( + onTap: () { + setState(() => selectedJob = job['label']); + }, + child: Container( + decoration: BoxDecoration( + color: + isSelected + ? AppColors.primaryLight + : AppColors.grey100, + border: Border.all( + color: + isSelected + ? AppColors.primary + : AppColors.grey100, + width: 1.5, + ), + borderRadius: BorderRadius.circular(8), ), - SizedBox(height: AppGaps.gap4), - Text( - job['label'] ?? '', - style: AppTypography.body2, + padding: EdgeInsets.symmetric(vertical: 16), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Image.asset( + job['image']!, + width: 16, + height: 22, + ), + SizedBox(height: AppGaps.gap4), + Text( + job['label'] ?? '', + style: AppTypography.body2, + ), + ], ), - ], - ), - ), - ); - }).toList(), + ), + ); + }).toList(), ), ), ], diff --git a/lib/sign_up/presentation/pages/code_lifestyle/code_lifestyle_drink_page.dart b/lib/sign_up/presentation/pages/code_lifestyle/code_lifestyle_drink_page.dart index 13b66d8..29680e6 100644 --- a/lib/sign_up/presentation/pages/code_lifestyle/code_lifestyle_drink_page.dart +++ b/lib/sign_up/presentation/pages/code_lifestyle/code_lifestyle_drink_page.dart @@ -55,8 +55,8 @@ class _CodeLifestyleDrinkPageState extends State { Expanded( child: ListView.separated( itemCount: drinkOptions.length, - separatorBuilder: (_, __) => - const SizedBox(height: AppGaps.gap16), + separatorBuilder: + (_, __) => const SizedBox(height: AppGaps.gap16), itemBuilder: (context, index) { final item = drinkOptions[index]; final isSelected = selectedIndex == index; @@ -74,13 +74,15 @@ class _CodeLifestyleDrinkPageState extends State { ), decoration: BoxDecoration( border: Border.all( - color: isSelected - ? AppColors.primary - : AppColors.grey400, + color: + isSelected + ? AppColors.primary + : AppColors.grey400, ), - color: isSelected - ? AppColors.primaryLight - : AppColors.white, + color: + isSelected + ? AppColors.primaryLight + : AppColors.white, ), child: Row( children: [ diff --git a/lib/sign_up/presentation/pages/code_lifestyle/code_lifestyle_smoke_page.dart b/lib/sign_up/presentation/pages/code_lifestyle/code_lifestyle_smoke_page.dart index 5f9a069..2ed14aa 100644 --- a/lib/sign_up/presentation/pages/code_lifestyle/code_lifestyle_smoke_page.dart +++ b/lib/sign_up/presentation/pages/code_lifestyle/code_lifestyle_smoke_page.dart @@ -63,8 +63,8 @@ class _CodeLifestyleDrinkPageState extends State { Expanded( child: ListView.separated( itemCount: drinkOptions.length, - separatorBuilder: (_, __) => - const SizedBox(height: AppGaps.gap16), + separatorBuilder: + (_, __) => const SizedBox(height: AppGaps.gap16), itemBuilder: (context, index) { final item = drinkOptions[index]; final isSelected = selectedIndex == index; @@ -82,13 +82,15 @@ class _CodeLifestyleDrinkPageState extends State { ), decoration: BoxDecoration( border: Border.all( - color: isSelected - ? AppColors.primary - : AppColors.grey400, + color: + isSelected + ? AppColors.primary + : AppColors.grey400, ), - color: isSelected - ? AppColors.primaryLight - : AppColors.white, + color: + isSelected + ? AppColors.primaryLight + : AppColors.white, ), child: Row( children: [ diff --git a/lib/sign_up/presentation/pages/profile_area/profile_area_page.dart b/lib/sign_up/presentation/pages/profile_area/profile_area_page.dart index 43a082f..cc4556e 100644 --- a/lib/sign_up/presentation/pages/profile_area/profile_area_page.dart +++ b/lib/sign_up/presentation/pages/profile_area/profile_area_page.dart @@ -356,56 +356,58 @@ class _ProfileRegionPageState extends State { ), SizedBox(width: AppGaps.gap20), Expanded( - child: selectedMainRegionIndex == null - ? const SizedBox.shrink() - : ListView.builder( - itemCount: subRegions[ - mainRegions[selectedMainRegionIndex!]]! - .length, - itemBuilder: (context, index) { - final subRegionName = subRegions[mainRegions[ - selectedMainRegionIndex!]]![index]; - final isSelected = - selectedSubRegionIndex == index; - return GestureDetector( - onTap: () { - setState(() { - selectedSubRegionIndex = index; - }); - }, - child: Container( - padding: const EdgeInsets.symmetric( - vertical: 16, - horizontal: 8, - ), - decoration: BoxDecoration( - color: Colors.transparent, - borderRadius: BorderRadius.circular(8), - ), - child: Row( - mainAxisAlignment: - MainAxisAlignment.spaceBetween, - children: [ - Text( - subRegionName, - style: AppTypography.body1.copyWith( - color: isSelected - ? AppColors.primary - : AppColors.grey900, - ), - ), - if (isSelected) - const Icon( - Icons.check, - color: AppColors.primary, - size: 20, + child: + selectedMainRegionIndex == null + ? const SizedBox.shrink() + : ListView.builder( + itemCount: + subRegions[mainRegions[selectedMainRegionIndex!]]! + .length, + itemBuilder: (context, index) { + final subRegionName = + subRegions[mainRegions[selectedMainRegionIndex!]]![index]; + final isSelected = + selectedSubRegionIndex == index; + return GestureDetector( + onTap: () { + setState(() { + selectedSubRegionIndex = index; + }); + }, + child: Container( + padding: const EdgeInsets.symmetric( + vertical: 16, + horizontal: 8, + ), + decoration: BoxDecoration( + color: Colors.transparent, + borderRadius: BorderRadius.circular(8), + ), + child: Row( + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + children: [ + Text( + subRegionName, + style: AppTypography.body1.copyWith( + color: + isSelected + ? AppColors.primary + : AppColors.grey900, + ), ), - ], + if (isSelected) + const Icon( + Icons.check, + color: AppColors.primary, + size: 20, + ), + ], + ), ), - ), - ); - }, - ), + ); + }, + ), ), ], ), diff --git a/lib/sign_up/presentation/pages/profile_image/profile_face_image_page.dart b/lib/sign_up/presentation/pages/profile_image/profile_face_image_page.dart index 42f7f1b..d77cbe3 100644 --- a/lib/sign_up/presentation/pages/profile_image/profile_face_image_page.dart +++ b/lib/sign_up/presentation/pages/profile_image/profile_face_image_page.dart @@ -22,7 +22,10 @@ class ProfileFaceImagePage extends ConsumerWidget { return Scaffold( appBar: const SignUpAppBar(), bottomNavigationBar: Padding( - padding: const EdgeInsets.symmetric(horizontal: AppGaps.gap20,vertical: 34), + padding: const EdgeInsets.symmetric( + horizontal: AppGaps.gap20, + vertical: 34, + ), child: ConfirmButton( enabled: images.length == 3, onPressed: () { @@ -46,24 +49,31 @@ class ProfileFaceImagePage extends ConsumerWidget { ), const SizedBox(height: AppGaps.gap40), - Text("사진 첨부 ${images.length} / 3", - style: AppTypography.subtitle3.copyWith(color: AppColors.grey900)), + Text( + "사진 첨부 ${images.length} / 3", + style: AppTypography.subtitle3.copyWith( + color: AppColors.grey900, + ), + ), const SizedBox(height: 10), Row( children: [ Padding( padding: const EdgeInsets.only(right: 12), - child: ProfileImageAddButton(onTap: () => viewModel.pickImage()), + child: ProfileImageAddButton( + onTap: () => viewModel.pickImage(), + ), ), - ...images - .map((file) => Padding( + ...images.map( + (file) => Padding( padding: const EdgeInsets.only(right: 12), child: ProfileImagePreview( file: file, onDelete: () => viewModel.removeImage(file), - ) - )), + ), + ), + ), ], ), ], diff --git a/lib/sign_up/presentation/pages/profile_image/profile_image_page.dart b/lib/sign_up/presentation/pages/profile_image/profile_image_page.dart index fbe1cc0..5547c8e 100644 --- a/lib/sign_up/presentation/pages/profile_image/profile_image_page.dart +++ b/lib/sign_up/presentation/pages/profile_image/profile_image_page.dart @@ -23,7 +23,10 @@ class ProfileImagePage extends ConsumerWidget { return Scaffold( appBar: const SignUpAppBar(), bottomNavigationBar: Padding( - padding: const EdgeInsets.symmetric(horizontal: AppGaps.gap20,vertical: 34), + padding: const EdgeInsets.symmetric( + horizontal: AppGaps.gap20, + vertical: 34, + ), child: ConfirmButton( enabled: images.isNotEmpty, onPressed: () { @@ -52,24 +55,31 @@ class ProfileImagePage extends ConsumerWidget { ), const SizedBox(height: AppGaps.gap40), - Text("사진 첨부 ${images.length} / 3", - style: AppTypography.subtitle3.copyWith(color: AppColors.grey900)), + Text( + "사진 첨부 ${images.length} / 3", + style: AppTypography.subtitle3.copyWith( + color: AppColors.grey900, + ), + ), const SizedBox(height: 10), Row( children: [ Padding( padding: const EdgeInsets.only(right: 12), - child: ProfileImageAddButton(onTap: () => viewModel.pickImage()), + child: ProfileImageAddButton( + onTap: () => viewModel.pickImage(), + ), + ), + ...images.map( + (file) => Padding( + padding: const EdgeInsets.only(right: 12), + child: ProfileImagePreview( + file: file, + onDelete: () => viewModel.removeImage(file), + ), + ), ), - ...images - .map((file) => Padding( - padding: const EdgeInsets.only(right: 12), - child: ProfileImagePreview( - file: file, - onDelete: () => viewModel.removeImage(file), - ) - )), ], ), ], diff --git a/lib/sign_up/presentation/pages/profile_image/providers.dart b/lib/sign_up/presentation/pages/profile_image/providers.dart index 43cca1e..18fb03b 100644 --- a/lib/sign_up/presentation/pages/profile_image/providers.dart +++ b/lib/sign_up/presentation/pages/profile_image/providers.dart @@ -2,10 +2,12 @@ import 'package:code_l/sign_up/presentation/pages/profile_image/profile_image_vi import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:image_picker/image_picker.dart'; -final profileImagesProvider = StateNotifierProvider>( +final profileImagesProvider = + StateNotifierProvider>( (ref) => ProfileImageViewModel(), -); + ); -final faceImagesProvider = StateNotifierProvider>( +final faceImagesProvider = + StateNotifierProvider>( (ref) => ProfileImageViewModel(), -); + ); diff --git a/lib/sign_up/presentation/pages/profile_image/widgets/profile_image_add_button.dart b/lib/sign_up/presentation/pages/profile_image/widgets/profile_image_add_button.dart index e209909..0441b1a 100644 --- a/lib/sign_up/presentation/pages/profile_image/widgets/profile_image_add_button.dart +++ b/lib/sign_up/presentation/pages/profile_image/widgets/profile_image_add_button.dart @@ -36,7 +36,11 @@ class ProfileImageAddButton extends StatelessWidget { color: AppColors.grey900, shape: BoxShape.circle, ), - child: const Icon(Icons.camera_alt, color: Colors.white, size: 12), + child: const Icon( + Icons.camera_alt, + color: Colors.white, + size: 12, + ), ), ), ], diff --git a/lib/sign_up/presentation/pages/profile_image/widgets/profile_image_preview.dart b/lib/sign_up/presentation/pages/profile_image/widgets/profile_image_preview.dart index eccc1b4..fede688 100644 --- a/lib/sign_up/presentation/pages/profile_image/widgets/profile_image_preview.dart +++ b/lib/sign_up/presentation/pages/profile_image/widgets/profile_image_preview.dart @@ -1,4 +1,3 @@ - import 'dart:io'; import 'package:flutter/cupertino.dart'; diff --git a/lib/sign_up/presentation/pages/profile_interest/profile_intereset_page.dart b/lib/sign_up/presentation/pages/profile_interest/profile_intereset_page.dart index a7a3d42..99b0f5f 100644 --- a/lib/sign_up/presentation/pages/profile_interest/profile_intereset_page.dart +++ b/lib/sign_up/presentation/pages/profile_interest/profile_intereset_page.dart @@ -109,13 +109,15 @@ class _ProfileInterestPageState extends State { ), decoration: BoxDecoration( border: Border.all( - color: isSelected - ? AppColors.primary - : AppColors.grey400, + color: + isSelected + ? AppColors.primary + : AppColors.grey400, ), - color: isSelected - ? AppColors.primaryLight - : AppColors.white, + color: + isSelected + ? AppColors.primaryLight + : AppColors.white, borderRadius: BorderRadius.circular(100), ), child: Text( diff --git a/lib/sign_up/presentation/pages/profile_mbti/profile_mbti_page.dart b/lib/sign_up/presentation/pages/profile_mbti/profile_mbti_page.dart index a1342ca..3a4d2b4 100644 --- a/lib/sign_up/presentation/pages/profile_mbti/profile_mbti_page.dart +++ b/lib/sign_up/presentation/pages/profile_mbti/profile_mbti_page.dart @@ -57,50 +57,54 @@ class ProfileMBTIPage extends ConsumerWidget { return Padding( padding: const EdgeInsets.only(bottom: AppGaps.gap20), child: Row( - children: group.map((option) { - final isSelected = viewModel.isSelected( - groupIndex, - option, - ); - return Expanded( - child: Padding( - padding: const EdgeInsets.symmetric( - horizontal: 6, - ), - child: GestureDetector( - onTap: () => viewModel.select( - groupIndex, - option, - ), - child: Container( + children: + group.map((option) { + final isSelected = viewModel.isSelected( + groupIndex, + option, + ); + return Expanded( + child: Padding( padding: const EdgeInsets.symmetric( - horizontal: 74, - vertical: 34, - ), - decoration: BoxDecoration( - color: isSelected - ? AppColors.primaryLight - : AppColors.grey100, - border: Border.all( - color: isSelected - ? AppColors.primary - : AppColors.grey100, - ), - borderRadius: BorderRadius.circular(8), + horizontal: 6, ), - child: Center( - child: Text( - option, - style: AppTypography.body1.copyWith( - color: AppColors.grey900, + child: GestureDetector( + onTap: + () => viewModel.select( + groupIndex, + option, + ), + child: Container( + padding: const EdgeInsets.symmetric( + horizontal: 74, + vertical: 34, + ), + decoration: BoxDecoration( + color: + isSelected + ? AppColors.primaryLight + : AppColors.grey100, + border: Border.all( + color: + isSelected + ? AppColors.primary + : AppColors.grey100, + ), + borderRadius: BorderRadius.circular(8), + ), + child: Center( + child: Text( + option, + style: AppTypography.body1.copyWith( + color: AppColors.grey900, + ), + ), ), ), ), ), - ), - ), - ); - }).toList(), + ); + }).toList(), ), ); }, diff --git a/lib/sign_up/presentation/pages/profile_mbti/providers.dart b/lib/sign_up/presentation/pages/profile_mbti/providers.dart index 9159df2..90f47cd 100644 --- a/lib/sign_up/presentation/pages/profile_mbti/providers.dart +++ b/lib/sign_up/presentation/pages/profile_mbti/providers.dart @@ -5,5 +5,5 @@ import '../../../domain/model/profile_mbti/profile_mbti_state.dart'; final profileMBTIProvider = StateNotifierProvider( - (ref) => ProfileMBTIViewModel(), -); + (ref) => ProfileMBTIViewModel(), + );