From 264f41c26206edfda3128729341558c5b711ca9f Mon Sep 17 00:00:00 2001 From: withseon Date: Sun, 5 May 2024 00:00:02 +0900 Subject: [PATCH 1/3] =?UTF-8?q?[Edit]=20=ED=9A=8C=EC=9B=90=20=EA=B0=80?= =?UTF-8?q?=EC=9E=85=20=EC=8B=9C,=20=EB=8B=89=EB=84=A4=EC=9E=84=EA=B3=BC?= =?UTF-8?q?=20=EC=83=9D=EB=85=84=EC=9B=94=EC=9D=BC=20=EC=9C=A0=ED=9A=A8?= =?UTF-8?q?=EC=84=B1=20=ED=8C=90=EB=B3=84=20#182?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - isValidNameFormat: 닉네임 유효성 판별 - isValidBirthFormat: 생년월일 유효성 판별 --- JUDA_iOS/JUDA.xcodeproj/project.pbxproj | 56 ++++--------------- .../xcshareddata/xcschemes/JUDA.xcscheme | 3 +- .../JUDA/View/LogIn/ProfileSettingView.swift | 19 +++++-- 3 files changed, 25 insertions(+), 53 deletions(-) diff --git a/JUDA_iOS/JUDA.xcodeproj/project.pbxproj b/JUDA_iOS/JUDA.xcodeproj/project.pbxproj index da89630..3dcc372 100644 --- a/JUDA_iOS/JUDA.xcodeproj/project.pbxproj +++ b/JUDA_iOS/JUDA.xcodeproj/project.pbxproj @@ -61,9 +61,7 @@ 09BCC15A2B7C8CD300FF4D1B /* IdentityVerificationView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09BCC1592B7C8CD300FF4D1B /* IdentityVerificationView.swift */; }; 09BCC15F2B7CFC7E00FF4D1B /* TermsAndVerificationView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09BCC15E2B7CFC7E00FF4D1B /* TermsAndVerificationView.swift */; }; 09C7C9AF2B8DB57E00F62617 /* NavigationRouter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09C7C9AE2B8DB57E00F62617 /* NavigationRouter.swift */; }; - 09E3B6E82BC51396001BC529 /* DrinkLoading.json in Resources */ = {isa = PBXBuildFile; fileRef = 09E3B6E72BC51396001BC529 /* DrinkLoading.json */; }; - 09E3B6EB2BC5139F001BC529 /* APIKEYS.plist in Resources */ = {isa = PBXBuildFile; fileRef = 09E3B6E92BC5139F001BC529 /* APIKEYS.plist */; }; - 09E3B6EC2BC5139F001BC529 /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 09E3B6EA2BC5139F001BC529 /* GoogleService-Info.plist */; }; + 09E3B6E82BC51396001BC529 /* (null) in Resources */ = {isa = PBXBuildFile; }; 09F3BD9C2BA9EAE90087E5FC /* Lottie in Frameworks */ = {isa = PBXBuildFile; productRef = 09F3BD9B2BA9EAE90087E5FC /* Lottie */; }; 09F869932B68E36800A56A4C /* Formatter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09F869922B68E36800A56A4C /* Formatter.swift */; }; 09F869962B68E46500A56A4C /* DrinkDetailView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09F869952B68E46500A56A4C /* DrinkDetailView.swift */; }; @@ -90,17 +88,15 @@ 2C63DD672B67EB1B00770E3A /* RecordView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2C63DD662B67EB1B00770E3A /* RecordView.swift */; }; 2C69CDAC2B9DF61600F70F80 /* RecordViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2C69CDAB2B9DF61600F70F80 /* RecordViewModel.swift */; }; 2C7FD5522B848EEF00169512 /* Post.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2C7FD5512B848EEF00169512 /* Post.swift */; }; - 2C9707442BC5144F001D57D5 /* APIKEYS.plist in Resources */ = {isa = PBXBuildFile; fileRef = 2C9707422BC5144F001D57D5 /* APIKEYS.plist */; }; - 2C9707452BC5144F001D57D5 /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 2C9707432BC5144F001D57D5 /* GoogleService-Info.plist */; }; 2C9707472BC51486001D57D5 /* DrinkLoading.json in Resources */ = {isa = PBXBuildFile; fileRef = 2C9707462BC51486001D57D5 /* DrinkLoading.json */; }; + 2C9743E12BE6801200694EE9 /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 2C9743DF2BE6801200694EE9 /* GoogleService-Info.plist */; }; + 2C9743E22BE6801200694EE9 /* APIKEYS.plist in Resources */ = {isa = PBXBuildFile; fileRef = 2C9743E02BE6801200694EE9 /* APIKEYS.plist */; }; 2CACB53C2B99BAC500DD6DCE /* FireStorageService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2CACB53B2B99BAC500DD6DCE /* FireStorageService.swift */; }; 7B0A8BC52B8C163E00740E61 /* Report.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B0A8BC42B8C163E00740E61 /* Report.swift */; }; 7B0A8BCD2B8CA7E900740E61 /* PostSearchList.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B0A8BCC2B8CA7E900740E61 /* PostSearchList.swift */; }; 7B0A8BCF2B8CA8C300740E61 /* PostSearchListCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B0A8BCE2B8CA8C300740E61 /* PostSearchListCell.swift */; }; 7B5174922B69EAB300915793 /* NavigationPostsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B5174912B69EAB300915793 /* NavigationPostsView.swift */; }; 7B56AE172BA66C8200C47F3C /* FirebaseFunctions in Frameworks */ = {isa = PBXBuildFile; productRef = 7B56AE162BA66C8200C47F3C /* FirebaseFunctions */; }; - 7B648FC52BC52969009010DC /* APIKEYS.plist in Resources */ = {isa = PBXBuildFile; fileRef = 7B648FC32BC52969009010DC /* APIKEYS.plist */; }; - 7B648FC62BC52969009010DC /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 7B648FC42BC52969009010DC /* GoogleService-Info.plist */; }; 7B6D76A72B677A8F00601B55 /* Button.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B6D76A62B677A8F00601B55 /* Button.swift */; }; 7B6D76AB2B67CE3D00601B55 /* PostDetailView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B6D76AA2B67CE3D00601B55 /* PostDetailView.swift */; }; 7B6D76AF2B67CFC900601B55 /* PostInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B6D76AE2B67CFC900601B55 /* PostInfo.swift */; }; @@ -122,7 +118,6 @@ 7BBDFF702B6B90EB0036FB8B /* PostGrid.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B6D76B62B68972000601B55 /* PostGrid.swift */; }; 7BBDFF722B6B912C0036FB8B /* TabItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2C63DD512B676E1000770E3A /* TabItem.swift */; }; 7BBDFF732B6B912C0036FB8B /* DrinkInfoSegment.swift in Sources */ = {isa = PBXBuildFile; fileRef = B16EB85B2B63859800E920A3 /* DrinkInfoSegment.swift */; }; - 7BD26B482BADC00F0036EB91 /* DrinkLoading.json in Resources */ = {isa = PBXBuildFile; fileRef = 7BD26B472BADC00F0036EB91 /* DrinkLoading.json */; }; 7BE14B952B84733900C1F6C3 /* Drink.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7BE14B942B84733900C1F6C3 /* Drink.swift */; }; 7BE14B972B84767000C1F6C3 /* DrinkUploadViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7BE14B962B84767000C1F6C3 /* DrinkUploadViewModel.swift */; }; AC110B572B69658C005390BB /* ChangeUserNameView.swift in Sources */ = {isa = PBXBuildFile; fileRef = AC110B562B69658C005390BB /* ChangeUserNameView.swift */; }; @@ -228,8 +223,6 @@ 09BCC1592B7C8CD300FF4D1B /* IdentityVerificationView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IdentityVerificationView.swift; sourceTree = ""; }; 09BCC15E2B7CFC7E00FF4D1B /* TermsAndVerificationView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TermsAndVerificationView.swift; sourceTree = ""; }; 09C7C9AE2B8DB57E00F62617 /* NavigationRouter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NavigationRouter.swift; sourceTree = ""; }; - 09E3B6E92BC5139F001BC529 /* APIKEYS.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = APIKEYS.plist; path = "../../../흐르미/APIKEYS.plist"; sourceTree = ""; }; - 09E3B6EA2BC5139F001BC529 /* GoogleService-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = "GoogleService-Info.plist"; path = "../../../흐르미/GoogleService-Info.plist"; sourceTree = ""; }; 09F869922B68E36800A56A4C /* Formatter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Formatter.swift; sourceTree = ""; }; 09F869952B68E46500A56A4C /* DrinkDetailView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DrinkDetailView.swift; sourceTree = ""; }; 09F869972B68E48400A56A4C /* DrinkDetails.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DrinkDetails.swift; sourceTree = ""; }; @@ -256,16 +249,14 @@ 2C63DD662B67EB1B00770E3A /* RecordView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RecordView.swift; sourceTree = ""; }; 2C69CDAB2B9DF61600F70F80 /* RecordViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RecordViewModel.swift; sourceTree = ""; }; 2C7FD5512B848EEF00169512 /* Post.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Post.swift; sourceTree = ""; }; - 2C9707422BC5144F001D57D5 /* APIKEYS.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = APIKEYS.plist; path = "../../../HrMi-JUDA/APIKEY & plist.plist/APIKEYS.plist"; sourceTree = ""; }; - 2C9707432BC5144F001D57D5 /* GoogleService-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = "GoogleService-Info.plist"; path = "../../../HrMi-JUDA/APIKEY & plist.plist/GoogleService-Info.plist"; sourceTree = ""; }; 2C9707462BC51486001D57D5 /* DrinkLoading.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; name = DrinkLoading.json; path = "../../../../../HrMi-JUDA/Lottie/DrinkLoading.json"; sourceTree = ""; }; + 2C9743DF2BE6801200694EE9 /* GoogleService-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = "GoogleService-Info.plist"; path = "../../../HrMi-JUDA/APIKEY & plist.plist/GoogleService-Info.plist"; sourceTree = ""; }; + 2C9743E02BE6801200694EE9 /* APIKEYS.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = APIKEYS.plist; path = "../../../HrMi-JUDA/APIKEY & plist.plist/APIKEYS.plist"; sourceTree = ""; }; 2CACB53B2B99BAC500DD6DCE /* FireStorageService.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FireStorageService.swift; sourceTree = ""; }; 7B0A8BC42B8C163E00740E61 /* Report.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Report.swift; sourceTree = ""; }; 7B0A8BCC2B8CA7E900740E61 /* PostSearchList.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PostSearchList.swift; sourceTree = ""; }; 7B0A8BCE2B8CA8C300740E61 /* PostSearchListCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PostSearchListCell.swift; sourceTree = ""; }; 7B5174912B69EAB300915793 /* NavigationPostsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NavigationPostsView.swift; sourceTree = ""; }; - 7B648FC32BC52969009010DC /* APIKEYS.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = APIKEYS.plist; path = ../../../../../../JUDA_file/APIKEYS.plist; sourceTree = ""; }; - 7B648FC42BC52969009010DC /* GoogleService-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = "GoogleService-Info.plist"; path = "../../../../../../JUDA_file/GoogleService-Info.plist"; sourceTree = ""; }; 7B6D76A62B677A8F00601B55 /* Button.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Button.swift; sourceTree = ""; }; 7B6D76AA2B67CE3D00601B55 /* PostDetailView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PostDetailView.swift; sourceTree = ""; }; 7B6D76AE2B67CFC900601B55 /* PostInfo.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PostInfo.swift; sourceTree = ""; }; @@ -283,7 +274,6 @@ 7B92656C2B692F0700840095 /* PostReportContent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PostReportContent.swift; sourceTree = ""; }; 7B92656E2B69303F00840095 /* PostReportButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PostReportButton.swift; sourceTree = ""; }; 7B9265702B6941D000840095 /* PostReportToolbar.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PostReportToolbar.swift; sourceTree = ""; }; - 7BD26B472BADC00F0036EB91 /* DrinkLoading.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; name = DrinkLoading.json; path = ../../../../../../../../JUDA_file/Lottie/DrinkLoading.json; sourceTree = ""; }; 7BE14B942B84733900C1F6C3 /* Drink.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Drink.swift; sourceTree = ""; }; 7BE14B962B84767000C1F6C3 /* DrinkUploadViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DrinkUploadViewModel.swift; sourceTree = ""; }; AC110B562B69658C005390BB /* ChangeUserNameView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChangeUserNameView.swift; sourceTree = ""; }; @@ -445,13 +435,6 @@ path = Lottie; sourceTree = ""; }; - 09E3B6E62BC51344001BC529 /* Recovered References */ = { - isa = PBXGroup; - children = ( - ); - name = "Recovered References"; - sourceTree = ""; - }; 09F869942B68E44A00A56A4C /* DrinkDetail */ = { isa = PBXGroup; children = ( @@ -475,13 +458,6 @@ path = ContentView; sourceTree = ""; }; - 2C9707412BC513BE001D57D5 /* Recovered References */ = { - isa = PBXGroup; - children = ( - ); - name = "Recovered References"; - sourceTree = ""; - }; 7B0A8BCA2B8CA77400740E61 /* PostDetail */ = { isa = PBXGroup; children = ( @@ -513,13 +489,6 @@ name = Frameworks; sourceTree = ""; }; - 7B648FC22BC528F7009010DC /* Recovered References */ = { - isa = PBXGroup; - children = ( - ); - name = "Recovered References"; - sourceTree = ""; - }; B121A5652B5F8D2000667D42 /* Resource */ = { isa = PBXGroup; children = ( @@ -581,7 +550,6 @@ children = ( B1B8FE7B2B5EA9D900921BBE /* JUDA */, 7B56AE152BA66C8200C47F3C /* Frameworks */, - 2C9707412BC513BE001D57D5 /* Recovered References */, ); sourceTree = ""; }; @@ -598,8 +566,8 @@ B1B8FE802B5EA9DA00921BBE /* Assets.xcassets */, B1B8FE8C2B5EAAAB00921BBE /* Colors.xcassets */, B121A56F2B5F8DA100667D42 /* Info.plist */, - 09E3B6E92BC5139F001BC529 /* APIKEYS.plist */, - 09E3B6EA2BC5139F001BC529 /* GoogleService-Info.plist */, + 2C9743E02BE6801200694EE9 /* APIKEYS.plist */, + 2C9743DF2BE6801200694EE9 /* GoogleService-Info.plist */, B1B8FE822B5EA9DA00921BBE /* Preview Content */, ); path = JUDA; @@ -867,8 +835,7 @@ }; buildConfigurationList = B1B8FE742B5EA9D900921BBE /* Build configuration list for PBXProject "JUDA" */; compatibilityVersion = "Xcode 14.0"; - - mentRegion = ko; + developmentRegion = en; hasScannedForEncodings = 0; knownRegions = ( en, @@ -903,20 +870,19 @@ B1B8FE8D2B5EAAAB00921BBE /* Colors.xcassets in Resources */, B121A5732B5F910900667D42 /* Pretendard-Bold.otf in Resources */, 09BCC14F2B7C7E2900FF4D1B /* Loading.json in Resources */, - 09E3B6E82BC51396001BC529 /* DrinkLoading.json in Resources */, + 09E3B6E82BC51396001BC529 /* (null) in Resources */, B1B8FE842B5EA9DA00921BBE /* Preview Assets.xcassets in Resources */, B121A5782B5F911A00667D42 /* Pretendard-Thin.otf in Resources */, B121A5772B5F911900667D42 /* Pretendard-SemiBold.otf in Resources */, 09BCC1532B7C7E2900FF4D1B /* Snow.json in Resources */, + 2C9743E12BE6801200694EE9 /* GoogleService-Info.plist in Resources */, 09BCC1542B7C7E2900FF4D1B /* Clouds.json in Resources */, - 09E3B6EC2BC5139F001BC529 /* GoogleService-Info.plist in Resources */, B121A5742B5F910B00667D42 /* Pretendard-Light.otf in Resources */, 09BCC1522B7C7E2900FF4D1B /* Rain.json in Resources */, - 2C9707452BC5144F001D57D5 /* GoogleService-Info.plist in Resources */, B121A5762B5F911700667D42 /* Pretendard-Regular.otf in Resources */, B1B8FE812B5EA9DA00921BBE /* Assets.xcassets in Resources */, B121A5752B5F911500667D42 /* Pretendard-Medium.otf in Resources */, - 09E3B6EB2BC5139F001BC529 /* APIKEYS.plist in Resources */, + 2C9743E22BE6801200694EE9 /* APIKEYS.plist in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/JUDA_iOS/JUDA.xcodeproj/xcshareddata/xcschemes/JUDA.xcscheme b/JUDA_iOS/JUDA.xcodeproj/xcshareddata/xcschemes/JUDA.xcscheme index 4a3ef73..29ee0a7 100644 --- a/JUDA_iOS/JUDA.xcodeproj/xcshareddata/xcschemes/JUDA.xcscheme +++ b/JUDA_iOS/JUDA.xcodeproj/xcshareddata/xcschemes/JUDA.xcscheme @@ -42,8 +42,7 @@ allowLocationSimulation = "YES"> - BundleIdentifier = "com.hrmi.juda" + FilePath = "/Users/chung-inseon/Library/Developer/Xcode/DerivedData/JUDA-alivsugfiknafgevihdwjnmwgsbv/Build/Products/Debug-iphoneos/JUDA.app"> 10) - } // 상위 뷰 체인지를 위함 @Binding var viewType: TermsOrVerification @@ -109,6 +110,9 @@ struct ProfileSettingView: View { .keyboardType(.default) .textInputAutocapitalization(.never) .autocorrectionDisabled() // 자동 수정 비활성화 + .onChange(of: name) { _ in + isValidNameFormat = (name.count >= 2) && (name.count <= 10) + } Spacer() // 텍스트 한번에 지우는 xmark 버튼 if !name.isEmpty && focusedField == .name { @@ -127,7 +131,7 @@ struct ProfileSettingView: View { // 닉네임 만족 기준 Text("닉네임을 2자~10자 이내로 적어주세요.") .font(.light14) - .foregroundStyle(nameReference ? .mainAccent01 : .clear) + .foregroundStyle(name.isEmpty || isValidNameFormat ? .clear : .mainAccent01) .frame(maxWidth: .infinity, alignment: .leading) } // 생일 + 성별 @@ -203,14 +207,17 @@ struct ProfileSettingView: View { .buttonStyle(.borderedProminent) .tint(.mainAccent03) // 모든 정보 입력 시, 버튼 보이도록 - .disabled(name.isEmpty || birthDate.isEmpty || selectedGender == nil) + .disabled(!isValidNameFormat || !isValidBirthFormat || selectedGender == nil) .padding(.bottom, 10) } .padding(.horizontal, 20) // 생일 6글자 치면 끝 .onChange(of: birthDate) { _ in if birthDate.count == 6 { + isValidBirthFormat = true focusedField = nil + } else { + isValidBirthFormat = false } } // 텍스트필드에서 엔터 시, 이동 From 7726f73ba50f83f596c3f8afa9eb2c2c9cc34b4d Mon Sep 17 00:00:00 2001 From: withseon Date: Sun, 12 May 2024 23:51:12 +0900 Subject: [PATCH 2/3] =?UTF-8?q?[Edit]=20User=20=EB=8B=89=EB=84=A4=EC=9E=84?= =?UTF-8?q?=20=EB=B3=80=EA=B2=BD=20#182?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - TextField 10자 이내 입력 가능 - 닉네임 만족 기준에 공백 여부 추가 --- .../MypageDetail/ChangeUserNameView.swift | 33 +++++++++++-------- .../JUDA/ViewModel/Auth/AuthViewModel.swift | 2 +- 2 files changed, 21 insertions(+), 14 deletions(-) diff --git a/JUDA_iOS/JUDA/View/Mypage/MypageDetail/ChangeUserNameView.swift b/JUDA_iOS/JUDA/View/Mypage/MypageDetail/ChangeUserNameView.swift index ca2e29c..1ce9ae6 100644 --- a/JUDA_iOS/JUDA/View/Mypage/MypageDetail/ChangeUserNameView.swift +++ b/JUDA_iOS/JUDA/View/Mypage/MypageDetail/ChangeUserNameView.swift @@ -34,6 +34,7 @@ struct ChangeUserNameView: View { .textInputAutocapitalization(.never) .autocorrectionDisabled() // 자동 수정 비활성화 .onChange(of: userChangeNickName) { _ in + userChangeNickName = String(userChangeNickName.prefix(10)) isCompleted = authViewModel.isChangeUserName(changeName: userChangeNickName) } Spacer() @@ -53,20 +54,26 @@ struct ChangeUserNameView: View { .background(.gray05) .clipShape(.rect(cornerRadius: 10)) // 유저 닉네임 만족 기준 - if isFocused { - if userChangeNickName.count <= 1 || userChangeNickName.count > 10 { - Text("닉네임을 2자~10자 이내로 적어주세요.") - .font(.light14) - .foregroundStyle(.mainAccent01) - .frame(maxWidth: .infinity, alignment: .leading) - } - if userChangeNickName == authViewModel.currentUser?.userField.name { - Text("현재 사용하고 있는 닉네임입니다.") - .font(.light14) - .foregroundStyle(.mainAccent01) - .frame(maxWidth: .infinity, alignment: .leading) - } + if !userChangeNickName.isEmpty && + (userChangeNickName.count <= 1 || userChangeNickName.count > 10) { + Text("닉네임을 2자~10자 이내로 적어주세요.") + .font(.light14) + .foregroundStyle(.mainAccent01) + .frame(maxWidth: .infinity, alignment: .leading) + } + if userChangeNickName == authViewModel.currentUser?.userField.name { + Text("현재 사용하고 있는 닉네임입니다.") + .font(.light14) + .foregroundStyle(.mainAccent01) + .frame(maxWidth: .infinity, alignment: .leading) + } + if userChangeNickName.contains(" ") { + Text("공백은 사용이 불가합니다.") + .font(.light14) + .foregroundStyle(.mainAccent01) + .frame(maxWidth: .infinity, alignment: .leading) } + // spacer 대용 (키보드 숨기기 onTapGesture 영역) Rectangle() .fill(.background) diff --git a/JUDA_iOS/JUDA/ViewModel/Auth/AuthViewModel.swift b/JUDA_iOS/JUDA/ViewModel/Auth/AuthViewModel.swift index a2ab806..a67ad59 100644 --- a/JUDA_iOS/JUDA/ViewModel/Auth/AuthViewModel.swift +++ b/JUDA_iOS/JUDA/ViewModel/Auth/AuthViewModel.swift @@ -124,7 +124,7 @@ final class AuthViewModel: ObservableObject { guard let user = currentUser else { return false } - return changeName.count >= 2 && changeName.count <= 10 && user.userField.name != changeName + return changeName.count >= 2 && changeName.count <= 10 && user.userField.name != changeName && user.userField.name.contains(" ") } // 유저 프로필 사진 변경 시, 사용되는 메서드 From 628a80f741bbc6061218e0040ae30230cbb80a95 Mon Sep 17 00:00:00 2001 From: withseon Date: Mon, 10 Jun 2024 21:51:24 +0900 Subject: [PATCH 3/3] =?UTF-8?q?[Edit]=20=ED=9A=8C=EC=9B=90=EA=B0=80?= =?UTF-8?q?=EC=9E=85,=20=EB=8B=89=EB=84=A4=EC=9E=84=20=EB=B3=80=EA=B2=BD?= =?UTF-8?q?=20=EC=8B=9C=20=EB=A1=9C=EC=A7=81=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 닉네임 - 공백 입력 불가 - 10자 입력 제한 - 2~10자 기준, 기존 닉네임 사용 등 기준 미충족 시 변경(생성) 불가 생년월일 - 6자 입력 제한 - 날짜 포맷 충족 여부 판별 - 현재 날짜보다 앞선 날짜인지 판별 - 기준 미충족 시 생성 불가 --- JUDA_iOS/JUDA/Resource/Constants.swift | 8 ++++ .../JUDA/View/LogIn/ProfileSettingView.swift | 43 +++++++++++++------ .../MypageDetail/ChangeUserNameView.swift | 23 ++++------ .../JUDA/ViewModel/Auth/AuthViewModel.swift | 16 +++++-- 4 files changed, 57 insertions(+), 33 deletions(-) diff --git a/JUDA_iOS/JUDA/Resource/Constants.swift b/JUDA_iOS/JUDA/Resource/Constants.swift index b97bbff..0aa0bae 100644 --- a/JUDA_iOS/JUDA/Resource/Constants.swift +++ b/JUDA_iOS/JUDA/Resource/Constants.swift @@ -193,3 +193,11 @@ enum WhereUsedPostGridContent { case myPage case main } + +// 닉네임 변경 & 생성 시 조건에 대한 enum +enum NickNameChange { + case invalidLength + case aleadyUsing + case completed + case userNotFound +} diff --git a/JUDA_iOS/JUDA/View/LogIn/ProfileSettingView.swift b/JUDA_iOS/JUDA/View/LogIn/ProfileSettingView.swift index 0e59a73..c72f0e0 100644 --- a/JUDA_iOS/JUDA/View/LogIn/ProfileSettingView.swift +++ b/JUDA_iOS/JUDA/View/LogIn/ProfileSettingView.swift @@ -19,15 +19,9 @@ struct ProfileSettingView: View { @State private var userProfileImage: UIImage? // 사용자 프로필 이미지 @State private var name: String = "" - var namePlaceholder: String { - guard let user = authViewModel.currentUser else { return "닉네임" } - return user.userField.name - } @State private var birthDate: String = "" @State private var selectedGender: Gender? - // 닉네임 형식을 만족하는지 판별하기 위한 상태 프로퍼티 - @State private var isValidNameFormat: Bool = false // 생년월일 형식을 만족하는지 판별하기 위한 상태 프로퍼티 @State private var isValidBirthFormat: Bool = false @@ -39,6 +33,13 @@ struct ProfileSettingView: View { // 알림 동의 @Binding var notificationAllowed: Bool + // 생년월일 형식을 만족하는지 판별하기 위한 포매터 + private let formatter : DateFormatter = { + let formatter = DateFormatter() + formatter.dateFormat = "yyMMdd" + return formatter + }() + var body: some View { ZStack { VStack(alignment: .center, spacing: 30) { @@ -102,8 +103,7 @@ struct ProfileSettingView: View { .foregroundStyle(.mainBlack) // 텍스트 필드 HStack { - TextField("닉네임", text: $name, - prompt: Text(namePlaceholder)) + TextField("닉네임", text: $name) .font(.medium16) .foregroundStyle(.mainBlack) .focused($focusedField, equals: .name) @@ -111,7 +111,9 @@ struct ProfileSettingView: View { .textInputAutocapitalization(.never) .autocorrectionDisabled() // 자동 수정 비활성화 .onChange(of: name) { _ in - isValidNameFormat = (name.count >= 2) && (name.count <= 10) + // 닉네임 공백 불가. 10자 이내 + name = String(name.prefix(10)).replacingOccurrences(of: " ", with: "") + authViewModel.isChangeUserName(changeName: name) } Spacer() // 텍스트 한번에 지우는 xmark 버튼 @@ -131,7 +133,7 @@ struct ProfileSettingView: View { // 닉네임 만족 기준 Text("닉네임을 2자~10자 이내로 적어주세요.") .font(.light14) - .foregroundStyle(name.isEmpty || isValidNameFormat ? .clear : .mainAccent01) + .foregroundStyle(authViewModel.nicknameState == .invalidLength && !name.isEmpty ? .mainAccent01 : .clear) .frame(maxWidth: .infinity, alignment: .leading) } // 생일 + 성별 @@ -177,6 +179,11 @@ struct ProfileSettingView: View { } } } + // 생년월일 만족 기준 + Text("생년월일이 유효하지 않습니다.") + .font(.light14) + .foregroundStyle(!isValidBirthFormat && !birthDate.isEmpty ? .mainAccent01 : .clear) + .frame(maxWidth: .infinity, alignment: .leading) } .scrollIndicators(.hidden) .scrollDismissesKeyboard(.immediately) @@ -206,15 +213,23 @@ struct ProfileSettingView: View { } .buttonStyle(.borderedProminent) .tint(.mainAccent03) - // 모든 정보 입력 시, 버튼 보이도록 - .disabled(!isValidNameFormat || !isValidBirthFormat || selectedGender == nil) + // 모든 정보 입력이 유효할 때, 버튼 보이도록 + .disabled(authViewModel.nicknameState != .completed || !isValidBirthFormat || selectedGender == nil) .padding(.bottom, 10) } .padding(.horizontal, 20) - // 생일 6글자 치면 끝 .onChange(of: birthDate) { _ in + // 생일 6글자 제한 + birthDate = String(birthDate.prefix(6)) + // 6자 입력 완료 시 생년월일 포맷 확인 if birthDate.count == 6 { - isValidBirthFormat = true + // 생년월일 형식 유효성. 현재 날짜 이전인지 판별 + if let userBirth = formatter.date(from: birthDate), userBirth < Date() { + isValidBirthFormat = true + } else { + isValidBirthFormat = false + } + // 포커스 해제 focusedField = nil } else { isValidBirthFormat = false diff --git a/JUDA_iOS/JUDA/View/Mypage/MypageDetail/ChangeUserNameView.swift b/JUDA_iOS/JUDA/View/Mypage/MypageDetail/ChangeUserNameView.swift index 1ce9ae6..ecd0911 100644 --- a/JUDA_iOS/JUDA/View/Mypage/MypageDetail/ChangeUserNameView.swift +++ b/JUDA_iOS/JUDA/View/Mypage/MypageDetail/ChangeUserNameView.swift @@ -17,7 +17,6 @@ struct ChangeUserNameView: View { // 새롭게 변경할 user Name을 담는 프로퍼티 @State private var userChangeNickName: String = "" - @State private var isCompleted: Bool = false var body: some View { VStack(alignment: .center, spacing: 15) { @@ -34,8 +33,9 @@ struct ChangeUserNameView: View { .textInputAutocapitalization(.never) .autocorrectionDisabled() // 자동 수정 비활성화 .onChange(of: userChangeNickName) { _ in - userChangeNickName = String(userChangeNickName.prefix(10)) - isCompleted = authViewModel.isChangeUserName(changeName: userChangeNickName) + // 닉네임 공백 불가. 10자 이내 + userChangeNickName = String(userChangeNickName.prefix(10)).replacingOccurrences(of: " ", with: "") + authViewModel.isChangeUserName(changeName: userChangeNickName) } Spacer() // 텍스트 한번에 지우는 xmark 버튼 @@ -54,26 +54,18 @@ struct ChangeUserNameView: View { .background(.gray05) .clipShape(.rect(cornerRadius: 10)) // 유저 닉네임 만족 기준 - if !userChangeNickName.isEmpty && - (userChangeNickName.count <= 1 || userChangeNickName.count > 10) { + if authViewModel.nicknameState == .invalidLength && !userChangeNickName.isEmpty { Text("닉네임을 2자~10자 이내로 적어주세요.") .font(.light14) .foregroundStyle(.mainAccent01) .frame(maxWidth: .infinity, alignment: .leading) } - if userChangeNickName == authViewModel.currentUser?.userField.name { + if authViewModel.nicknameState == .aleadyUsing { Text("현재 사용하고 있는 닉네임입니다.") .font(.light14) .foregroundStyle(.mainAccent01) .frame(maxWidth: .infinity, alignment: .leading) } - if userChangeNickName.contains(" ") { - Text("공백은 사용이 불가합니다.") - .font(.light14) - .foregroundStyle(.mainAccent01) - .frame(maxWidth: .infinity, alignment: .leading) - } - // spacer 대용 (키보드 숨기기 onTapGesture 영역) Rectangle() .fill(.background) @@ -85,6 +77,7 @@ struct ChangeUserNameView: View { Task { isFocused = false await authViewModel.updateUserName(userName: userChangeNickName) + userChangeNickName = "" navigationRouter.back() } } label: { @@ -95,8 +88,8 @@ struct ChangeUserNameView: View { .padding(.vertical, 5) } - .disabled(!isCompleted) - .foregroundColor(isCompleted ? .white : .gray01) + .disabled(authViewModel.nicknameState != .completed) + .foregroundColor(authViewModel.nicknameState == .completed ? .white : .gray01) .buttonStyle(.borderedProminent) .tint(.mainAccent03) } diff --git a/JUDA_iOS/JUDA/ViewModel/Auth/AuthViewModel.swift b/JUDA_iOS/JUDA/ViewModel/Auth/AuthViewModel.swift index a67ad59..cb0190c 100644 --- a/JUDA_iOS/JUDA/ViewModel/Auth/AuthViewModel.swift +++ b/JUDA_iOS/JUDA/ViewModel/Auth/AuthViewModel.swift @@ -29,6 +29,7 @@ final class AuthViewModel: ObservableObject { // Error @Published var showError: Bool = false @Published var errorMessage: String = "" + @Published var nicknameState: NickNameChange = .invalidLength // 로그인 다이얼로그 @Published var isShowLoginDialog: Bool = false // Nonce : 암호와된 임의의 난수 @@ -120,11 +121,18 @@ final class AuthViewModel: ObservableObject { // MyPage / Setting 에서 사용 // 유저 닉네임 수정 시, 2글자 이상 10글자 이하 && 기존 닉네임과 같은지 체크 - func isChangeUserName(changeName: String) -> Bool { - guard let user = currentUser else { - return false + func isChangeUserName(changeName: String) { + if changeName.count < 2 || changeName.count > 10 { // 닉네임 길이 + nicknameState = .invalidLength + } else { + nicknameState = .completed + } + + if let user = currentUser { // 로그인한 유저의 닉네임 변경 시, 기존 닉네임과 동일한지 + if user.userField.name == changeName { + nicknameState = .aleadyUsing + } } - return changeName.count >= 2 && changeName.count <= 10 && user.userField.name != changeName && user.userField.name.contains(" ") } // 유저 프로필 사진 변경 시, 사용되는 메서드