diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md
index 001df22..2ebf3a6 100644
--- a/.github/PULL_REQUEST_TEMPLATE.md
+++ b/.github/PULL_REQUEST_TEMPLATE.md
@@ -13,3 +13,5 @@ close #
## ๐ฌ๋ฆฌ๋ทฐ ์๊ตฌ์ฌํญ
+## ๋ค์ ์์
+
diff --git a/android/app/build.gradle.kts b/android/app/build.gradle.kts
index a0a7822..f958fb1 100644
--- a/android/app/build.gradle.kts
+++ b/android/app/build.gradle.kts
@@ -4,7 +4,6 @@ plugins {
id("com.android.application")
id("kotlin-android")
id("com.google.gms.google-services")
- // The Flutter Gradle Plugin must be applied after the Android and Kotlin Gradle plugins.
id("dev.flutter.flutter-gradle-plugin")
}
@@ -53,3 +52,4 @@ android {
flutter {
source = "../.."
}
+
diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml
index 0079ea1..70d1b84 100644
--- a/android/app/src/main/AndroidManifest.xml
+++ b/android/app/src/main/AndroidManifest.xml
@@ -7,6 +7,18 @@
android:label="code_l"
android:name="${applicationName}"
android:icon="@mipmap/ic_launcher">
+
+
+
+
+
+
+
+
+
+
("clean") {
delete(rootProject.layout.buildDirectory)
}
+
+buildscript {
+ repositories {
+ google()
+ mavenCentral()
+ }
+ dependencies {
+ classpath("com.google.gms:google-services:4.3.15") // โ
๊ดํธ ์ฃผ์
+ }
+}
+
diff --git a/firebase.json b/firebase.json
new file mode 100644
index 0000000..4fdea37
--- /dev/null
+++ b/firebase.json
@@ -0,0 +1 @@
+{"flutter":{"platforms":{"android":{"default":{"projectId":"code-l-b109b","appId":"1:971644319685:android:34198e5a313e5294b53dac","fileOutput":"android/app/google-services.json"}},"ios":{"default":{"projectId":"code-l-b109b","appId":"1:971644319685:ios:bde2639222525193b53dac","uploadDebugSymbols":false,"fileOutput":"ios/Runner/GoogleService-Info.plist"}},"dart":{"lib/firebase_options.dart":{"projectId":"code-l-b109b","configurations":{"android":"1:971644319685:android:34198e5a313e5294b53dac","ios":"1:971644319685:ios:bde2639222525193b53dac"}}}}}}
\ No newline at end of file
diff --git a/ios/Podfile.lock b/ios/Podfile.lock
new file mode 100644
index 0000000..dfc16f7
--- /dev/null
+++ b/ios/Podfile.lock
@@ -0,0 +1,136 @@
+PODS:
+ - Firebase/Auth (11.10.0):
+ - Firebase/CoreOnly
+ - FirebaseAuth (~> 11.10.0)
+ - Firebase/CoreOnly (11.10.0):
+ - FirebaseCore (~> 11.10.0)
+ - firebase_auth (5.5.2):
+ - Firebase/Auth (= 11.10.0)
+ - firebase_core
+ - Flutter
+ - firebase_core (3.13.0):
+ - Firebase/CoreOnly (= 11.10.0)
+ - Flutter
+ - FirebaseAppCheckInterop (11.11.0)
+ - FirebaseAuth (11.10.0):
+ - FirebaseAppCheckInterop (~> 11.0)
+ - FirebaseAuthInterop (~> 11.0)
+ - FirebaseCore (~> 11.10.0)
+ - FirebaseCoreExtension (~> 11.10.0)
+ - GoogleUtilities/AppDelegateSwizzler (~> 8.0)
+ - GoogleUtilities/Environment (~> 8.0)
+ - GTMSessionFetcher/Core (< 5.0, >= 3.4)
+ - RecaptchaInterop (~> 101.0)
+ - FirebaseAuthInterop (11.11.0)
+ - FirebaseCore (11.10.0):
+ - FirebaseCoreInternal (~> 11.10.0)
+ - GoogleUtilities/Environment (~> 8.0)
+ - GoogleUtilities/Logger (~> 8.0)
+ - FirebaseCoreExtension (11.10.0):
+ - FirebaseCore (~> 11.10.0)
+ - FirebaseCoreInternal (11.10.0):
+ - "GoogleUtilities/NSData+zlib (~> 8.0)"
+ - Flutter (1.0.0)
+ - fluttertoast (0.0.2):
+ - Flutter
+ - GoogleUtilities/AppDelegateSwizzler (8.0.2):
+ - GoogleUtilities/Environment
+ - GoogleUtilities/Logger
+ - GoogleUtilities/Network
+ - GoogleUtilities/Privacy
+ - GoogleUtilities/Environment (8.0.2):
+ - GoogleUtilities/Privacy
+ - GoogleUtilities/Logger (8.0.2):
+ - GoogleUtilities/Environment
+ - GoogleUtilities/Privacy
+ - GoogleUtilities/Network (8.0.2):
+ - GoogleUtilities/Logger
+ - "GoogleUtilities/NSData+zlib"
+ - GoogleUtilities/Privacy
+ - GoogleUtilities/Reachability
+ - "GoogleUtilities/NSData+zlib (8.0.2)":
+ - GoogleUtilities/Privacy
+ - GoogleUtilities/Privacy (8.0.2)
+ - GoogleUtilities/Reachability (8.0.2):
+ - GoogleUtilities/Logger
+ - GoogleUtilities/Privacy
+ - GTMSessionFetcher/Core (4.4.0)
+ - kakao_flutter_sdk_common (1.9.7-3):
+ - Flutter
+ - RecaptchaInterop (101.0.0)
+ - screen_protector (1.2.1):
+ - Flutter
+ - ScreenProtectorKit (~> 1.3.1)
+ - ScreenProtectorKit (1.3.1)
+ - shared_preferences_foundation (0.0.1):
+ - Flutter
+ - FlutterMacOS
+ - sign_in_with_apple (0.0.1):
+ - Flutter
+
+DEPENDENCIES:
+ - firebase_auth (from `.symlinks/plugins/firebase_auth/ios`)
+ - firebase_core (from `.symlinks/plugins/firebase_core/ios`)
+ - Flutter (from `Flutter`)
+ - fluttertoast (from `.symlinks/plugins/fluttertoast/ios`)
+ - kakao_flutter_sdk_common (from `.symlinks/plugins/kakao_flutter_sdk_common/ios`)
+ - screen_protector (from `.symlinks/plugins/screen_protector/ios`)
+ - shared_preferences_foundation (from `.symlinks/plugins/shared_preferences_foundation/darwin`)
+ - sign_in_with_apple (from `.symlinks/plugins/sign_in_with_apple/ios`)
+
+SPEC REPOS:
+ trunk:
+ - Firebase
+ - FirebaseAppCheckInterop
+ - FirebaseAuth
+ - FirebaseAuthInterop
+ - FirebaseCore
+ - FirebaseCoreExtension
+ - FirebaseCoreInternal
+ - GoogleUtilities
+ - GTMSessionFetcher
+ - RecaptchaInterop
+ - ScreenProtectorKit
+
+EXTERNAL SOURCES:
+ firebase_auth:
+ :path: ".symlinks/plugins/firebase_auth/ios"
+ firebase_core:
+ :path: ".symlinks/plugins/firebase_core/ios"
+ Flutter:
+ :path: Flutter
+ fluttertoast:
+ :path: ".symlinks/plugins/fluttertoast/ios"
+ kakao_flutter_sdk_common:
+ :path: ".symlinks/plugins/kakao_flutter_sdk_common/ios"
+ screen_protector:
+ :path: ".symlinks/plugins/screen_protector/ios"
+ shared_preferences_foundation:
+ :path: ".symlinks/plugins/shared_preferences_foundation/darwin"
+ sign_in_with_apple:
+ :path: ".symlinks/plugins/sign_in_with_apple/ios"
+
+SPEC CHECKSUMS:
+ Firebase: 1fe1c0a7d9aaea32efe01fbea5f0ebd8d70e53a2
+ firebase_auth: ad485af7f854ba5f86634f81725b22b37f317883
+ firebase_core: 2d4534e7b489907dcede540c835b48981d890943
+ FirebaseAppCheckInterop: f23709c9ce92d810aa53ff4ce12ad3e666a3c7be
+ FirebaseAuth: c4146bdfdc87329f9962babd24dae89373f49a32
+ FirebaseAuthInterop: ac22ed402c2f4e3a8c63ebd3278af9a06073c1be
+ FirebaseCore: 8344daef5e2661eb004b177488d6f9f0f24251b7
+ FirebaseCoreExtension: 6f357679327f3614e995dc7cf3f2d600bdc774ac
+ FirebaseCoreInternal: ef4505d2afb1d0ebbc33162cb3795382904b5679
+ Flutter: e0871f40cf51350855a761d2e70bf5af5b9b5de7
+ fluttertoast: 2c67e14dce98bbdb200df9e1acf610d7a6264ea1
+ GoogleUtilities: 26a3abef001b6533cf678d3eb38fd3f614b7872d
+ GTMSessionFetcher: 75b671f9e551e4c49153d4c4f8659ef4f559b970
+ kakao_flutter_sdk_common: 600d55b532da0bd37268a529e1add49302477710
+ RecaptchaInterop: 11e0b637842dfb48308d242afc3f448062325aba
+ screen_protector: 3d90d44ac886b25335aebd93230b454aef45794a
+ ScreenProtectorKit: 83a6281b02c7a5902ee6eac4f5045f674e902ae4
+ shared_preferences_foundation: 9e1978ff2562383bd5676f64ec4e9aa8fa06a6f7
+ sign_in_with_apple: c5dcc141574c8c54d5ac99dd2163c0c72ad22418
+
+PODFILE CHECKSUM: f8c2dcdfb50bb67645580d28a6bf814fca30bdec
+
+COCOAPODS: 1.16.2
diff --git a/ios/Runner.xcodeproj/project.pbxproj b/ios/Runner.xcodeproj/project.pbxproj
index d7b0228..7ccd31d 100644
--- a/ios/Runner.xcodeproj/project.pbxproj
+++ b/ios/Runner.xcodeproj/project.pbxproj
@@ -62,6 +62,8 @@
97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; };
97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
A0C3D7BA37E297BF670F5764 /* Pods-RunnerTests.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.profile.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.profile.xcconfig"; sourceTree = ""; };
+ AFD21D852DB512DE00452D52 /* RunnerDebug.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = RunnerDebug.entitlements; sourceTree = ""; };
+ AFE368902DB7F7D10072E7EF /* Runner.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Runner.entitlements; sourceTree = ""; };
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 = ""; };
@@ -145,6 +147,8 @@
97C146F01CF9000F007C117D /* Runner */ = {
isa = PBXGroup;
children = (
+ AFE368902DB7F7D10072E7EF /* Runner.entitlements */,
+ AFD21D852DB512DE00452D52 /* RunnerDebug.entitlements */,
E1FBF0C02DAE7C460017C51F /* GoogleService-Info.plist */,
97C146FA1CF9000F007C117D /* Main.storyboard */,
97C146FD1CF9000F007C117D /* Assets.xcassets */,
@@ -473,6 +477,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 +665,7 @@
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
+ CODE_SIGN_ENTITLEMENTS = Runner/RunnerDebug.entitlements;
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
@@ -687,6 +693,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/GoogleService-Info.plist b/ios/Runner/GoogleService-Info.plist
new file mode 100644
index 0000000..f6353c7
--- /dev/null
+++ b/ios/Runner/GoogleService-Info.plist
@@ -0,0 +1,36 @@
+
+
+
+
+ CLIENT_ID
+ 971644319685-jo8kiqh779jhevlh53d3cbj3lrdavovf.apps.googleusercontent.com
+ REVERSED_CLIENT_ID
+ com.googleusercontent.apps.971644319685-jo8kiqh779jhevlh53d3cbj3lrdavovf
+ ANDROID_CLIENT_ID
+ 971644319685-vnlopiq93h2n0cukes3chrm8n51t2836.apps.googleusercontent.com
+ API_KEY
+ AIzaSyA6aPcY0Qv4eCO4Q_KLxF0KMDQ9M9wdZlw
+ GCM_SENDER_ID
+ 971644319685
+ PLIST_VERSION
+ 1
+ BUNDLE_ID
+ com.codel.codel
+ PROJECT_ID
+ code-l-b109b
+ STORAGE_BUCKET
+ code-l-b109b.firebasestorage.app
+ IS_ADS_ENABLED
+
+ IS_ANALYTICS_ENABLED
+
+ IS_APPINVITE_ENABLED
+
+ IS_GCM_ENABLED
+
+ IS_SIGNIN_ENABLED
+
+ GOOGLE_APP_ID
+ 1:971644319685:ios:bde2639222525193b53dac
+
+
\ No newline at end of file
diff --git a/ios/Runner/Info.plist b/ios/Runner/Info.plist
index b2fbcc6..f425cd0 100644
--- a/ios/Runner/Info.plist
+++ b/ios/Runner/Info.plist
@@ -2,15 +2,8 @@
-CFBundleURLTypes
-
-
- CFBundleURLSchemes
-
- kakaoe17acdc68adf7250d61dd15f8ee185c1
-
-
-
+ CADisableMinimumFrameDurationOnPhone
+
CFBundleDevelopmentRegion
$(DEVELOPMENT_LANGUAGE)
CFBundleDisplayName
@@ -29,10 +22,43 @@
$(FLUTTER_BUILD_NAME)
CFBundleSignature
????
+ CFBundleURLTypes
+
+
+ CFBundleURLSchemes
+
+ kakaoe17acdc68adf7250d61dd15f8ee185c1
+ app-1-971644319685-ios-bde2639222525193b53dac
+
+
+
+ CFBundleTypeRole
+ Editor
+ CFBundleURLSchemes
+
+ com.googleusercontent.apps.971644319685-jo8kiqh779jhevlh53d3cbj3lrdavovf
+
+
+
+ CFBundleTypeRole
+ Editor
+ CFBundleURLSchemes
+
+ app-1-971644319685-ios-bde2639222525193b53dac
+
+
+
+
CFBundleVersion
$(FLUTTER_BUILD_NUMBER)
LSRequiresIPhoneOS
+ UIApplicationSupportsIndirectInputEvents
+
+ UIBackgroundModes
+
+ remote-notification
+
UILaunchStoryboardName
LaunchScreen
UIMainStoryboardFile
@@ -50,9 +76,5 @@
UIInterfaceOrientationLandscapeLeft
UIInterfaceOrientationLandscapeRight
- CADisableMinimumFrameDurationOnPhone
-
- UIApplicationSupportsIndirectInputEvents
-
diff --git a/ios/Runner/Runner.entitlements b/ios/Runner/Runner.entitlements
new file mode 100644
index 0000000..a812db5
--- /dev/null
+++ b/ios/Runner/Runner.entitlements
@@ -0,0 +1,10 @@
+
+
+
+
+ com.apple.developer.applesignin
+
+ Default
+
+
+
diff --git a/ios/Runner/RunnerDebug.entitlements b/ios/Runner/RunnerDebug.entitlements
new file mode 100644
index 0000000..80b5221
--- /dev/null
+++ b/ios/Runner/RunnerDebug.entitlements
@@ -0,0 +1,12 @@
+
+
+
+
+ aps-environment
+ development
+ com.apple.developer.applesignin
+
+ Default
+
+
+
diff --git a/lib/auth/data/repositories/auth_repository_impl.dart b/lib/auth/data/repositories/auth_repository_impl.dart
new file mode 100644
index 0000000..dda74b5
--- /dev/null
+++ b/lib/auth/data/repositories/auth_repository_impl.dart
@@ -0,0 +1,54 @@
+import 'dart:developer';
+
+import 'package:firebase_auth/firebase_auth.dart';
+
+import '../../domain/repositories/auth_repository.dart';
+
+class AuthRepositoryImpl implements AuthRepository {
+ final FirebaseAuth _auth = FirebaseAuth.instance;
+
+ @override
+ Future verifyPhoneNumber(
+ String phoneNumber, Function(String) onCodeSent) async {
+ await _auth.verifyPhoneNumber(
+ phoneNumber: phoneNumber,
+ timeout: const Duration(seconds: 60),
+ verificationCompleted: (PhoneAuthCredential credential) async {
+ log(name: 'AuthRepositoryImpl : verifyPhoneNumber', 'ํธ๋ํฐ ์๋ ์ธ์ฆ ์๋ฃ');
+ await _auth.signInWithCredential(credential);
+ },
+ verificationFailed: (FirebaseAuthException e) {
+ log(
+ name: 'AuthRepositoryImpl : verifyPhoneNumber',
+ 'Phone verification failed: ${e.message}');
+ },
+ codeSent: (String verificationId, int? forceResendingToken) async {
+ log(name: 'AuthRepositoryImpl : verifyPhoneNumber', '์ธ์ฆ ๋ฒํธ ์ ์ก');
+ onCodeSent(verificationId);
+ },
+ codeAutoRetrievalTimeout: (String verificationId) {
+ log(name: 'AuthRepositoryImpl : verifyPhoneNumber', "์ธ์ฆ ๋ฒํธ ๋ง๋ฃ");
+ },
+ );
+ }
+
+ @override
+ Future signInWithSmsCode(String verificationId, String smsCode) async {
+ try {
+ log(
+ name: 'AuthRepositoryImpl : signInWithSmsCode',
+ "$verificationId - $smsCode");
+ final credential = PhoneAuthProvider.credential(
+ verificationId: verificationId,
+ smsCode: smsCode,
+ );
+ await _auth.signInWithCredential(credential);
+ log(name: 'AuthRepositoryImpl : signInWithSmsCode', 'Sign in successful');
+ } on FirebaseAuthException catch (e) {
+ log(
+ name: 'AuthRepositoryImpl : signInWithSmsCode',
+ 'FirebaseAuthException: ${e.code} - ${e.message}');
+ rethrow;
+ }
+ }
+}
diff --git a/lib/auth/domain/repositories/.gitkeep b/lib/auth/domain/repositories/.gitkeep
deleted file mode 100644
index e69de29..0000000
diff --git a/lib/auth/domain/repositories/auth_repository.dart b/lib/auth/domain/repositories/auth_repository.dart
new file mode 100644
index 0000000..3bb06e6
--- /dev/null
+++ b/lib/auth/domain/repositories/auth_repository.dart
@@ -0,0 +1,5 @@
+abstract class AuthRepository {
+ Future verifyPhoneNumber(
+ String phoneNumber, Function(String) onCodeSent);
+ Future signInWithSmsCode(String verificationId, String smsCode);
+}
diff --git a/lib/auth/domain/usecases/.gitkeep b/lib/auth/domain/usecases/.gitkeep
deleted file mode 100644
index e69de29..0000000
diff --git a/lib/auth/domain/usecases/phone_verificarion_usecase.dart b/lib/auth/domain/usecases/phone_verificarion_usecase.dart
new file mode 100644
index 0000000..978ee5f
--- /dev/null
+++ b/lib/auth/domain/usecases/phone_verificarion_usecase.dart
@@ -0,0 +1,20 @@
+import 'package:flutter_riverpod/flutter_riverpod.dart';
+
+import '../repositories/auth_repository.dart';
+
+class VerifyPhoneNumberUseCase {
+ final AuthRepository _authRepository;
+
+ VerifyPhoneNumberUseCase(this._authRepository);
+
+ Future sendCode(
+ String phoneNumber,
+ Function(String) onCodeSent,
+ ) async {
+ await _authRepository.verifyPhoneNumber(phoneNumber, onCodeSent);
+ }
+
+ Future verifyCode(String verificationId, String smsCode) async {
+ await _authRepository.signInWithSmsCode(verificationId, smsCode);
+ }
+}
diff --git a/lib/auth/presentation/pages/congratulation/congratulation_page.dart b/lib/auth/presentation/pages/congratulation/congratulation_page.dart
index 86e1ffc..a31ea27 100644
--- a/lib/auth/presentation/pages/congratulation/congratulation_page.dart
+++ b/lib/auth/presentation/pages/congratulation/congratulation_page.dart
@@ -100,7 +100,6 @@ class CongratulationPage extends StatelessWidget {
height: 40,
),
),
-
Padding(
padding: const EdgeInsets.all(AppGaps.gap4),
child: CongratulationConfirmButton(
diff --git a/lib/auth/presentation/pages/identity/identity_verification_page.dart b/lib/auth/presentation/pages/identity/identity_verification_page.dart
new file mode 100644
index 0000000..42c3b7c
--- /dev/null
+++ b/lib/auth/presentation/pages/identity/identity_verification_page.dart
@@ -0,0 +1,136 @@
+import 'package:code_l/auth/presentation/pages/identity/providers.dart';
+import 'package:code_l/auth/presentation/pages/identity/widgets/identity_verification_app_bar.dart';
+import 'package:code_l/auth/presentation/widgets/auth_confirm_button.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 '../login/login_page.dart';
+
+class PhoneVerificationPage extends ConsumerWidget {
+ const PhoneVerificationPage({Key? key}) : super(key: key);
+
+ @override
+ Widget build(BuildContext context, WidgetRef ref) {
+ final viewModel = ref.watch(phoneVerificationViewModelProvider.notifier);
+ final state = ref.watch(phoneVerificationViewModelProvider);
+
+ return Scaffold(
+ appBar: IdentityVerificationAppBar(),
+ bottomNavigationBar: Padding(
+ padding: const EdgeInsets.all(20.0),
+ child: AuthConfirmButton(
+ enabled: state.codeSent,
+ onPressed: () {
+ if (viewModel.formKey.currentState!.validate()) {
+ viewModel.verifyCode(() {
+ Navigator.pushReplacement(
+ context,
+ MaterialPageRoute(builder: (context) => const LoginPage()),
+ );
+ });
+ }
+ },
+ ),
+ ),
+ body: Padding(
+ padding: const EdgeInsets.all(20),
+ child: Column(
+ children: [
+ Form(
+ key: viewModel.formKey,
+ child: Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ mainAxisSize: MainAxisSize.min,
+ children: [
+ SizedBox(height: AppGaps.gap40),
+ Text("ํด๋์ ํ ๋ฒํธ\n์ธ์ฆ์ด ํ์ํฉ๋๋ค", style: AppTypography.header1),
+ Text(
+ "์ํํ ์๋น์ค ์ด์ฉ์ ์ํด ๋ฒํธ์ธ์ฆ์ ํด์ฃผ์ธ์",
+ style: AppTypography.body2.copyWith(
+ color: AppColors.grey600,
+ ),
+ ),
+ SizedBox(height: AppGaps.gap40),
+ SizedBox(height: AppGaps.gap40),
+ TextFormField(
+ controller: viewModel.phoneController,
+ keyboardType: TextInputType.phone,
+ decoration: InputDecoration(
+ border: UnderlineInputBorder(
+ borderSide: BorderSide(
+ color: AppColors.grey400,
+ width: 0.6,
+ ),
+ ),
+ hintText: 'ํด๋์ ํ ๋ฒํธ',
+ suffixIcon: ElevatedButton(
+ onPressed: () {
+ if (viewModel.formKey.currentState!.validate()) {
+ viewModel.sendSmsCode();
+ }
+ },
+ style: ElevatedButton.styleFrom(
+ backgroundColor: AppColors.primary,
+ foregroundColor: AppColors.white,
+ textStyle: AppTypography.subtitle2.copyWith(
+ color: AppColors.white,
+ ),
+ shape: RoundedRectangleBorder(),
+ padding: const EdgeInsets.symmetric(
+ horizontal: AppGaps.gap12,
+ vertical: AppGaps.gap12,
+ ),
+ ),
+ child: const Text("์ธ์ฆ ์์ฒญ"),
+ ),
+ ),
+ validator: (value) {
+ if (value == null || value.isEmpty) {
+ return 'ํด๋์ ํ ๋ฒํธ๋ฅผ ์
๋ ฅํ์ธ์.';
+ }
+ if (!RegExp(
+ r'^01[0-9]-?\d{3,4}-?\d{4}$',
+ ).hasMatch(value)) {
+ return '์ ํจํ ํด๋์ ํ ๋ฒํธ๋ฅผ ์
๋ ฅํ์ธ์.';
+ }
+ return null;
+ },
+ ),
+ const SizedBox(height: 15),
+ if (state.codeSent) ...[
+ const SizedBox(height: 20),
+ // ์ธ์ฆ ์ฝ๋ ์
๋ ฅ ํ๋
+ TextFormField(
+ controller: viewModel.smsCodeController,
+ keyboardType: TextInputType.number,
+ decoration: InputDecoration(
+ border: UnderlineInputBorder(
+ borderSide: BorderSide(
+ color: AppColors.grey400,
+ width: 0.6,
+ ),
+ ),
+ hintText: '์ธ์ฆ๋ฒํธ๋ฅผ ์
๋ ฅํ์ธ์.',
+ ),
+ validator: (value) {
+ if (value == null || value.isEmpty) {
+ return '์ธ์ฆ๋ฒํธ ์
๋ ฅ';
+ }
+ if (!RegExp(r'^\d{6}$').hasMatch(value)) {
+ return '6์๋ฆฌ ์ธ์ฆ๋ฒํธ๋ฅผ ์
๋ ฅํ์ธ์.';
+ }
+ return null;
+ },
+ ),
+ ],
+ ],
+ ),
+ ),
+ ],
+ ),
+ ),
+ );
+ }
+}
diff --git a/lib/auth/presentation/pages/identity/identity_verification_viewmodel.dart b/lib/auth/presentation/pages/identity/identity_verification_viewmodel.dart
new file mode 100644
index 0000000..cb42ef0
--- /dev/null
+++ b/lib/auth/presentation/pages/identity/identity_verification_viewmodel.dart
@@ -0,0 +1,85 @@
+import 'dart:developer';
+
+import 'package:code_l/auth/presentation/pages/identity/providers.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter_riverpod/flutter_riverpod.dart';
+import 'package:fluttertoast/fluttertoast.dart';
+
+import '../../../domain/usecases/phone_verificarion_usecase.dart';
+
+class PhoneVerificationState {
+ final bool codeSent;
+ final String verificationId;
+
+ PhoneVerificationState({
+ this.codeSent = false,
+ this.verificationId = '',
+ });
+
+ PhoneVerificationState copyWith({
+ bool? codeSent,
+ String? verificationId,
+ }) {
+ return PhoneVerificationState(
+ codeSent: codeSent ?? this.codeSent,
+ verificationId: verificationId ?? this.verificationId,
+ );
+ }
+}
+
+class PhoneVerificationViewModel extends Notifier {
+ late final VerifyPhoneNumberUseCase _verifyPhoneNumberUseCase;
+ final formKey = GlobalKey();
+ final phoneController = TextEditingController();
+ final smsCodeController = TextEditingController();
+
+ @override
+ PhoneVerificationState build() {
+ _verifyPhoneNumberUseCase = ref.read(verifyPhoneNumberUseCaseProvider);
+ return PhoneVerificationState();
+ }
+
+ Future sendSmsCode() async {
+ if (formKey.currentState!.validate()) {
+ await _verifyPhoneNumberUseCase.sendCode(
+ "+82${phoneController.text.substring(1)}",
+ (verificationId) {
+ state = state.copyWith(
+ verificationId: verificationId,
+ codeSent: true,
+ );
+ },
+ );
+ log(
+ name: 'PhoneVerificationViewModel : sendSmsCode',
+ "+82${phoneController.text.substring(1)}");
+ }
+ }
+
+ Future verifyCode(Function onSuccess) async {
+ try {
+ await _verifyPhoneNumberUseCase.verifyCode(
+ state.verificationId,
+ smsCodeController.text,
+ );
+ log(
+ name: 'PhoneVerificationViewModel : verifyCode',
+ state.verificationId);
+ log(
+ name: 'PhoneVerificationViewModel : verifyCode',
+ smsCodeController.text);
+ log(name: 'PhoneVerificationViewModel : verifyCode', 'Code verified');
+ Fluttertoast.showToast(msg: '์ธ์ฆ์ด ์๋ฃ๋์์ต๋๋ค');
+ onSuccess();
+ } catch (e) {
+ log(name: 'PhoneVerificationViewModel : verifyCode', e.toString());
+ log(
+ name: 'PhoneVerificationViewModel : verifyCode',
+ state.verificationId);
+ log(
+ name: 'PhoneVerificationViewModel : verifyCode',
+ smsCodeController.text);
+ Fluttertoast.showToast(msg: "์ธ์ฆ ๋ฒํธ๊ฐ ์ฌ๋ฐ๋ฅด์ง ์์ต๋๋ค");
+ }
+ }
+}
diff --git a/lib/auth/presentation/pages/identity/providers.dart b/lib/auth/presentation/pages/identity/providers.dart
new file mode 100644
index 0000000..a079449
--- /dev/null
+++ b/lib/auth/presentation/pages/identity/providers.dart
@@ -0,0 +1,20 @@
+import 'package:flutter_riverpod/flutter_riverpod.dart';
+
+import '../../../data/repositories/auth_repository_impl.dart';
+import '../../../domain/repositories/auth_repository.dart';
+import '../../../domain/usecases/phone_verificarion_usecase.dart';
+import 'identity_verification_viewmodel.dart';
+
+final verifyPhoneNumberUseCaseProvider =
+ Provider((ref) {
+ return VerifyPhoneNumberUseCase(ref.read(authRepositoryProvider));
+});
+
+final phoneVerificationViewModelProvider =
+ NotifierProvider(
+ PhoneVerificationViewModel.new,
+);
+
+final authRepositoryProvider = Provider((ref) {
+ return AuthRepositoryImpl();
+});
diff --git a/lib/auth/presentation/pages/identity/widgets/identity_verification_app_bar.dart b/lib/auth/presentation/pages/identity/widgets/identity_verification_app_bar.dart
new file mode 100644
index 0000000..07b29ff
--- /dev/null
+++ b/lib/auth/presentation/pages/identity/widgets/identity_verification_app_bar.dart
@@ -0,0 +1,38 @@
+import 'package:code_l/core/utills/design/app_gaps.dart';
+import 'package:flutter/material.dart';
+
+import '../../../../../core/utills/design/app_colors.dart';
+import '../../../../../core/utills/design/app_typography.dart';
+
+class IdentityVerificationAppBar extends StatelessWidget
+ implements PreferredSizeWidget {
+ const IdentityVerificationAppBar({super.key});
+
+ @override
+ Size get preferredSize => Size.fromHeight(56);
+ @override
+ Widget build(BuildContext context) {
+ return SafeArea(
+ child: Padding(
+ padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8),
+ child: Row(
+ mainAxisAlignment: MainAxisAlignment.spaceBetween,
+ crossAxisAlignment: CrossAxisAlignment.center,
+ children: [
+ SizedBox(width: AppGaps.gap36),
+ Text(
+ "ํด๋์ ํ ๋ฒํธ ์ธ์ฆ",
+ style: AppTypography.subtitle2.copyWith(color: AppColors.grey900),
+ ),
+ IconButton(
+ icon: const Icon(Icons.close),
+ onPressed: () {
+ Navigator.pop(context);
+ },
+ ),
+ ],
+ ),
+ ),
+ );
+ }
+}
diff --git a/lib/auth/presentation/pages/login/login_page.dart b/lib/auth/presentation/pages/login/login_page.dart
index 7c4a875..986d1ea 100644
--- a/lib/auth/presentation/pages/login/login_page.dart
+++ b/lib/auth/presentation/pages/login/login_page.dart
@@ -1,7 +1,9 @@
+import 'package:code_l/auth/presentation/pages/identity/identity_verification_page.dart';
import 'package:code_l/auth/presentation/pages/login/providers.dart';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter_svg/flutter_svg.dart';
+import 'package:sign_in_with_apple/sign_in_with_apple.dart';
import '../../../../core/utills/design/app_colors.dart';
import '../../../../core/utills/design/app_gaps.dart';
@@ -19,7 +21,7 @@ class LoginPage extends ConsumerWidget {
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Flexible(
- flex: 4,
+ flex: 3,
child: Column(
mainAxisAlignment: MainAxisAlignment.end,
children: [
@@ -32,11 +34,19 @@ class LoginPage extends ConsumerWidget {
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
- Text("์ฝ๋๊ฐ ๋ง๋ ์ฐ๋ฆฌ๋ง์", style: AppTypography.body1),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
- Text("๊ณต๊ฐ์์ ์์๋๋ ", style: AppTypography.body1),
+ Text("์ฝ๋๊ฐ ๋ง๋ ์ฐ๋ฆฌ๋ง์ ๊ณต๊ฐ",
+ style: AppTypography.subtitle2
+ .copyWith(color: AppColors.primary)),
+ Text("์์", style: AppTypography.body1),
+ ],
+ ),
+ Row(
+ mainAxisAlignment: MainAxisAlignment.center,
+ children: [
+ Text("์์๋๋ ", style: AppTypography.body1),
Text("์ง์ง ์ธ์ฐ", style: AppTypography.subtitle1),
],
),
@@ -68,7 +78,7 @@ class LoginPage extends ConsumerWidget {
SvgPicture.asset('assets/icons/kakao_logo.svg'),
const SizedBox(width: 10),
Text(
- "์นด์นด์ค๋ก 3์ด๋ง์ ๋ก๊ทธ์ธ",
+ "์นด์นด์ค๋ก ๋ก๊ทธ์ธ",
style: AppTypography.body1.copyWith(
color: AppColors.black,
),
@@ -88,10 +98,11 @@ class LoginPage extends ConsumerWidget {
side: const BorderSide(color: AppColors.black),
),
onPressed: () {
+ ref.read(loginViewModelProvider).loginWithApple();
Navigator.push(
context,
MaterialPageRoute(
- builder: (context) => const LoginPage(),
+ builder: (context) => const PhoneVerificationPage(),
),
);
},
@@ -103,7 +114,7 @@ class LoginPage extends ConsumerWidget {
SvgPicture.asset('assets/icons/apple_logo.svg'),
const SizedBox(width: 10),
Text(
- "Apple๋ก ๊ณ์ํ๊ธฐ",
+ "Apple๋ก ๋ก๊ทธ์ธ",
style: AppTypography.body1.copyWith(
color: AppColors.black,
),
@@ -116,6 +127,16 @@ class LoginPage extends ConsumerWidget {
],
),
),
+ Flexible(
+ flex: 1,
+ child: Row(
+ mainAxisAlignment: MainAxisAlignment.center,
+ children: [
+ Text("๋ ์ฆ๋น์ธ", style: AppTypography.subtitle2),
+ Text("์ ์ํ ๋ ๊น์ด์๋ ๋งค์นญ์ฑ", style: AppTypography.body1),
+ ],
+ ),
+ ),
],
),
),
diff --git a/lib/auth/presentation/pages/login/login_viewmodel.dart b/lib/auth/presentation/pages/login/login_viewmodel.dart
index 830484f..896e9f5 100644
--- a/lib/auth/presentation/pages/login/login_viewmodel.dart
+++ b/lib/auth/presentation/pages/login/login_viewmodel.dart
@@ -3,6 +3,7 @@ import 'dart:developer';
import 'package:code_l/auth/domain/model/login_type.dart';
import 'package:flutter/cupertino.dart';
import 'package:kakao_flutter_sdk_user/kakao_flutter_sdk_user.dart';
+import 'package:sign_in_with_apple/sign_in_with_apple.dart';
import '../../../domain/usecases/login_usecase.dart';
@@ -15,10 +16,9 @@ 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();
@@ -38,4 +38,38 @@ class LoginViewModel extends ChangeNotifier {
log(name: 'LoginViewModel::loginOauth', 'error: $e');
}
}
+
+ Future loginWithApple() async {
+ try {
+ // ์ ํ ์ธ์ฆ ์ ๋ณด ๊ฐ์ ธ์ค๊ธฐ
+ final AuthorizationCredentialAppleID credential =
+ await SignInWithApple.getAppleIDCredential(
+ scopes: [
+ AppleIDAuthorizationScopes.email,
+ AppleIDAuthorizationScopes.fullName,
+ ],
+ webAuthenticationOptions: WebAuthenticationOptions(
+ clientId: "codel.codel.com", // Apple Developer Console์ ๋ฑ๋ก๋ clientId
+ redirectUri: Uri.parse(
+ "https://chartreuse-gratis-lungfish.glitch.me/callbacks/sign_in_with_apple",
+ ),
+ ),
+ );
+
+ // authorizationCode์ identityToken ํ์ธ
+ final authorizationCode = credential.authorizationCode;
+ final identityToken = credential.identityToken;
+
+ if (authorizationCode == null || identityToken == null) {
+ throw Exception("Authorization Code ๋๋ Identity Token์ ๊ฐ์ ธ์ค์ง ๋ชปํ์ต๋๋ค.");
+ }
+
+ // ๋ฐฑ์๋๋ก OAuth ์ธ์ฆ ์์ฒญ
+ await loginOauth(LoginType.apple, identityToken);
+
+ log(name: 'LoginViewModel::loginWithApple', 'success: $identityToken');
+ } 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 4c8c842..87332b0 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,10 +73,9 @@ 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(
@@ -84,10 +83,9 @@ 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,
),
),
],
@@ -104,10 +102,9 @@ 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,
),
),
),
@@ -116,10 +113,9 @@ 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 9b45753..44cf916 100644
--- a/lib/auth/presentation/pages/woman/woman_verification_Page.dart
+++ b/lib/auth/presentation/pages/woman/woman_verification_Page.dart
@@ -130,10 +130,9 @@ class WomanVerificationPage extends ConsumerWidget {
Text(
"์ ์๋ด์ฌํญ์ ๋ชจ๋ ํ์ธํ์์ต๋๋ค.",
style: AppTypography.subtitle2.copyWith(
- color:
- viewModel.isChecked
- ? AppColors.grey800
- : AppColors.grey400,
+ color: viewModel.isChecked
+ ? AppColors.grey800
+ : AppColors.grey400,
),
),
IconButton(
@@ -142,10 +141,9 @@ 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/firebase_options.dart b/lib/firebase_options.dart
new file mode 100644
index 0000000..0a2eae0
--- /dev/null
+++ b/lib/firebase_options.dart
@@ -0,0 +1,72 @@
+// File generated by FlutterFire CLI.
+// ignore_for_file: type=lint
+import 'package:firebase_core/firebase_core.dart' show FirebaseOptions;
+import 'package:flutter/foundation.dart'
+ show defaultTargetPlatform, kIsWeb, TargetPlatform;
+
+/// Default [FirebaseOptions] for use with your Firebase apps.
+///
+/// Example:
+/// ```dart
+/// import 'firebase_options.dart';
+/// // ...
+/// await Firebase.initializeApp(
+/// options: DefaultFirebaseOptions.currentPlatform,
+/// );
+/// ```
+class DefaultFirebaseOptions {
+ static FirebaseOptions get currentPlatform {
+ if (kIsWeb) {
+ throw UnsupportedError(
+ 'DefaultFirebaseOptions have not been configured for web - '
+ 'you can reconfigure this by running the FlutterFire CLI again.',
+ );
+ }
+ switch (defaultTargetPlatform) {
+ case TargetPlatform.android:
+ return android;
+ case TargetPlatform.iOS:
+ return ios;
+ case TargetPlatform.macOS:
+ throw UnsupportedError(
+ 'DefaultFirebaseOptions have not been configured for macos - '
+ 'you can reconfigure this by running the FlutterFire CLI again.',
+ );
+ case TargetPlatform.windows:
+ throw UnsupportedError(
+ 'DefaultFirebaseOptions have not been configured for windows - '
+ 'you can reconfigure this by running the FlutterFire CLI again.',
+ );
+ case TargetPlatform.linux:
+ throw UnsupportedError(
+ 'DefaultFirebaseOptions have not been configured for linux - '
+ 'you can reconfigure this by running the FlutterFire CLI again.',
+ );
+ default:
+ throw UnsupportedError(
+ 'DefaultFirebaseOptions are not supported for this platform.',
+ );
+ }
+ }
+
+ static const FirebaseOptions android = FirebaseOptions(
+ apiKey: 'AIzaSyAGaxpjP5Jn2P1J-O5W5DmFCQgqcIhuxyw',
+ appId: '1:971644319685:android:34198e5a313e5294b53dac',
+ messagingSenderId: '971644319685',
+ projectId: 'code-l-b109b',
+ storageBucket: 'code-l-b109b.firebasestorage.app',
+ );
+
+ static const FirebaseOptions ios = FirebaseOptions(
+ apiKey: 'AIzaSyA6aPcY0Qv4eCO4Q_KLxF0KMDQ9M9wdZlw',
+ appId: '1:971644319685:ios:bde2639222525193b53dac',
+ messagingSenderId: '971644319685',
+ projectId: 'code-l-b109b',
+ storageBucket: 'code-l-b109b.firebasestorage.app',
+ androidClientId:
+ '971644319685-vnlopiq93h2n0cukes3chrm8n51t2836.apps.googleusercontent.com',
+ iosClientId:
+ '971644319685-jo8kiqh779jhevlh53d3cbj3lrdavovf.apps.googleusercontent.com',
+ iosBundleId: 'com.codel.codel',
+ );
+}
diff --git a/lib/main.dart b/lib/main.dart
index c30236d..409f503 100644
--- a/lib/main.dart
+++ b/lib/main.dart
@@ -1,6 +1,5 @@
import 'package:code_l/auth/presentation/pages/login/login_page.dart';
import 'package:code_l/auth/presentation/pages/terms_and_conditions/terms_and_condition_page.dart';
-import 'package:code_l/sign_up/presentation/pages/profile_interest/profile_intereset_page.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:flutter/material.dart';
import 'package:flutter_dotenv/flutter_dotenv.dart';
@@ -27,7 +26,7 @@ class MyApp extends StatelessWidget {
Widget build(BuildContext context) {
return MaterialApp(
title: 'Kakao Login Demo',
- home: const ProfileInterestPage(),
+ home: const LoginPage(),
theme: ThemeData(
primarySwatch: Colors.blue,
scaffoldBackgroundColor: Colors.white,
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 fcfa1b4..7fd1d29 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,47 +63,44 @@ 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),
+ 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,
),
- 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,
- ),
- ],
+ 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 76147d2..13b66d8 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
@@ -52,12 +52,11 @@ class _CodeLifestyleDrinkPageState extends State {
style: AppTypography.body2.copyWith(color: AppColors.grey600),
),
SizedBox(height: AppGaps.gap40),
-
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;
@@ -75,15 +74,13 @@ 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 2ed14aa..5f9a069 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,15 +82,13 @@ 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 cc4556e..43a082f 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,58 +356,56 @@ 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,
- ),
+ 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,
),
- if (isSelected)
- const Icon(
- Icons.check,
- color: AppColors.primary,
- size: 20,
- ),
- ],
- ),
+ ],
),
- );
- },
- ),
+ ),
+ );
+ },
+ ),
),
],
),
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 99b0f5f..a7a3d42 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,15 +109,13 @@ 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_lovestyle/profile_lovestyle_page.dart b/lib/sign_up/presentation/pages/profile_lovestyle/profile_lovestyle_page.dart
index 0a9a834..0ed62f7 100644
--- a/lib/sign_up/presentation/pages/profile_lovestyle/profile_lovestyle_page.dart
+++ b/lib/sign_up/presentation/pages/profile_lovestyle/profile_lovestyle_page.dart
@@ -161,7 +161,6 @@ class _ProfileLoveStylePageState extends State {
},
),
),
-
SizedBox(height: AppGaps.gap32),
Text("๊ฐ๋ฑ ํด๊ฒฐ", style: AppTypography.subtitle1),
SizedBox(height: AppGaps.gap12),
diff --git a/pubspec.lock b/pubspec.lock
index 3f6ba92..328c584 100644
--- a/pubspec.lock
+++ b/pubspec.lock
@@ -5,10 +5,10 @@ packages:
dependency: transitive
description:
name: _fe_analyzer_shared
- sha256: dc27559385e905ad30838356c5f5d574014ba39872d732111cd07ac0beff4c57
+ sha256: e55636ed79578b9abca5fecf9437947798f5ef7456308b5cb85720b793eac92f
url: "https://pub.dev"
source: hosted
- version: "80.0.0"
+ version: "82.0.0"
_flutterfire_internals:
dependency: transitive
description:
@@ -21,10 +21,10 @@ packages:
dependency: transitive
description:
name: analyzer
- sha256: "192d1c5b944e7e53b24b5586db760db934b177d4147c42fbca8c8c5f1eb8d11e"
+ sha256: f4c21c94eb4623b183c1014a470196b3910701bea9b926e6c91270d756e6fc60
url: "https://pub.dev"
source: hosted
- version: "7.3.0"
+ version: "7.4.1"
args:
dependency: transitive
description:
@@ -266,10 +266,10 @@ packages:
dependency: "direct main"
description:
name: flutter_svg
- sha256: c200fd79c918a40c5cd50ea0877fa13f81bdaf6f0a5d3dbcc2a13e3285d6aa1b
+ sha256: d44bf546b13025ec7353091516f6881f1d4c633993cb109c3916c3a0159dadf1
url: "https://pub.dev"
source: hosted
- version: "2.0.17"
+ version: "2.1.0"
flutter_test:
dependency: "direct dev"
description: flutter
@@ -280,6 +280,14 @@ packages:
description: flutter
source: sdk
version: "0.0.0"
+ fluttertoast:
+ dependency: "direct main"
+ description:
+ name: fluttertoast
+ sha256: "25e51620424d92d3db3832464774a6143b5053f15e382d8ffbfd40b6e795dcf1"
+ url: "https://pub.dev"
+ source: hosted
+ version: "8.2.12"
glob:
dependency: transitive
description:
@@ -324,10 +332,10 @@ packages:
dependency: "direct main"
description:
name: json_serializable
- sha256: "81f04dee10969f89f604e1249382d46b97a1ccad53872875369622b5bfc9e58a"
+ sha256: c50ef5fc083d5b5e12eef489503ba3bf5ccc899e487d691584699b4bdefeea8c
url: "https://pub.dev"
source: hosted
- version: "6.9.4"
+ version: "6.9.5"
kakao_flutter_sdk_auth:
dependency: transitive
description:
@@ -540,10 +548,10 @@ packages:
dependency: transitive
description:
name: shared_preferences_android
- sha256: "3ec7210872c4ba945e3244982918e502fa2bfb5230dff6832459ca0e1879b7ad"
+ sha256: "20cbd561f743a342c76c151d6ddb93a9ce6005751e7aa458baad3858bfbfb6ac"
url: "https://pub.dev"
source: hosted
- version: "2.4.8"
+ version: "2.4.10"
shared_preferences_foundation:
dependency: transitive
description:
@@ -584,6 +592,30 @@ packages:
url: "https://pub.dev"
source: hosted
version: "2.4.1"
+ sign_in_with_apple:
+ dependency: "direct main"
+ description:
+ name: sign_in_with_apple
+ sha256: "8bd875c8e8748272749eb6d25b896f768e7e9d60988446d543fe85a37a2392b8"
+ url: "https://pub.dev"
+ source: hosted
+ version: "7.0.1"
+ sign_in_with_apple_platform_interface:
+ dependency: transitive
+ description:
+ name: sign_in_with_apple_platform_interface
+ sha256: "981bca52cf3bb9c3ad7ef44aace2d543e5c468bb713fd8dda4275ff76dfa6659"
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.0.0"
+ sign_in_with_apple_web:
+ dependency: transitive
+ description:
+ name: sign_in_with_apple_web
+ sha256: f316400827f52cafcf50d00e1a2e8a0abc534ca1264e856a81c5f06bd5b10fed
+ url: "https://pub.dev"
+ source: hosted
+ version: "3.0.0"
sky_engine:
dependency: transitive
description: flutter
diff --git a/pubspec.yaml b/pubspec.yaml
index d867a8a..8cd355b 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -41,9 +41,11 @@ dependencies:
firebase_auth: ^5.5.2
firebase_core: ^3.13.0
http: ^1.3.0
+ fluttertoast: ^8.2.12
kakao_flutter_sdk_user: ^1.9.7+3
flutter_dotenv: ^5.2.1
screen_protector: ^1.4.2+1
+ sign_in_with_apple: ^7.0.1
dev_dependencies:
flutter_test:
diff --git a/test/widget_test.dart b/test/widget_test.dart
index 7f18f08..3855f07 100644
--- a/test/widget_test.dart
+++ b/test/widget_test.dart
@@ -11,20 +11,20 @@ import 'package:flutter_test/flutter_test.dart';
import 'package:code_l/main.dart';
void main() {
- testWidgets('Counter increments smoke test', (WidgetTester tester) async {
- // Build our app and trigger a frame.
- await tester.pumpWidget(const MyApp());
-
- // Verify that our counter starts at 0.
- expect(find.text('0'), findsOneWidget);
- expect(find.text('1'), findsNothing);
-
- // Tap the '+' icon and trigger a frame.
- await tester.tap(find.byIcon(Icons.add));
- await tester.pump();
-
- // Verify that our counter has incremented.
- expect(find.text('0'), findsNothing);
- expect(find.text('1'), findsOneWidget);
- });
+ // testWidgets('Counter increments smoke test', (WidgetTester tester) async {
+ // // Build our app and trigger a frame.
+ // await tester.pumpWidget(const MyApp());
+ //
+ // // Verify that our counter starts at 0.
+ // expect(find.text('0'), findsOneWidget);
+ // expect(find.text('1'), findsNothing);
+ //
+ // // Tap the '+' icon and trigger a frame.
+ // await tester.tap(find.byIcon(Icons.add));
+ // await tester.pump();
+ //
+ // // Verify that our counter has incremented.
+ // expect(find.text('0'), findsNothing);
+ // expect(find.text('1'), findsOneWidget);
+ // });
}