From d048205b5b2720a6c76d436d51a5a35634a739fb Mon Sep 17 00:00:00 2001 From: Zoe Date: Sun, 22 Sep 2024 04:09:22 +0900 Subject: [PATCH 01/20] =?UTF-8?q?[Add/#42]=20=ED=94=84=EB=A1=9C=EC=A0=9D?= =?UTF-8?q?=ED=8A=B8=ED=8C=8C=EC=9D=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- DDANZI_iOS/DDANZI_iOS.xcodeproj/project.pbxproj | 16 ++++++++++++++++ .../Data/DTO/Mypage/UserAccountRequestDTO.swift | 8 ++++++++ .../Presentation/Mypage/Model/BankList.swift | 8 ++++++++ .../Mypage/View/Info/AccountAddCell.swift | 8 ++++++++ .../View/Info/AccountAddViewController.swift | 8 ++++++++ 5 files changed, 48 insertions(+) create mode 100644 DDANZI_iOS/DDANZI_iOS/Data/DTO/Mypage/UserAccountRequestDTO.swift create mode 100644 DDANZI_iOS/DDANZI_iOS/Presentation/Mypage/Model/BankList.swift create mode 100644 DDANZI_iOS/DDANZI_iOS/Presentation/Mypage/View/Info/AccountAddCell.swift create mode 100644 DDANZI_iOS/DDANZI_iOS/Presentation/Mypage/View/Info/AccountAddViewController.swift diff --git a/DDANZI_iOS/DDANZI_iOS.xcodeproj/project.pbxproj b/DDANZI_iOS/DDANZI_iOS.xcodeproj/project.pbxproj index 72d014a..4ab9f43 100644 --- a/DDANZI_iOS/DDANZI_iOS.xcodeproj/project.pbxproj +++ b/DDANZI_iOS/DDANZI_iOS.xcodeproj/project.pbxproj @@ -72,6 +72,10 @@ 363F1A102C9B10BA007527E2 /* LogoutDTO.swift in Sources */ = {isa = PBXBuildFile; fileRef = 363F1A0F2C9B10BA007527E2 /* LogoutDTO.swift */; }; 363F1A122C9B1638007527E2 /* UserAccountDTO.swift in Sources */ = {isa = PBXBuildFile; fileRef = 363F1A112C9B1638007527E2 /* UserAccountDTO.swift */; }; 363F1A182C9CA04F007527E2 /* Amplitude in Frameworks */ = {isa = PBXBuildFile; productRef = 363F1A172C9CA04F007527E2 /* Amplitude */; }; + 363F1A1A2C9EE9EB007527E2 /* AccountAddViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 363F1A192C9EE9EB007527E2 /* AccountAddViewController.swift */; }; + 363F1A1C2C9EF029007527E2 /* AccountAddCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 363F1A1B2C9EF029007527E2 /* AccountAddCell.swift */; }; + 363F1A1E2C9F072F007527E2 /* UserAccountRequestDTO.swift in Sources */ = {isa = PBXBuildFile; fileRef = 363F1A1D2C9F072F007527E2 /* UserAccountRequestDTO.swift */; }; + 363F1A252C9F1BE2007527E2 /* BankList.swift in Sources */ = {isa = PBXBuildFile; fileRef = 363F1A242C9F1BE2007527E2 /* BankList.swift */; }; 3648954E2C6281BB00AAA8E2 /* HomeItemsResponseDTO.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3648954D2C6281BB00AAA8E2 /* HomeItemsResponseDTO.swift */; }; 364895502C62822200AAA8E2 /* ProductDetailResponseDTO.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3648954F2C62822200AAA8E2 /* ProductDetailResponseDTO.swift */; }; 364895522C62826200AAA8E2 /* SearchItemsResponseDTO.swift in Sources */ = {isa = PBXBuildFile; fileRef = 364895512C62826200AAA8E2 /* SearchItemsResponseDTO.swift */; }; @@ -306,6 +310,10 @@ 363F1A0D2C9B10AF007527E2 /* WithDrawDTO.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WithDrawDTO.swift; sourceTree = ""; }; 363F1A0F2C9B10BA007527E2 /* LogoutDTO.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LogoutDTO.swift; sourceTree = ""; }; 363F1A112C9B1638007527E2 /* UserAccountDTO.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserAccountDTO.swift; sourceTree = ""; }; + 363F1A192C9EE9EB007527E2 /* AccountAddViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccountAddViewController.swift; sourceTree = ""; }; + 363F1A1B2C9EF029007527E2 /* AccountAddCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccountAddCell.swift; sourceTree = ""; }; + 363F1A1D2C9F072F007527E2 /* UserAccountRequestDTO.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserAccountRequestDTO.swift; sourceTree = ""; }; + 363F1A242C9F1BE2007527E2 /* BankList.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BankList.swift; sourceTree = ""; }; 3648954D2C6281BB00AAA8E2 /* HomeItemsResponseDTO.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeItemsResponseDTO.swift; sourceTree = ""; }; 3648954F2C62822200AAA8E2 /* ProductDetailResponseDTO.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProductDetailResponseDTO.swift; sourceTree = ""; }; 364895512C62826200AAA8E2 /* SearchItemsResponseDTO.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchItemsResponseDTO.swift; sourceTree = ""; }; @@ -538,6 +546,7 @@ 3631528A2C3D120400DF689E /* PurchaseSectionModel.swift */, 363C24202C6512E60097FCB7 /* UserInfoModel.swift */, 363C242C2C6529500097FCB7 /* UserAddressModel.swift */, + 363F1A242C9F1BE2007527E2 /* BankList.swift */, ); path = Model; sourceTree = ""; @@ -653,6 +662,7 @@ 3648955D2C6284D000AAA8E2 /* UserSaleResponseDTO.swift */, 3648955F2C62850200AAA8E2 /* UserInterestResponesDTO.swift */, 363F1A112C9B1638007527E2 /* UserAccountDTO.swift */, + 363F1A1D2C9F072F007527E2 /* UserAccountRequestDTO.swift */, ); path = Mypage; sourceTree = ""; @@ -764,6 +774,8 @@ 36542E802C308ED000D5BFEB /* BankAccountViewController.swift */, 363152F22C44F8BE00DF689E /* AddressSettingViewController.swift */, 36BE65B02C4510FE00CD4511 /* AccountViewController.swift */, + 363F1A192C9EE9EB007527E2 /* AccountAddViewController.swift */, + 363F1A1B2C9EF029007527E2 /* AccountAddCell.swift */, 363C242E2C6537840097FCB7 /* KakaoPostCodeViewController.swift */, ); path = Info; @@ -1543,6 +1555,7 @@ 368E36842C4936AB003FA911 /* APIConstants.swift in Sources */, 363C24332C6607080097FCB7 /* HomeRepository.swift in Sources */, 369C63E52C1A95280021E2E0 /* UIButton+.swift in Sources */, + 363F1A1C2C9EF029007527E2 /* AccountAddCell.swift in Sources */, 3648954E2C6281BB00AAA8E2 /* HomeItemsResponseDTO.swift in Sources */, 36BE65C62C4591F500CD4511 /* PurchaseHeaderView.swift in Sources */, 362864D72C8EBEAB00029452 /* ItemEndpoint.swift in Sources */, @@ -1554,6 +1567,7 @@ 363152F12C44F80900DF689E /* SalesDetailViewController.swift in Sources */, 363C242F2C6537840097FCB7 /* KakaoPostCodeViewController.swift in Sources */, 363C242D2C6529500097FCB7 /* UserAddressModel.swift in Sources */, + 363F1A1E2C9F072F007527E2 /* UserAccountRequestDTO.swift in Sources */, 36BE65C22C458FA600CD4511 /* TermsTableViewCell.swift in Sources */, 363152AB2C3DC57800DF689E /* PurchaseModel.swift in Sources */, 36B745052C6C5AC2002892C4 /* UserDefaltManager.swift in Sources */, @@ -1643,6 +1657,7 @@ 36EB5FA82C1ED6B600FAF995 /* ProductModel.swift in Sources */, 363152A52C3DBE9500DF689E /* TotalPriceFooterView.swift in Sources */, 368833AA2C20A9B7000F3A45 /* String.swift in Sources */, + 363F1A252C9F1BE2007527E2 /* BankList.swift in Sources */, 363152902C3DB37000DF689E /* PurchaseDetailViewController.swift in Sources */, 36774A682C466E4000F32637 /* CompleteCollectionViewCell.swift in Sources */, 36B833EE2C5CDCFB009C2C3E /* HomeEndpoint.swift in Sources */, @@ -1652,6 +1667,7 @@ 36EB5FA52C1ECDED00FAF995 /* String+.swift in Sources */, 362864CA2C8E985400029452 /* LandingViewController.swift in Sources */, 36542E792C2E892500D5BFEB /* CsCenterViewController.swift in Sources */, + 363F1A1A2C9EE9EB007527E2 /* AccountAddViewController.swift in Sources */, 363152A12C3DBA0B00DF689E /* InfoCollectionViewCell.swift in Sources */, 363C24292C6520DD0097FCB7 /* DdanziChipButton.swift in Sources */, 362864E52C8EDE6700029452 /* RegisteItemDTO.swift in Sources */, diff --git a/DDANZI_iOS/DDANZI_iOS/Data/DTO/Mypage/UserAccountRequestDTO.swift b/DDANZI_iOS/DDANZI_iOS/Data/DTO/Mypage/UserAccountRequestDTO.swift new file mode 100644 index 0000000..8202353 --- /dev/null +++ b/DDANZI_iOS/DDANZI_iOS/Data/DTO/Mypage/UserAccountRequestDTO.swift @@ -0,0 +1,8 @@ +// +// UserAccountRequestDTO.swift +// DDANZI_iOS +// +// Created by 이지희 on 9/21/24. +// + +import Foundation diff --git a/DDANZI_iOS/DDANZI_iOS/Presentation/Mypage/Model/BankList.swift b/DDANZI_iOS/DDANZI_iOS/Presentation/Mypage/Model/BankList.swift new file mode 100644 index 0000000..6b76989 --- /dev/null +++ b/DDANZI_iOS/DDANZI_iOS/Presentation/Mypage/Model/BankList.swift @@ -0,0 +1,8 @@ +// +// BankList.swift +// DDANZI_iOS +// +// Created by 이지희 on 9/22/24. +// + +import Foundation diff --git a/DDANZI_iOS/DDANZI_iOS/Presentation/Mypage/View/Info/AccountAddCell.swift b/DDANZI_iOS/DDANZI_iOS/Presentation/Mypage/View/Info/AccountAddCell.swift new file mode 100644 index 0000000..933dc76 --- /dev/null +++ b/DDANZI_iOS/DDANZI_iOS/Presentation/Mypage/View/Info/AccountAddCell.swift @@ -0,0 +1,8 @@ +// +// AccountTableViewCell.swift +// DDANZI_iOS +// +// Created by 이지희 on 9/21/24. +// + +import Foundation diff --git a/DDANZI_iOS/DDANZI_iOS/Presentation/Mypage/View/Info/AccountAddViewController.swift b/DDANZI_iOS/DDANZI_iOS/Presentation/Mypage/View/Info/AccountAddViewController.swift new file mode 100644 index 0000000..a19a4cb --- /dev/null +++ b/DDANZI_iOS/DDANZI_iOS/Presentation/Mypage/View/Info/AccountAddViewController.swift @@ -0,0 +1,8 @@ +// +// AccountAddViewController.swift +// DDANZI_iOS +// +// Created by 이지희 on 9/21/24. +// + +import Foundation From 2e10f3e17031d383fd2501585d2b9357bc4a83ea Mon Sep 17 00:00:00 2001 From: Zoe Date: Sun, 22 Sep 2024 04:09:51 +0900 Subject: [PATCH 02/20] =?UTF-8?q?[Feat/#42]=20=EA=B3=84=EC=A2=8C=EB=93=B1?= =?UTF-8?q?=EB=A1=9D=20DTO?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../DDANZI_iOS/Data/DTO/Mypage/UserAccountRequestDTO.swift | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/DDANZI_iOS/DDANZI_iOS/Data/DTO/Mypage/UserAccountRequestDTO.swift b/DDANZI_iOS/DDANZI_iOS/Data/DTO/Mypage/UserAccountRequestDTO.swift index 8202353..54e8e19 100644 --- a/DDANZI_iOS/DDANZI_iOS/Data/DTO/Mypage/UserAccountRequestDTO.swift +++ b/DDANZI_iOS/DDANZI_iOS/Data/DTO/Mypage/UserAccountRequestDTO.swift @@ -6,3 +6,9 @@ // import Foundation + +struct UserAccountRequestDTO: Codable { + let acountName: String + let bank: String + let accountNumber: String +} From 8e56049feecde8225c025a035aa6a00ab6cc91a9 Mon Sep 17 00:00:00 2001 From: Zoe Date: Sun, 22 Sep 2024 04:11:00 +0900 Subject: [PATCH 03/20] =?UTF-8?q?[Feat/#42]=20=EC=A3=BC=EC=86=8C=20?= =?UTF-8?q?=EB=93=B1=EB=A1=9D=20=EC=88=98=EC=A0=95=20=EC=82=AC=ED=95=AD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../DTO/Setting/UserAddressResponseDTO.swift | 6 ++--- .../View/Info/AddressFormViewController.swift | 2 +- .../Info/AddressSettingViewController.swift | 24 ++++++++++++------- 3 files changed, 19 insertions(+), 13 deletions(-) diff --git a/DDANZI_iOS/DDANZI_iOS/Data/DTO/Setting/UserAddressResponseDTO.swift b/DDANZI_iOS/DDANZI_iOS/Data/DTO/Setting/UserAddressResponseDTO.swift index 44fcd77..fbac4ce 100644 --- a/DDANZI_iOS/DDANZI_iOS/Data/DTO/Setting/UserAddressResponseDTO.swift +++ b/DDANZI_iOS/DDANZI_iOS/Data/DTO/Setting/UserAddressResponseDTO.swift @@ -11,9 +11,9 @@ import Foundation struct UserAddressResponseDTO: Codable { let addressID: Int? let recipient: String? - let zipCode: String - let type: AddressType - let address, detailAddress, recipientPhone: String + let zipCode: String? + let type: AddressType? + let address, detailAddress, recipientPhone: String? enum CodingKeys: String, CodingKey { case addressID = "addressId" diff --git a/DDANZI_iOS/DDANZI_iOS/Presentation/Mypage/View/Info/AddressFormViewController.swift b/DDANZI_iOS/DDANZI_iOS/Presentation/Mypage/View/Info/AddressFormViewController.swift index 4e533e2..7ce0cf5 100644 --- a/DDANZI_iOS/DDANZI_iOS/Presentation/Mypage/View/Info/AddressFormViewController.swift +++ b/DDANZI_iOS/DDANZI_iOS/Presentation/Mypage/View/Info/AddressFormViewController.swift @@ -32,7 +32,7 @@ final class AddressFormViewController: UIViewController { $0.rowHeight = 75 $0.separatorStyle = .none $0.scrollsToTop = false - $0.contentInset = .init(top: 30, left: 0, bottom: 0, right: 0) + $0.contentInset = .init(top: 10, left: 0, bottom: 0, right: 0) } private let headerView = MyPageSectionHeaderView().then { $0.setTitleLabel(title: "배송지 등록") diff --git a/DDANZI_iOS/DDANZI_iOS/Presentation/Mypage/View/Info/AddressSettingViewController.swift b/DDANZI_iOS/DDANZI_iOS/Presentation/Mypage/View/Info/AddressSettingViewController.swift index 7434a0b..b9816e0 100644 --- a/DDANZI_iOS/DDANZI_iOS/Presentation/Mypage/View/Info/AddressSettingViewController.swift +++ b/DDANZI_iOS/DDANZI_iOS/Presentation/Mypage/View/Info/AddressSettingViewController.swift @@ -145,15 +145,21 @@ class AddressSettingViewController: UIViewController { Providers.MypageProvider.request(target: .fetchUserAddress, instance: BaseResponse.self) { result in guard let data = result.data else { return } - let newAddress = Address(name: data.recipient ?? "", - address: "(\(data.zipCode) \(data.address), \(data.detailAddress))", - phone: data.recipientPhone) - - var currentList = (try? self.addressListSubject.value()) ?? [] - currentList.append(newAddress) - self.addressId = data.addressID ?? 0 - - self.addressListSubject.onNext(currentList) + if let name = data.recipient, + let zipcode = data.zipCode, + let address = data.address, + let detailAddress = data.detailAddress, + let phone = data.recipientPhone { + let newAddress = Address(name: name, + address: "(\(zipcode) \(address), \(detailAddress))", + phone: phone) + + var currentList = (try? self.addressListSubject.value()) ?? [] + currentList.append(newAddress) + + self.addressId = data.addressID ?? 0 + self.addressListSubject.onNext(currentList) + } } } From 00fe4e5b9aae2addd29e1bed5c189b23d15fbe94 Mon Sep 17 00:00:00 2001 From: Zoe Date: Sun, 22 Sep 2024 04:11:28 +0900 Subject: [PATCH 04/20] =?UTF-8?q?[Chore/#42]=20=EC=9E=90=EC=9E=98=ED=95=9C?= =?UTF-8?q?=20=EC=98=A4=EB=A5=98=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../CustomNavigationBarView.swift | 2 +- .../HelperView/MyPageSectionHeaderView.swift | 90 +++++++++---------- 2 files changed, 46 insertions(+), 46 deletions(-) diff --git a/DDANZI_iOS/DDANZI_iOS/Presentation/Common/NavigationBar/CustomNavigationBarView.swift b/DDANZI_iOS/DDANZI_iOS/Presentation/Common/NavigationBar/CustomNavigationBarView.swift index 5fd51d6..898ac1f 100644 --- a/DDANZI_iOS/DDANZI_iOS/Presentation/Common/NavigationBar/CustomNavigationBarView.swift +++ b/DDANZI_iOS/DDANZI_iOS/Presentation/Common/NavigationBar/CustomNavigationBarView.swift @@ -49,7 +49,7 @@ final class CustomNavigationBarView: UIView { // MARK: - componenets private var leftView = UIView(frame: .init(x: 0, y: 0, width: 25, height: 25)) - private var subView = UIView(frame: .init(x: 0, y: 0, width: 25, height: 25)) + private var subView = UIView(frame: .init(x: 0, y: 0, width: 25, height: 25)) private var rightView = UIView(frame: .init(x: 0, y: 0, width: 25, height: 25)) private let titleLabel = UILabel().then { diff --git a/DDANZI_iOS/DDANZI_iOS/Presentation/Mypage/View/MyPage/HelperView/MyPageSectionHeaderView.swift b/DDANZI_iOS/DDANZI_iOS/Presentation/Mypage/View/MyPage/HelperView/MyPageSectionHeaderView.swift index 1f8e505..bfee0dc 100644 --- a/DDANZI_iOS/DDANZI_iOS/Presentation/Mypage/View/MyPage/HelperView/MyPageSectionHeaderView.swift +++ b/DDANZI_iOS/DDANZI_iOS/Presentation/Mypage/View/MyPage/HelperView/MyPageSectionHeaderView.swift @@ -11,50 +11,50 @@ import SnapKit import Then final class MyPageSectionHeaderView: UIView { - - private let titleLabel = UILabel().then { - $0.textColor = .black - $0.font = .body2Sb20 - } - - private let lineView = UIView().then { - $0.backgroundColor = .black - } - - init() { - super.init(frame: .zero) - setUI() - } - - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - private func setUI() { - self.backgroundColor = .white - setHierarchy() - setConstraints() - } - - private func setHierarchy() { - self.addSubviews(titleLabel, lineView) - } - - private func setConstraints() { - titleLabel.snp.makeConstraints { - $0.centerY.equalToSuperview() - $0.leading.equalToSuperview().offset(20) - } - - lineView.snp.makeConstraints { - $0.height.equalTo(1) - $0.top.equalTo(titleLabel.snp.bottom).offset(5) - $0.leading.trailing.equalToSuperview().inset(20) - } - } - - func setTitleLabel(title: String){ - titleLabel.text = title - } + + private let titleLabel = UILabel().then { + $0.textColor = .black + $0.font = .body2Sb20 + } + + private let lineView = UIView().then { + $0.backgroundColor = .black + } + + init() { + super.init(frame: .zero) + setUI() + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + private func setUI() { + self.backgroundColor = .white + setHierarchy() + setConstraints() + } + + private func setHierarchy() { + self.addSubviews(titleLabel, lineView) + } + + private func setConstraints() { + titleLabel.snp.makeConstraints { + $0.centerY.equalToSuperview() + $0.leading.equalToSuperview().offset(20) + } + + lineView.snp.makeConstraints { + $0.height.equalTo(1) + $0.top.equalTo(titleLabel.snp.bottom).offset(5) + $0.leading.trailing.equalToSuperview().inset(20) + } + } + + func setTitleLabel(title: String){ + titleLabel.text = title + } } From c8892ec19873c75373032896858cacec7d501d96 Mon Sep 17 00:00:00 2001 From: Zoe Date: Sun, 22 Sep 2024 04:11:52 +0900 Subject: [PATCH 05/20] =?UTF-8?q?[Feat/#42]=20=EA=B3=84=EC=A2=8C=20?= =?UTF-8?q?=EB=93=B1=EB=A1=9D=20=EB=B2=84=ED=8A=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../View/Info/BankAccountViewController.swift | 54 ++++++++++++++++--- 1 file changed, 48 insertions(+), 6 deletions(-) diff --git a/DDANZI_iOS/DDANZI_iOS/Presentation/Mypage/View/Info/BankAccountViewController.swift b/DDANZI_iOS/DDANZI_iOS/Presentation/Mypage/View/Info/BankAccountViewController.swift index 985efb0..100b4e0 100644 --- a/DDANZI_iOS/DDANZI_iOS/Presentation/Mypage/View/Info/BankAccountViewController.swift +++ b/DDANZI_iOS/DDANZI_iOS/Presentation/Mypage/View/Info/BankAccountViewController.swift @@ -17,10 +17,22 @@ class BankAccountViewController: UIViewController { private let navigationBarView = CustomNavigationBarView(navigationBarType: .normal) private let headerView = MyPageSectionHeaderView() + + private let registerButton = UIButton().then { + $0.backgroundColor = .white + $0.makeBorder(width: 1, color: .gray2) + $0.setTitleColor(.black, for: .normal) + $0.setTitle("+ 계좌 등록", for: .normal) + $0.titleLabel?.font = .body4R16 + $0.makeCornerRound(radius: 10) + $0.isHidden = true // 초기 상태는 숨김 + } + private let accountButton = UIButton().then { $0.backgroundColor = .white $0.makeCornerRound(radius: 10) $0.makeBorder(width: 1, color: .gray2) + $0.isHidden = true // 초기 상태는 숨김 } private let stackView = UIStackView().then { @@ -70,10 +82,11 @@ class BankAccountViewController: UIViewController { private func setHierarchy() { view.addSubviews(navigationBarView, headerView, - accountButton) + accountButton, + registerButton) accountButton.addSubviews(stackView, - detailButton) + detailButton) stackView.addArrangedSubviews(bankNameLabel, innerStackView) @@ -99,6 +112,12 @@ class BankAccountViewController: UIViewController { $0.height.equalTo(100) } + registerButton.snp.makeConstraints { + $0.top.equalTo(headerView.snp.bottom).offset(19) + $0.leading.trailing.equalToSuperview().inset(20) + $0.height.equalTo(100) + } + stackView.snp.makeConstraints { $0.centerY.equalToSuperview() $0.leading.equalToSuperview().offset(18) @@ -114,10 +133,19 @@ class BankAccountViewController: UIViewController { func fetchAccountInfo() { Providers.MypageProvider.request(target: .fetchUserAccount, instance: BaseResponse.self) { response in guard let data = response.data else { return } - - self.bankNameLabel.text = data.bank ?? "" - self.nameLabel.text = data.name - self.accountNumberLabel.text = data.accountNumber ?? "" + if let bank = data.bank, + let accountNumber = data.accountNumber, + let accountId = data.accountId { + self.bankNameLabel.text = bank + self.nameLabel.text = data.name + self.accountNumberLabel.text = accountNumber + self.accountButton.isHidden = false + self.registerButton.isHidden = true // 계좌 정보가 있으면 등록 버튼을 숨김 + } else { + // 계좌 정보가 없으면 등록 버튼을 보이고 계좌 정보 버튼을 숨김 + self.accountButton.isHidden = true + self.registerButton.isHidden = false + } } } @@ -127,5 +155,19 @@ class BankAccountViewController: UIViewController { self?.navigationController?.popViewController(animated: true) }) .disposed(by: disposeBag) + + registerButton.rx.tap + .subscribe(onNext: { [weak self] in + // 계좌 등록 화면으로 이동하는 로직 추가 + self?.navigateToAccountRegistration() + }) + .disposed(by: disposeBag) + } + + // 계좌 등록 화면으로 이동하는 함수 + private func navigateToAccountRegistration() { + // 계좌 등록 화면 이동 로직을 구현 + let accountRegistrationVC = AccountAddViewController() + self.navigationController?.pushViewController(accountRegistrationVC, animated: true) } } From c1afcb5f9c45c0e50d4a6a475c4b3acba25b4312 Mon Sep 17 00:00:00 2001 From: Zoe Date: Sun, 22 Sep 2024 04:12:16 +0900 Subject: [PATCH 06/20] =?UTF-8?q?[Feat/#42]=20=EA=B3=84=EC=A2=8C=20?= =?UTF-8?q?=EB=93=B1=EB=A1=9D=EB=B7=B0=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Presentation/Mypage/Model/BankList.swift | 72 +++++++ .../Mypage/View/Info/AccountAddCell.swift | 73 ++++++- .../View/Info/AccountAddViewController.swift | 199 +++++++++++++++++- 3 files changed, 341 insertions(+), 3 deletions(-) diff --git a/DDANZI_iOS/DDANZI_iOS/Presentation/Mypage/Model/BankList.swift b/DDANZI_iOS/DDANZI_iOS/Presentation/Mypage/Model/BankList.swift index 6b76989..3b76dd9 100644 --- a/DDANZI_iOS/DDANZI_iOS/Presentation/Mypage/Model/BankList.swift +++ b/DDANZI_iOS/DDANZI_iOS/Presentation/Mypage/Model/BankList.swift @@ -6,3 +6,75 @@ // import Foundation +struct Bank { + let code: String + let name: String +} + +struct BankList { + static let banks: [Bank] = [ + Bank(code: "001", name: "한국은행"), + Bank(code: "002", name: "산업은행"), + Bank(code: "003", name: "기업은행"), + Bank(code: "004", name: "국민은행"), + Bank(code: "005", name: "외환은행"), + Bank(code: "007", name: "수협중앙회"), + Bank(code: "008", name: "수출입은행"), + Bank(code: "011", name: "농협은행"), + Bank(code: "012", name: "농협회원조합"), + Bank(code: "020", name: "우리은행"), + Bank(code: "023", name: "SC제일은행"), + Bank(code: "027", name: "한국씨티은행"), + Bank(code: "031", name: "대구은행"), + Bank(code: "032", name: "부산은행"), + Bank(code: "034", name: "광주은행"), + Bank(code: "035", name: "제주은행"), + Bank(code: "037", name: "전북은행"), + Bank(code: "039", name: "경남은행"), + Bank(code: "045", name: "새마을금고연합회"), + Bank(code: "048", name: "신협중앙회"), + Bank(code: "050", name: "상호저축은행"), + Bank(code: "052", name: "모건스탠리은행"), + Bank(code: "054", name: "HSBC은행"), + Bank(code: "055", name: "도이치은행"), + Bank(code: "056", name: "에이비엔암로은행"), + Bank(code: "057", name: "제이피모간체이스은행"), + Bank(code: "058", name: "미즈호코퍼레이트은행"), + Bank(code: "059", name: "미쓰비시도쿄UFJ은행"), + Bank(code: "060", name: "BOA"), + Bank(code: "071", name: "정보통신부 우체국"), + Bank(code: "076", name: "신용보증기금"), + Bank(code: "077", name: "기술신용보증기금"), + Bank(code: "081", name: "하나은행"), + Bank(code: "088", name: "신한은행"), + Bank(code: "093", name: "한국주택금융공사"), + Bank(code: "094", name: "서울보증보험"), + Bank(code: "095", name: "경찰청"), + Bank(code: "099", name: "금융결제원"), + Bank(code: "209", name: "동양종합금융증권"), + Bank(code: "218", name: "현대증권"), + Bank(code: "230", name: "미래에셋증권"), + Bank(code: "238", name: "대우증권"), + Bank(code: "240", name: "삼성증권"), + Bank(code: "243", name: "한국투자증권"), + Bank(code: "247", name: "우리투자증권"), + Bank(code: "261", name: "교보증권"), + Bank(code: "262", name: "하이투자증권"), + Bank(code: "263", name: "에이치엠씨투자증권"), + Bank(code: "264", name: "키움증권"), + Bank(code: "265", name: "이트레이드증권"), + Bank(code: "266", name: "에스케이증권"), + Bank(code: "267", name: "대신증권"), + Bank(code: "268", name: "솔로몬투자증권"), + Bank(code: "269", name: "한화투자증권"), + Bank(code: "270", name: "하나대투증권"), + Bank(code: "278", name: "굿모닝신한증권"), + Bank(code: "279", name: "동부증권"), + Bank(code: "280", name: "유진투자증권"), + Bank(code: "287", name: "메리츠증권"), + Bank(code: "289", name: "엔에이치투자증권"), + Bank(code: "290", name: "부국증권"), + Bank(code: "291", name: "신영증권"), + Bank(code: "292", name: "엘아이지투자증권") + ] +} diff --git a/DDANZI_iOS/DDANZI_iOS/Presentation/Mypage/View/Info/AccountAddCell.swift b/DDANZI_iOS/DDANZI_iOS/Presentation/Mypage/View/Info/AccountAddCell.swift index 933dc76..fa2a4e0 100644 --- a/DDANZI_iOS/DDANZI_iOS/Presentation/Mypage/View/Info/AccountAddCell.swift +++ b/DDANZI_iOS/DDANZI_iOS/Presentation/Mypage/View/Info/AccountAddCell.swift @@ -1,8 +1,77 @@ // -// AccountTableViewCell.swift +// AccountAddCell.swift // DDANZI_iOS // // Created by 이지희 on 9/21/24. // -import Foundation +import UIKit + +import Then +import SnapKit +import RxSwift + +final class AccountAddCell: UITableViewCell { + + let disposeBag = DisposeBag() + + private let titleLabel = UILabel().then { + $0.font = .body2Sb18 + $0.textColor = .black + } + let textField = UITextField().then { + $0.font = .body4R16 + } + private let lineView = UIView().then { + $0.backgroundColor = .black + } + + override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { + super.init(style: style, reuseIdentifier: reuseIdentifier) + setUI() + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + override func prepareForReuse() { + super.prepareForReuse() + textField.text = "" + textField.isUserInteractionEnabled = true + } + + func configureCell(title: String, placeHolder: String, isEditable: Bool) { + titleLabel.text = title + textField.placeholder = placeHolder + textField.isUserInteractionEnabled = isEditable + } + + private func setUI() { + self.selectionStyle = .none + setHierarchy() + setConstraints() + } + + private func setHierarchy() { + addSubviews(titleLabel, textField, lineView) + } + + private func setConstraints() { + titleLabel.snp.makeConstraints { + $0.leading.equalToSuperview().offset(20) + $0.top.equalToSuperview().offset(7) + } + + textField.snp.makeConstraints { + $0.top.equalTo(titleLabel.snp.bottom).offset(10) + $0.leading.trailing.equalToSuperview().inset(20) + } + + lineView.snp.makeConstraints { + $0.height.equalTo(1) + $0.leading.trailing.equalToSuperview().inset(20) + $0.bottom.equalToSuperview().inset(7) + } + } +} diff --git a/DDANZI_iOS/DDANZI_iOS/Presentation/Mypage/View/Info/AccountAddViewController.swift b/DDANZI_iOS/DDANZI_iOS/Presentation/Mypage/View/Info/AccountAddViewController.swift index a19a4cb..0f9d120 100644 --- a/DDANZI_iOS/DDANZI_iOS/Presentation/Mypage/View/Info/AccountAddViewController.swift +++ b/DDANZI_iOS/DDANZI_iOS/Presentation/Mypage/View/Info/AccountAddViewController.swift @@ -5,4 +5,201 @@ // Created by 이지희 on 9/21/24. // -import Foundation +import UIKit + +import Then +import SnapKit + +import RxSwift +import RxCocoa +import RxDataSources +import RxGesture + +final class AccountAddViewController: UIViewController { + + // MARK: Property + private let titles = ["이름", "은행", "계좌번호"] + private var userName = UserDefaults.standard.string(forKey: "name") ?? "사용자" + + private let disposeBag = DisposeBag() + + private var selectedBankCode: String? + private lazy var nameSubject = BehaviorSubject(value: userName) + private let bankSubject = BehaviorSubject(value: "") + private let accountNumberSubject = BehaviorSubject(value: "") + + // MARK: UI + private let navigationView = CustomNavigationBarView(navigationBarType: .normal) + private let headerView = MyPageSectionHeaderView().then { + $0.setTitleLabel(title: "계좌 등록") + } + private let tableView = UITableView(frame: .zero, style: .plain).then { + $0.rowHeight = 75 + $0.register(AccountAddCell.self, forCellReuseIdentifier: AccountAddCell.className) + $0.separatorStyle = .none + $0.isScrollEnabled = false + } + private let conformButton = DdanziButton(title: "입력 완료", enable: false) + + // MARK: LifeCycle + override func viewDidLoad() { + super.viewDidLoad() + userName = maskMiddleCharacters(of: userName) // 이름 중간 글자 마스킹 처리 + setUI() + bind() + setupDismissKeyboardGesture() + } + + private func setUI() { + self.view.backgroundColor = .white + setHierarchy() + setConstraints() + } + + private func setHierarchy() { + view.addSubviews(navigationView, headerView, tableView, conformButton) + } + + private func setConstraints() { + navigationView.snp.makeConstraints { + $0.top.equalTo(view.safeAreaLayoutGuide) + $0.leading.trailing.equalToSuperview() + } + + headerView.snp.makeConstraints { + $0.top.equalTo(navigationView.snp.bottom) + $0.leading.trailing.equalToSuperview() + $0.height.equalTo(48) + } + + tableView.snp.makeConstraints { + $0.top.equalTo(headerView.snp.bottom) + $0.leading.trailing.bottom.equalToSuperview() + } + + conformButton.snp.makeConstraints { + $0.height.equalTo(52.adjusted) + $0.leading.trailing.equalToSuperview().inset(20.adjusted) + $0.bottom.equalToSuperview().inset(58.adjusted) + } + } + + private func bind() { + tableView.delegate = self + tableView.dataSource = self + // 모든 필드가 채워졌을 때 버튼 활성화 + Observable.combineLatest(nameSubject, bankSubject, accountNumberSubject) + .map { !$0.0.isEmpty && !$0.1.isEmpty && !$0.2.isEmpty } + .bind(with: self, onNext: { owner, isEnable in + if isEnable { owner.conformButton.setEnable() } + }) + .disposed(by: disposeBag) + + conformButton.rx.tap + .subscribe(with: self) { owner, _ in + // 등록 버튼 눌렀을 때의 처리 + let accountName = try? owner.nameSubject.value() + let bank = try? owner.bankSubject.value() + let accountNumber = try? owner.accountNumberSubject.value() + + owner.conformAccount(accountName: accountName ?? "", bank: bank ?? "", accountNumber: accountNumber ?? "") + } + .disposed(by: disposeBag) + } + + + func showBankSelection() { + let alert = UIAlertController(title: "은행 선택", message: nil, preferredStyle: .actionSheet) + + for bank in BankList.banks { + let action = UIAlertAction(title: bank.name, style: .default) { _ in + // 은행 선택 시 코드 저장 + self.selectedBankCode = bank.code + self.bankSubject.onNext(bank.name) + } + alert.addAction(action) + } + + let cancel = UIAlertAction(title: "취소", style: .cancel, handler: nil) + alert.addAction(cancel) + + present(alert, animated: true, completion: nil) + } + + private func maskMiddleCharacters(of name: String) -> String { + guard name.count >= 2 else { return name } + let middleIndex = name.index(name.startIndex, offsetBy: name.count / 2) + return name.replacingCharacters(in: middleIndex...middleIndex, with: "*") + } + + private func conformAccount(accountName: String, bank: String, accountNumber: String) { + let body = UserAccountRequestDTO(acountName: accountName, bank: bank, accountNumber: accountNumber) + Providers.MypageProvider.request(target: .addUserAccount(body), instance: BaseResponse.self) { response in + guard let data = response.data else { return } + if response.status != 200 || response.status != 201 { + self.view.showToast(message: "계좌 등록 오류 입니다. 잠시 후 다시 시도해주세요", at: 100) + } else { + self.navigationController?.popViewController(animated: true) + } + } + } + + private func setupDismissKeyboardGesture() { + let tapGesture = UITapGestureRecognizer(target: self, action: #selector(dismissKeyboard)) + tapGesture.cancelsTouchesInView = false // 터치 이벤트가 다른 뷰로 전파되도록 설정 + view.addGestureRecognizer(tapGesture) + } + + @objc private func dismissKeyboard() { + view.endEditing(true) + } +} + +extension AccountAddViewController: UITableViewDataSource { + func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { + return 3 + } + + func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { + let cell = tableView.dequeueReusableCell(withIdentifier: AccountAddCell.className, for: indexPath) as! AccountAddCell + switch indexPath.row { + case 0: + cell.configureCell(title: self.titles[0], placeHolder: self.userName, isEditable: false) + cell.textField.text = self.userName + case 1: + cell.configureCell(title: self.titles[1], placeHolder: "은행을 선택해주세요", isEditable: false) + self.bankSubject + .bind(to: cell.textField.rx.text) + .disposed(by: cell.disposeBag) + case 2: + cell.configureCell(title: self.titles[2], placeHolder: "-를 제외한 계좌번호를 작성해주세요", isEditable: true) + // 계좌번호 입력 값을 accountNumberSubject에 바인딩 + cell.textField.rx.text.orEmpty + .bind(to: self.accountNumberSubject) + .disposed(by: cell.disposeBag) + + cell.textField.delegate = self + default: + break + } + return cell + } +} + +extension AccountAddViewController: UITableViewDelegate { + func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { + if indexPath.row == 1 { + self.showBankSelection() + } else if indexPath.row == 2 { + let cell = tableView.cellForRow(at: indexPath) as? AccountAddCell + cell?.textField.becomeFirstResponder() // 포커스 설정 + } + } +} + +extension AccountAddViewController: UITextFieldDelegate { + func textFieldShouldReturn(_ textField: UITextField) -> Bool { + textField.resignFirstResponder() + return true + } +} From 135c39344704c9d5a94699dc16333394c3196ee0 Mon Sep 17 00:00:00 2001 From: Zoe Date: Sun, 22 Sep 2024 04:12:40 +0900 Subject: [PATCH 07/20] =?UTF-8?q?[Add/#42]=20RxGesture=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- DDANZI_iOS/DDANZI_iOS.xcodeproj/project.pbxproj | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/DDANZI_iOS/DDANZI_iOS.xcodeproj/project.pbxproj b/DDANZI_iOS/DDANZI_iOS.xcodeproj/project.pbxproj index 4ab9f43..ebe356e 100644 --- a/DDANZI_iOS/DDANZI_iOS.xcodeproj/project.pbxproj +++ b/DDANZI_iOS/DDANZI_iOS.xcodeproj/project.pbxproj @@ -75,6 +75,7 @@ 363F1A1A2C9EE9EB007527E2 /* AccountAddViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 363F1A192C9EE9EB007527E2 /* AccountAddViewController.swift */; }; 363F1A1C2C9EF029007527E2 /* AccountAddCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 363F1A1B2C9EF029007527E2 /* AccountAddCell.swift */; }; 363F1A1E2C9F072F007527E2 /* UserAccountRequestDTO.swift in Sources */ = {isa = PBXBuildFile; fileRef = 363F1A1D2C9F072F007527E2 /* UserAccountRequestDTO.swift */; }; + 363F1A232C9F15EB007527E2 /* RxGesture in Frameworks */ = {isa = PBXBuildFile; productRef = 363F1A222C9F15EB007527E2 /* RxGesture */; }; 363F1A252C9F1BE2007527E2 /* BankList.swift in Sources */ = {isa = PBXBuildFile; fileRef = 363F1A242C9F1BE2007527E2 /* BankList.swift */; }; 3648954E2C6281BB00AAA8E2 /* HomeItemsResponseDTO.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3648954D2C6281BB00AAA8E2 /* HomeItemsResponseDTO.swift */; }; 364895502C62822200AAA8E2 /* ProductDetailResponseDTO.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3648954F2C62822200AAA8E2 /* ProductDetailResponseDTO.swift */; }; @@ -472,6 +473,7 @@ 36B744F92C6C50D3002892C4 /* RxKakaoSDKCommon in Frameworks */, 36B744F22C6C4CD2002892C4 /* KakaoSDKCommon in Frameworks */, 3664CFDA2C6E2179007FB5DF /* Lottie in Frameworks */, + 363F1A232C9F15EB007527E2 /* RxGesture in Frameworks */, 368E36A82C4A3BBE003FA911 /* RxDataSources in Frameworks */, 368E36992C4A3B55003FA911 /* Moya in Frameworks */, 363C243C2C6619950097FCB7 /* Kingfisher in Frameworks */, @@ -1380,6 +1382,7 @@ 3664CFD92C6E2179007FB5DF /* Lottie */, 36130D032C92B0F90028CF3A /* FirebaseMessaging */, 363F1A172C9CA04F007527E2 /* Amplitude */, + 363F1A222C9F15EB007527E2 /* RxGesture */, ); productName = DDANZI_iOS; productReference = 369C63872C1A7A240021E2E0 /* DDANZI_iOS.app */; @@ -1467,6 +1470,7 @@ 3664CFD82C6E2179007FB5DF /* XCRemoteSwiftPackageReference "lottie-ios" */, 36130D022C92B0F90028CF3A /* XCRemoteSwiftPackageReference "firebase-ios-sdk" */, 363F1A162C9CA04F007527E2 /* XCRemoteSwiftPackageReference "Amplitude-iOS" */, + 363F1A212C9F15EB007527E2 /* XCRemoteSwiftPackageReference "RxGesture" */, ); productRefGroup = 369C63882C1A7A240021E2E0 /* Products */; projectDirPath = ""; @@ -2079,6 +2083,14 @@ kind = branch; }; }; + 363F1A212C9F15EB007527E2 /* XCRemoteSwiftPackageReference "RxGesture" */ = { + isa = XCRemoteSwiftPackageReference; + repositoryURL = "https://github.com/RxSwiftCommunity/RxGesture"; + requirement = { + kind = upToNextMajorVersion; + minimumVersion = 4.0.4; + }; + }; 3664CFD82C6E2179007FB5DF /* XCRemoteSwiftPackageReference "lottie-ios" */ = { isa = XCRemoteSwiftPackageReference; repositoryURL = "https://github.com/airbnb/lottie-ios"; @@ -2177,6 +2189,11 @@ package = 363F1A162C9CA04F007527E2 /* XCRemoteSwiftPackageReference "Amplitude-iOS" */; productName = Amplitude; }; + 363F1A222C9F15EB007527E2 /* RxGesture */ = { + isa = XCSwiftPackageProductDependency; + package = 363F1A212C9F15EB007527E2 /* XCRemoteSwiftPackageReference "RxGesture" */; + productName = RxGesture; + }; 3664CFD92C6E2179007FB5DF /* Lottie */ = { isa = XCSwiftPackageProductDependency; package = 3664CFD82C6E2179007FB5DF /* XCRemoteSwiftPackageReference "lottie-ios" */; From 7ea581f8e1775292304df6acfa321dbc2b108ade Mon Sep 17 00:00:00 2001 From: Zoe Date: Sun, 22 Sep 2024 22:35:50 +0900 Subject: [PATCH 08/20] =?UTF-8?q?[Add/#42]=20dev=EB=B2=84=EC=A0=84=20?= =?UTF-8?q?=EC=84=A4=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- DDANZI_iOS/DDANZI_iOS.xcodeproj/project.pbxproj | 6 +++--- .../AppIcon_dev.appiconset/Contents.json | 14 ++++++++++++++ .../AppIcon_dev.appiconset/appicon.png | Bin 0 -> 16849 bytes 3 files changed, 17 insertions(+), 3 deletions(-) create mode 100644 DDANZI_iOS/DDANZI_iOS/Common/Resource/Assets.xcassets/AppIcon_dev.appiconset/Contents.json create mode 100644 DDANZI_iOS/DDANZI_iOS/Common/Resource/Assets.xcassets/AppIcon_dev.appiconset/appicon.png diff --git a/DDANZI_iOS/DDANZI_iOS.xcodeproj/project.pbxproj b/DDANZI_iOS/DDANZI_iOS.xcodeproj/project.pbxproj index ebe356e..c9652a6 100644 --- a/DDANZI_iOS/DDANZI_iOS.xcodeproj/project.pbxproj +++ b/DDANZI_iOS/DDANZI_iOS.xcodeproj/project.pbxproj @@ -1870,7 +1870,7 @@ 369C63B22C1A7A270021E2E0 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon_dev; ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; ASSETCATALOG_COMPILER_INCLUDE_ALL_APPICON_ASSETS = NO; CODE_SIGN_ENTITLEMENTS = DDANZI_iOS/DDANZI_iOS.entitlements; @@ -1879,7 +1879,7 @@ DEVELOPMENT_TEAM = 65NSM7Z327; GENERATE_INFOPLIST_FILE = YES; INFOPLIST_FILE = DDANZI_iOS/Application/Info.plist; - INFOPLIST_KEY_CFBundleDisplayName = "딴지"; + INFOPLIST_KEY_CFBundleDisplayName = "딴지(DEV)"; INFOPLIST_KEY_LSApplicationCategoryType = ""; INFOPLIST_KEY_NSPhotoLibraryUsageDescription = "상품 캡처본을 위해 접근이 필요합니다. "; INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; @@ -1892,7 +1892,7 @@ "@executable_path/Frameworks", ); MARKETING_VERSION = 1.0; - PRODUCT_BUNDLE_IDENTIFIER = "com.orangeCo.DDANZI-iOS"; + PRODUCT_BUNDLE_IDENTIFIER = "com.orangeCo.DDANZI-iOS.dev"; PRODUCT_NAME = "$(TARGET_NAME)"; SUPPORTED_PLATFORMS = "iphoneos iphonesimulator"; SUPPORTS_MACCATALYST = NO; diff --git a/DDANZI_iOS/DDANZI_iOS/Common/Resource/Assets.xcassets/AppIcon_dev.appiconset/Contents.json b/DDANZI_iOS/DDANZI_iOS/Common/Resource/Assets.xcassets/AppIcon_dev.appiconset/Contents.json new file mode 100644 index 0000000..3193f63 --- /dev/null +++ b/DDANZI_iOS/DDANZI_iOS/Common/Resource/Assets.xcassets/AppIcon_dev.appiconset/Contents.json @@ -0,0 +1,14 @@ +{ + "images" : [ + { + "filename" : "appicon.png", + "idiom" : "universal", + "platform" : "ios", + "size" : "1024x1024" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/DDANZI_iOS/DDANZI_iOS/Common/Resource/Assets.xcassets/AppIcon_dev.appiconset/appicon.png b/DDANZI_iOS/DDANZI_iOS/Common/Resource/Assets.xcassets/AppIcon_dev.appiconset/appicon.png new file mode 100644 index 0000000000000000000000000000000000000000..61ed6147d77569b507d90eebfdd9a481e835d1ac GIT binary patch literal 16849 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 literal 0 HcmV?d00001 From bb56eecff5ff814136d0e84562a1f24c0d65368c Mon Sep 17 00:00:00 2001 From: Zoe Date: Sun, 22 Sep 2024 22:36:52 +0900 Subject: [PATCH 09/20] =?UTF-8?q?[Feat/#42]=20enum=20=ED=83=80=EC=9E=85=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Presentation/Transaction/Model/PurchaseModel.swift | 8 +++++++- .../ViewController/SalesDetailViewController.swift | 2 +- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/DDANZI_iOS/DDANZI_iOS/Presentation/Transaction/Model/PurchaseModel.swift b/DDANZI_iOS/DDANZI_iOS/Presentation/Transaction/Model/PurchaseModel.swift index 4cc2992..f6d4f0f 100644 --- a/DDANZI_iOS/DDANZI_iOS/Presentation/Transaction/Model/PurchaseModel.swift +++ b/DDANZI_iOS/DDANZI_iOS/Presentation/Transaction/Model/PurchaseModel.swift @@ -15,6 +15,8 @@ enum StatusType { case cancel case notDeposit case onSale + case delayedShipping + case warning var statusString: String { switch self { @@ -24,7 +26,7 @@ enum StatusType { return "주문 완료" case .deposit: return "입금 완료" - case .delivery: + case .delivery,.delayedShipping,.warning: return "배송 중" case .complete: return "거래 완료" @@ -52,6 +54,10 @@ enum StatusType { self = .cancel case "ON_SALE": self = .onSale + case "DELAYED_SHIPPING": + self = .delayedShipping + case "WARNING": + self = .warning default: return nil } diff --git a/DDANZI_iOS/DDANZI_iOS/Presentation/Transaction/ViewController/SalesDetailViewController.swift b/DDANZI_iOS/DDANZI_iOS/Presentation/Transaction/ViewController/SalesDetailViewController.swift index 8e866ba..2e52d99 100644 --- a/DDANZI_iOS/DDANZI_iOS/Presentation/Transaction/ViewController/SalesDetailViewController.swift +++ b/DDANZI_iOS/DDANZI_iOS/Presentation/Transaction/ViewController/SalesDetailViewController.swift @@ -161,7 +161,7 @@ class SalesDetailViewController: UIViewController { case .deposit: owner.button.titleLabel?.text = "판매 확정하기" owner.button.setEnable() - case .delivery: + case .delivery, .delayedShipping, .warning: owner.button.titleLabel?.text = "배송 중인 상품입니다." case .complete: owner.button.titleLabel?.text = "거래가 완료된 상품입니다." From 0510a2e42e8f4d5bbb69c725d2d87d20bec82711 Mon Sep 17 00:00:00 2001 From: Zoe Date: Sun, 22 Sep 2024 22:37:16 +0900 Subject: [PATCH 10/20] =?UTF-8?q?[Feat/#42]=20=EC=BB=A4=EC=8A=A4=ED=85=80?= =?UTF-8?q?=20=EC=95=8C=EB=9F=BF=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../DDANZI_iOS.xcodeproj/project.pbxproj | 4 + .../Common/ReusableView/CustomAlertView.swift | 131 ++++++++++++++++++ 2 files changed, 135 insertions(+) create mode 100644 DDANZI_iOS/DDANZI_iOS/Presentation/Common/ReusableView/CustomAlertView.swift diff --git a/DDANZI_iOS/DDANZI_iOS.xcodeproj/project.pbxproj b/DDANZI_iOS/DDANZI_iOS.xcodeproj/project.pbxproj index c9652a6..4691798 100644 --- a/DDANZI_iOS/DDANZI_iOS.xcodeproj/project.pbxproj +++ b/DDANZI_iOS/DDANZI_iOS.xcodeproj/project.pbxproj @@ -77,6 +77,7 @@ 363F1A1E2C9F072F007527E2 /* UserAccountRequestDTO.swift in Sources */ = {isa = PBXBuildFile; fileRef = 363F1A1D2C9F072F007527E2 /* UserAccountRequestDTO.swift */; }; 363F1A232C9F15EB007527E2 /* RxGesture in Frameworks */ = {isa = PBXBuildFile; productRef = 363F1A222C9F15EB007527E2 /* RxGesture */; }; 363F1A252C9F1BE2007527E2 /* BankList.swift in Sources */ = {isa = PBXBuildFile; fileRef = 363F1A242C9F1BE2007527E2 /* BankList.swift */; }; + 363F1A272C9F57D4007527E2 /* CustomAlertView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 363F1A262C9F57D4007527E2 /* CustomAlertView.swift */; }; 3648954E2C6281BB00AAA8E2 /* HomeItemsResponseDTO.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3648954D2C6281BB00AAA8E2 /* HomeItemsResponseDTO.swift */; }; 364895502C62822200AAA8E2 /* ProductDetailResponseDTO.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3648954F2C62822200AAA8E2 /* ProductDetailResponseDTO.swift */; }; 364895522C62826200AAA8E2 /* SearchItemsResponseDTO.swift in Sources */ = {isa = PBXBuildFile; fileRef = 364895512C62826200AAA8E2 /* SearchItemsResponseDTO.swift */; }; @@ -315,6 +316,7 @@ 363F1A1B2C9EF029007527E2 /* AccountAddCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccountAddCell.swift; sourceTree = ""; }; 363F1A1D2C9F072F007527E2 /* UserAccountRequestDTO.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserAccountRequestDTO.swift; sourceTree = ""; }; 363F1A242C9F1BE2007527E2 /* BankList.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BankList.swift; sourceTree = ""; }; + 363F1A262C9F57D4007527E2 /* CustomAlertView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomAlertView.swift; sourceTree = ""; }; 3648954D2C6281BB00AAA8E2 /* HomeItemsResponseDTO.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeItemsResponseDTO.swift; sourceTree = ""; }; 3648954F2C62822200AAA8E2 /* ProductDetailResponseDTO.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProductDetailResponseDTO.swift; sourceTree = ""; }; 364895512C62826200AAA8E2 /* SearchItemsResponseDTO.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchItemsResponseDTO.swift; sourceTree = ""; }; @@ -538,6 +540,7 @@ 363152802C35EAF400DF689E /* DdanziButton.swift */, 363C24282C6520DD0097FCB7 /* DdanziChipButton.swift */, 36A5947D2C87F90C0097DE70 /* DdanziLoadingView.swift */, + 363F1A262C9F57D4007527E2 /* CustomAlertView.swift */, ); path = ReusableView; sourceTree = ""; @@ -1610,6 +1613,7 @@ 364895542C62829200AAA8E2 /* SearchResultResponseDTO.swift in Sources */, 363C24252C651E620097FCB7 /* AddressFormViewController.swift in Sources */, 364895662C6285C900AAA8E2 /* UserAddressRequestDTO.swift in Sources */, + 363F1A272C9F57D4007527E2 /* CustomAlertView.swift in Sources */, 3648DB802C93E134003EA6BE /* PushViewController.swift in Sources */, 36B833EC2C5CDCE4009C2C3E /* AuthEndpoint.swift in Sources */, 362864CE2C8EBC2C00029452 /* PickerManager.swift in Sources */, diff --git a/DDANZI_iOS/DDANZI_iOS/Presentation/Common/ReusableView/CustomAlertView.swift b/DDANZI_iOS/DDANZI_iOS/Presentation/Common/ReusableView/CustomAlertView.swift new file mode 100644 index 0000000..0021028 --- /dev/null +++ b/DDANZI_iOS/DDANZI_iOS/Presentation/Common/ReusableView/CustomAlertView.swift @@ -0,0 +1,131 @@ +// +// CustomAlertView.swift +// DDANZI_iOS +// +// Created by 이지희 on 9/22/24. +// + +import UIKit + +import Then +import SnapKit +import RxSwift + +final class CustomAlertViewController: UIViewController { + + var primaryButtonTap = PublishSubject() + private let disposeBag = DisposeBag() + + private let dimView = UIView().then { + $0.backgroundColor = .black.withAlphaComponent(0.3) + } + + private let alertView = UIView().then { + $0.backgroundColor = .white + $0.makeCornerRound(radius: 10) + } + + private let innerStackView = UIStackView().then { + $0.axis = .vertical + $0.alignment = .center + $0.spacing = 20.adjusted + } + + private let titleLabel = UILabel().then { + $0.font = .title4Sb24 + $0.textAlignment = .center + $0.textColor = .black + } + + private let contentLabel = UILabel().then { + $0.font = .body4R16 + $0.textAlignment = .center + $0.numberOfLines = 3 + $0.textColor = .black + } + + private let conformButton = UIButton().then { + $0.titleLabel?.font = .body3Sb16 + $0.backgroundColor = .black + $0.setTitleColor(.white, for: .normal) + $0.makeCornerRound(radius: 10) + } + + private let subButton = UIButton().then { + $0.setUnderline() + $0.titleLabel?.font = .buttonText + $0.setTitleColor(.gray3, for: .normal) + $0.isHidden = true + } + + init(title: String, content: String, buttonText: String, subButton: String?){ + self.titleLabel.text = title + self.contentLabel.text = content + self.conformButton.setTitle(buttonText, for: .normal) + if let subButton { + self.subButton.setTitle(subButton, for: .normal) + self.subButton.isHidden = false + } + super.init(nibName: nil, bundle: nil) + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + override func viewDidLoad() { + super.viewDidLoad() + setUI() + bindActions() + } + + private func setUI() { + setHierarchy() + setConstraints() + // Add tap gesture recognizer to dimView + let tapGesture = UITapGestureRecognizer(target: self, action: #selector(dismissAlert)) + dimView.addGestureRecognizer(tapGesture) + } + + @objc private func dismissAlert() { + dismiss(animated: true, completion: nil) + } + + private func setHierarchy() { + view.addSubview(dimView) + dimView.addSubview(alertView) + alertView.addSubviews(innerStackView) + innerStackView.addArrangedSubviews(titleLabel, contentLabel, conformButton, subButton) + } + + private func setConstraints() { + dimView.snp.makeConstraints { + $0.edges.equalToSuperview() + } + + alertView.snp.makeConstraints { + $0.centerY.equalToSuperview() + $0.leading.trailing.equalToSuperview().inset(24) + $0.height.equalTo(240.adjusted) + } + + innerStackView.snp.makeConstraints { + $0.center.equalToSuperview() + $0.leading.trailing.equalToSuperview().inset(15) + } + + conformButton.snp.makeConstraints { + $0.height.equalTo(52.adjusted) + $0.leading.trailing.equalToSuperview().inset(10) + } + } + + private func bindActions() { + conformButton.rx.tap + .do(onNext: { [weak self] in + self?.dismiss(animated: false, completion: nil) + }) + .bind(to: primaryButtonTap) + .disposed(by: disposeBag) + } +} From b6305ceb4ce6ec9f9cceb08e9c9c08a5bf7e3360 Mon Sep 17 00:00:00 2001 From: Zoe Date: Sun, 22 Sep 2024 22:37:46 +0900 Subject: [PATCH 11/20] =?UTF-8?q?[Fix/#42]=20=EB=A1=9C=EA=B7=B8=EC=95=84?= =?UTF-8?q?=EC=9B=83=20=EC=B2=98=EB=A6=AC=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Common/LocalStorage/Keychainwrapper.swift | 2 +- .../Data/Network/Foundation/Interceptor.swift | 82 ++++++++++++------- .../View/Info/AccountViewController.swift | 6 +- 3 files changed, 58 insertions(+), 32 deletions(-) diff --git a/DDANZI_iOS/DDANZI_iOS/Common/LocalStorage/Keychainwrapper.swift b/DDANZI_iOS/DDANZI_iOS/Common/LocalStorage/Keychainwrapper.swift index 415ace2..401094e 100644 --- a/DDANZI_iOS/DDANZI_iOS/Common/LocalStorage/Keychainwrapper.swift +++ b/DDANZI_iOS/DDANZI_iOS/Common/LocalStorage/Keychainwrapper.swift @@ -131,7 +131,7 @@ public final class KeychainWrapper { return status == errSecSuccess } - private func deleteAccessToken() -> Bool { + func deleteAccessToken() -> Bool { let query: [CFString: Any] = [ kSecClass: kSecClassGenericPassword, kSecAttrService: userKey diff --git a/DDANZI_iOS/DDANZI_iOS/Data/Network/Foundation/Interceptor.swift b/DDANZI_iOS/DDANZI_iOS/Data/Network/Foundation/Interceptor.swift index 9c92afb..05e205e 100644 --- a/DDANZI_iOS/DDANZI_iOS/Data/Network/Foundation/Interceptor.swift +++ b/DDANZI_iOS/DDANZI_iOS/Data/Network/Foundation/Interceptor.swift @@ -21,39 +21,65 @@ final class AuthInterceptor: RequestInterceptor { } func retry(_ request: Request, for session: Session, dueTo error: Error, completion: @escaping (RetryResult) -> Void) { - print("-------🔧retry 시작🔧-------") - guard (request.response?.statusCode) != nil - else { - print("🚨status code 오류") - return completion(.doNotRetry) - } - - if request.retryCount < retryLimit { - if let statusCode = request.response?.statusCode, - request.retryCount < retryLimit { - if statusCode == 401 { - refreshToken() - } else { - completion(.doNotRetryWithError(error)) - return - } + print("-------🔧retry 시작🔧-------") + guard let statusCode = request.response?.statusCode else { + print("🚨status code 오류") + return completion(.doNotRetry) + } + + if request.retryCount < retryLimit { + if statusCode == 401 { + refreshToken { success in + if success { + // Retry the request if token refresh was successful + completion(.retry) + } else { + // Token refresh failed; do not retry + completion(.doNotRetry) + } + } + } else { + completion(.doNotRetryWithError(error)) + } + } else { + completion(.doNotRetry) } - } } + } extension AuthInterceptor { - private func refreshToken() { - Providers.AuthProvider.request(target: .refreshToken, instance: BaseResponse.self) { response in - guard let data = response.data else { return } - if let accessToken = data.accesstoken { - KeychainWrapper.shared.setAccessToken(accessToken) - UserDefaults.standard.set(data.refreshtoken, forKey: .refreshToken) - } - - if response.status == 401 { - UserDefaults.standard.set(data.refreshtoken, forKey: .refreshToken) + private func refreshToken(completion: @escaping (Bool) -> Void) { + Providers.AuthProvider.request(target: .refreshToken, instance: BaseResponse.self) { response in + guard let data = response.data else { + // Token refresh failed + self.handleTokenRefreshFailure() + completion(false) // Indicate failure + return + } + + if let accessToken = data.accesstoken { + KeychainWrapper.shared.setAccessToken(accessToken) + UserDefaults.standard.set(data.refreshtoken, forKey: .refreshToken) + } + + if response.status == 401 { + UserDefaults.standard.set(data.refreshtoken, forKey: .refreshToken) + } + + completion(true) // Indicate success } - } + } + + + private func handleTokenRefreshFailure() { + // Clear tokens + KeychainWrapper.shared.deleteAccessToken() + UserDefaults.standard.removeObject(forKey: .refreshToken) + + // Set isLogin to false + UserDefaults.standard.set(false, forKey: "isLogin") + + print("🚨 Token refresh failed. Tokens cleared and isLogin set to false.") } } diff --git a/DDANZI_iOS/DDANZI_iOS/Presentation/Mypage/View/Info/AccountViewController.swift b/DDANZI_iOS/DDANZI_iOS/Presentation/Mypage/View/Info/AccountViewController.swift index 6ab35b9..e5f0499 100644 --- a/DDANZI_iOS/DDANZI_iOS/Presentation/Mypage/View/Info/AccountViewController.swift +++ b/DDANZI_iOS/DDANZI_iOS/Presentation/Mypage/View/Info/AccountViewController.swift @@ -100,13 +100,13 @@ extension AccountViewController: UITableViewDataSource { UserApi.shared.logout {(error) in if let error = error { print(error) - + KeychainWrapper.shared.deleteAccessToken() UserDefaults.standard.set(false, forKey: .isLogin) self.navigationController?.popToRootViewController(animated: true) } else { UserDefaults.standard.clearAll() - + KeychainWrapper.shared.deleteAccessToken() UserDefaults.standard.set(false, forKey: .isLogin) self.navigationController?.popToRootViewController(animated: true) print("logout() success.") @@ -125,7 +125,7 @@ extension AccountViewController: UITableViewDataSource { } else { UserDefaults.standard.clearAll() - KeychainWrapper.shared.setAccessToken("") + KeychainWrapper.shared.deleteAccessToken() UserDefaults.standard.set(false, forKey: .isLogin) self.navigationController?.popToRootViewController(animated: true) } From 5ea25b5c1937875c65eefeb9733b09c9bfaafde0 Mon Sep 17 00:00:00 2001 From: Zoe Date: Sun, 22 Sep 2024 22:38:44 +0900 Subject: [PATCH 12/20] =?UTF-8?q?[Feat/#42]=20=EA=B3=84=EC=A2=8C=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80=20API=20=EC=97=B0=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Data/DTO/Item/itemConfirmedDTO.swift | 2 +- .../Data/Endpoint/MypageEndpoint.swift | 24 +++++++++++++++---- 2 files changed, 20 insertions(+), 6 deletions(-) diff --git a/DDANZI_iOS/DDANZI_iOS/Data/DTO/Item/itemConfirmedDTO.swift b/DDANZI_iOS/DDANZI_iOS/Data/DTO/Item/itemConfirmedDTO.swift index 68f1897..9874a11 100644 --- a/DDANZI_iOS/DDANZI_iOS/Data/DTO/Item/itemConfirmedDTO.swift +++ b/DDANZI_iOS/DDANZI_iOS/Data/DTO/Item/itemConfirmedDTO.swift @@ -11,7 +11,7 @@ struct itemConformedDTO: Codable { let productID, productName: String let imgURL: String let originPrice, salePrice: Int - let isAccountExist: Bool + var isAccountExist: Bool enum CodingKeys: String, CodingKey { case productID = "productId" diff --git a/DDANZI_iOS/DDANZI_iOS/Data/Endpoint/MypageEndpoint.swift b/DDANZI_iOS/DDANZI_iOS/Data/Endpoint/MypageEndpoint.swift index 11b2181..818c1b5 100644 --- a/DDANZI_iOS/DDANZI_iOS/Data/Endpoint/MypageEndpoint.swift +++ b/DDANZI_iOS/DDANZI_iOS/Data/Endpoint/MypageEndpoint.swift @@ -20,12 +20,14 @@ enum MypageEndpoint { /// 주소 관련 API case fetchUserAddress case addUserAddress(UserAddressRequestDTO) - case editUserAddress(Int) + case editUserAddress(Int,UserAddressRequestDTO) case deleteUserAddress(Int) /// 계좌 관련 API case fetchUserAccount - case addUserAccount + case addUserAccount(UserAccountRequestDTO) + case editUserAccount(Int,UserAccountRequestDTO) + case deleteUserAccount(Int) case settingUserNoti } @@ -51,7 +53,7 @@ extension MypageEndpoint: BaseTargetType { return "/api/v1/mypage/setting/address" case .addUserAddress: return "/api/v1/mypage/setting/address" - case let .editUserAddress(id): + case let .editUserAddress(id, _): return "/api/v1/mypage/setting/address/\(id)" case let .deleteUserAddress(id): return "/api/v1/mypage/setting/address/\(id)" @@ -61,6 +63,10 @@ extension MypageEndpoint: BaseTargetType { return "/api/v1/mypage/setting/account" case .addUserAccount: return "/api/v1/mypage/setting/account" + case let .editUserAccount(id, _): + return "/api/v1/mypage/setting/account/\(id)" + case let .deleteUserAccount(id): + return "/api/v1/mypage/setting/account/\(id)" } } @@ -90,6 +96,10 @@ extension MypageEndpoint: BaseTargetType { return .get case .addUserAccount: return .post + case .editUserAccount: + return .put + case .deleteUserAccount: + return .delete } } @@ -109,7 +119,7 @@ extension MypageEndpoint: BaseTargetType { return .requestPlain case let .addUserAddress(body): return .requestJSONEncodable(body) - case .editUserAddress: + case let .editUserAddress(_, body): return .requestPlain case .deleteUserAddress: return .requestPlain @@ -117,7 +127,11 @@ extension MypageEndpoint: BaseTargetType { return .requestPlain case .fetchUserAccount: return .requestPlain - case .addUserAccount: + case .addUserAccount(let body): + return .requestJSONEncodable(body) + case let .editUserAccount(_, body): + return .requestJSONEncodable(body) + case .deleteUserAccount(_): return .requestPlain } } From 024a228861659d78174bb21c13be8bb1c0b451d7 Mon Sep 17 00:00:00 2001 From: Zoe Date: Sun, 22 Sep 2024 22:39:14 +0900 Subject: [PATCH 13/20] =?UTF-8?q?[Feat/#42]=20=EB=A7=88=EC=9D=B4=ED=8E=98?= =?UTF-8?q?=EC=9D=B4=EC=A7=80=20=EA=B3=84=EC=A2=8C=20=EA=B4=80=EB=A6=AC=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 --- .../View/Info/AccountAddViewController.swift | 43 +++++++++++++++++-- .../View/Info/BankAccountViewController.swift | 4 +- 2 files changed, 42 insertions(+), 5 deletions(-) diff --git a/DDANZI_iOS/DDANZI_iOS/Presentation/Mypage/View/Info/AccountAddViewController.swift b/DDANZI_iOS/DDANZI_iOS/Presentation/Mypage/View/Info/AccountAddViewController.swift index 0f9d120..99ae33c 100644 --- a/DDANZI_iOS/DDANZI_iOS/Presentation/Mypage/View/Info/AccountAddViewController.swift +++ b/DDANZI_iOS/DDANZI_iOS/Presentation/Mypage/View/Info/AccountAddViewController.swift @@ -18,10 +18,13 @@ import RxGesture final class AccountAddViewController: UIViewController { // MARK: Property + private var bankAccountId: Int? private let titles = ["이름", "은행", "계좌번호"] private var userName = UserDefaults.standard.string(forKey: "name") ?? "사용자" private let disposeBag = DisposeBag() + // 계좌 등록 완료 상태를 전달할 Relay + var accountRegisteredRelay = PublishRelay() private var selectedBankCode: String? private lazy var nameSubject = BehaviorSubject(value: userName) @@ -41,6 +44,15 @@ final class AccountAddViewController: UIViewController { } private let conformButton = DdanziButton(title: "입력 완료", enable: false) + init(bankAccountId: Int?) { + self.bankAccountId = bankAccountId + super.init(nibName: nil, bundle: nil) + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + // MARK: LifeCycle override func viewDidLoad() { super.viewDidLoad() @@ -87,6 +99,13 @@ final class AccountAddViewController: UIViewController { private func bind() { tableView.delegate = self tableView.dataSource = self + + navigationView.backButtonTap + .subscribe(with: self) { owner, _ in + owner.navigationController?.popViewController(animated: true) + } + .disposed(by: disposeBag) + // 모든 필드가 채워졌을 때 버튼 활성화 Observable.combineLatest(nameSubject, bankSubject, accountNumberSubject) .map { !$0.0.isEmpty && !$0.1.isEmpty && !$0.2.isEmpty } @@ -98,11 +117,14 @@ final class AccountAddViewController: UIViewController { conformButton.rx.tap .subscribe(with: self) { owner, _ in // 등록 버튼 눌렀을 때의 처리 - let accountName = try? owner.nameSubject.value() - let bank = try? owner.bankSubject.value() + let accountName = UserDefaults.standard.string(forKey: .name) + let bank = self.selectedBankCode let accountNumber = try? owner.accountNumberSubject.value() - - owner.conformAccount(accountName: accountName ?? "", bank: bank ?? "", accountNumber: accountNumber ?? "") + if let bankAccountId = self.bankAccountId { + owner.editAccount(accountId: bankAccountId, accountName: accountName ?? "", bank: bank ?? "", accountNumber: accountNumber ?? "") + } else { + owner.conformAccount(accountName: accountName ?? "", bank: bank ?? "", accountNumber: accountNumber ?? "") + } } .disposed(by: disposeBag) } @@ -132,6 +154,18 @@ final class AccountAddViewController: UIViewController { return name.replacingCharacters(in: middleIndex...middleIndex, with: "*") } + private func editAccount(accountId: Int, accountName: String, bank: String, accountNumber: String) { + let body = UserAccountRequestDTO(acountName: accountName, bank: bank, accountNumber: accountNumber) + Providers.MypageProvider.request(target: .editUserAccount(accountId, body), instance: BaseResponse.self) { response in + guard let data = response.data else { return } + if response.status != 200 || response.status != 201 { + self.view.showToast(message: "계좌 등록 오류 입니다. 잠시 후 다시 시도해주세요", at: 100) + } else { + self.navigationController?.popViewController(animated: true) + } + } + } + private func conformAccount(accountName: String, bank: String, accountNumber: String) { let body = UserAccountRequestDTO(acountName: accountName, bank: bank, accountNumber: accountNumber) Providers.MypageProvider.request(target: .addUserAccount(body), instance: BaseResponse.self) { response in @@ -139,6 +173,7 @@ final class AccountAddViewController: UIViewController { if response.status != 200 || response.status != 201 { self.view.showToast(message: "계좌 등록 오류 입니다. 잠시 후 다시 시도해주세요", at: 100) } else { + self.accountRegisteredRelay.accept(true) self.navigationController?.popViewController(animated: true) } } diff --git a/DDANZI_iOS/DDANZI_iOS/Presentation/Mypage/View/Info/BankAccountViewController.swift b/DDANZI_iOS/DDANZI_iOS/Presentation/Mypage/View/Info/BankAccountViewController.swift index 100b4e0..df543c6 100644 --- a/DDANZI_iOS/DDANZI_iOS/Presentation/Mypage/View/Info/BankAccountViewController.swift +++ b/DDANZI_iOS/DDANZI_iOS/Presentation/Mypage/View/Info/BankAccountViewController.swift @@ -14,6 +14,7 @@ import RxSwift class BankAccountViewController: UIViewController { private let disposeBag = DisposeBag() + private var bankAccountId: Int? private let navigationBarView = CustomNavigationBarView(navigationBarType: .normal) private let headerView = MyPageSectionHeaderView() @@ -141,6 +142,7 @@ class BankAccountViewController: UIViewController { self.accountNumberLabel.text = accountNumber self.accountButton.isHidden = false self.registerButton.isHidden = true // 계좌 정보가 있으면 등록 버튼을 숨김 + self.bankAccountId = accountId } else { // 계좌 정보가 없으면 등록 버튼을 보이고 계좌 정보 버튼을 숨김 self.accountButton.isHidden = true @@ -167,7 +169,7 @@ class BankAccountViewController: UIViewController { // 계좌 등록 화면으로 이동하는 함수 private func navigateToAccountRegistration() { // 계좌 등록 화면 이동 로직을 구현 - let accountRegistrationVC = AccountAddViewController() + let accountRegistrationVC = AccountAddViewController(bankAccountId: bankAccountId) self.navigationController?.pushViewController(accountRegistrationVC, animated: true) } } From 33335c425fb573643d04288ab1b6450eca4d4a6c Mon Sep 17 00:00:00 2001 From: Zoe Date: Sun, 22 Sep 2024 22:39:49 +0900 Subject: [PATCH 14/20] =?UTF-8?q?[Feat/#42]=20=EC=83=81=ED=92=88=20?= =?UTF-8?q?=EB=93=B1=EB=A1=9D=20=EC=8B=9C=20=EA=B3=84=EC=A2=8C=20=EB=93=B1?= =?UTF-8?q?=EB=A1=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Selling/RegisteItemCell.swift | 11 +++- .../Selling/RegisteItemViewController.swift | 50 +++++++++++++------ 2 files changed, 46 insertions(+), 15 deletions(-) diff --git a/DDANZI_iOS/DDANZI_iOS/Presentation/Selling/RegisteItemCell.swift b/DDANZI_iOS/DDANZI_iOS/Presentation/Selling/RegisteItemCell.swift index ee0507a..5502985 100644 --- a/DDANZI_iOS/DDANZI_iOS/Presentation/Selling/RegisteItemCell.swift +++ b/DDANZI_iOS/DDANZI_iOS/Presentation/Selling/RegisteItemCell.swift @@ -19,6 +19,15 @@ final class RegisteItemCell: UICollectionViewCell { var selectedTerms = BehaviorRelay<[Bool]>(value: [false, false]) var itemInfo = PublishRelay() var dateString = BehaviorRelay(value: "") + + var isReadyToRegister: Observable { + return Observable.combineLatest(selectedTerms.asObservable(), dateString.asObservable()) + .map { termsSelected, date in + let allSelected = termsSelected.allSatisfy { $0 } + return allSelected && !date.isEmpty + } + } + private let disposeBag = DisposeBag() private let imageView = UIImageView() @@ -200,7 +209,7 @@ final class RegisteItemCell: UICollectionViewCell { } termsTableView.snp.makeConstraints { - $0.top.equalTo(fullAgreementButton.snp.bottom).offset(35.adjusted) + $0.top.equalTo(fullAgreementButton.snp.bottom).offset(18.adjusted) $0.leading.trailing.bottom.equalToSuperview() } } diff --git a/DDANZI_iOS/DDANZI_iOS/Presentation/Selling/RegisteItemViewController.swift b/DDANZI_iOS/DDANZI_iOS/Presentation/Selling/RegisteItemViewController.swift index ace6312..852fb16 100644 --- a/DDANZI_iOS/DDANZI_iOS/Presentation/Selling/RegisteItemViewController.swift +++ b/DDANZI_iOS/DDANZI_iOS/Presentation/Selling/RegisteItemViewController.swift @@ -102,7 +102,20 @@ final class RegisteItemViewController: UIViewController { } let dueDate = cell.dateString.value Amplitude.instance().logEvent("click_sell_next", withEventProperties: ["product_id": owner.info.productID]) - owner.registeItem(due: dueDate) + if !owner.info.isAccountExist { + let alertVC = CustomAlertViewController(title: "잠시만요!", content: "상품 판매금액 정산을 위해 입금 받으실 대표계좌 등록이 필요합니다.", buttonText: "계좌 등록 하러 가기", subButton: nil) + + alertVC.primaryButtonTap + .subscribe(onNext: { _ in + owner.navigateToAccountAdd(dueDate: dueDate) + }) + .disposed(by: owner.disposeBag) + + alertVC.modalPresentationStyle = .overFullScreen + owner.present(alertVC, animated: false, completion: nil) + } else { + owner.registeItem(due: dueDate) + } } .disposed(by: disposeBag) @@ -119,12 +132,29 @@ final class RegisteItemViewController: UIViewController { collectionView.delegate = self } + private func navigateToAccountAdd(dueDate: String) { + let accountAddVC = AccountAddViewController(bankAccountId: nil) + + // AccountAddViewController의 accountRegisteredRelay를 구독 + accountAddVC.accountRegisteredRelay + .subscribe(onNext: { [weak self] isRegistered in + guard let self = self else { return } + if isRegistered { + self.info.isAccountExist = true + self.registeItem(due: dueDate) // 계좌 등록이 완료되면 나머지 플로우 진행 + } + }) + .disposed(by: disposeBag) + self.navigationController?.pushViewController(accountAddVC, animated: true) + } + private func registeItem(due: String) { let body = RegisteItemBody(productId: info.productID, productName: info.productName, receivedDate: due, registeredImage: info.imgURL) Providers.ItemProvider.request(target: .registeItem(body: body), instance: BaseResponse.self) { response in guard let data = response.data else { return } let registeCompleteVC = RegisteCompleteViewController(response: data) let pushVC = PushSettingViewController(isSelling: true, orderId: "", response: data) + PermissionManager.shared.checkPermission(for: .notification) .bind(with: self, onNext: { owner, isAllow in Amplitude.instance().logEvent("complete_sell_adjustment", withEventProperties: ["item_id": data.itemId]) @@ -147,20 +177,12 @@ extension RegisteItemViewController: UICollectionViewDataSource { func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: RegisteItemCell.className, for: indexPath) as? RegisteItemCell else { return UICollectionViewCell() } cell.configure(info: self.info) - - // 날짜와 전체 동의 여부 확인 - Observable.combineLatest(cell.selectedTerms, cell.dateString) - .map { termsSelected, date in - // 모든 약관이 동의됐고, 날짜가 선택됐는지 확인 - let allSelected = termsSelected.allSatisfy { $0 } - return allSelected && !date.isEmpty - } - .bind(onNext: { isAllow in - self.registeButton.setEnable() + cell.isReadyToRegister + .subscribe(onNext: { [weak self] isReady in + guard let self = self else { return } + self.registeButton.setEnable(isEnable: isReady) }) .disposed(by: disposeBag) - - return cell } @@ -168,6 +190,6 @@ extension RegisteItemViewController: UICollectionViewDataSource { extension RegisteItemViewController: UICollectionViewDelegateFlowLayout { func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize { - return CGSize(width: collectionView.frame.width, height: 850.adjusted) // 원하는 크기 설정 + return CGSize(width: collectionView.frame.width, height: 830.adjusted) } } From d9d8968b47434d1c9c2d8e19c90b4ccd6438e229 Mon Sep 17 00:00:00 2001 From: Zoe Date: Sun, 22 Sep 2024 22:40:20 +0900 Subject: [PATCH 15/20] =?UTF-8?q?[Feat/#42]=20=EB=B2=84=ED=8A=BC=20Disable?= =?UTF-8?q?=20=EC=83=81=ED=83=9C=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Presentation/Common/ReusableView/DdanziButton.swift | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/DDANZI_iOS/DDANZI_iOS/Presentation/Common/ReusableView/DdanziButton.swift b/DDANZI_iOS/DDANZI_iOS/Presentation/Common/ReusableView/DdanziButton.swift index 1f990a4..15dd9e1 100644 --- a/DDANZI_iOS/DDANZI_iOS/Presentation/Common/ReusableView/DdanziButton.swift +++ b/DDANZI_iOS/DDANZI_iOS/Presentation/Common/ReusableView/DdanziButton.swift @@ -17,9 +17,9 @@ final class DdanziButton: UIButton { fatalError("init(coder:) has not been implemented") } - func setEnable() { - self.backgroundColor = .black - self.isEnabled = true + func setEnable(isEnable: Bool = true) { + self.backgroundColor = isEnable ? .black : .gray2 + self.isEnabled = isEnable } private func configureButton(title: String) { From 6b6e89822d4ccc746b42ffb4834b11f8455829d2 Mon Sep 17 00:00:00 2001 From: Zoe Date: Sun, 22 Sep 2024 22:40:45 +0900 Subject: [PATCH 16/20] =?UTF-8?q?[Feat/#42]=20=EC=95=8C=EB=A6=BC=ED=83=AD?= =?UTF-8?q?=20=EB=88=8C=EB=A0=80=EC=9D=84=20=EB=95=8C=20=EB=A1=9C=EA=B7=B8?= =?UTF-8?q?=EC=9D=B8=20=EC=B2=98=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Home/ViewController/HomeViewController.swift | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/DDANZI_iOS/DDANZI_iOS/Presentation/Home/ViewController/HomeViewController.swift b/DDANZI_iOS/DDANZI_iOS/Presentation/Home/ViewController/HomeViewController.swift index 2eff150..d0a9ca7 100644 --- a/DDANZI_iOS/DDANZI_iOS/Presentation/Home/ViewController/HomeViewController.swift +++ b/DDANZI_iOS/DDANZI_iOS/Presentation/Home/ViewController/HomeViewController.swift @@ -232,7 +232,12 @@ final class HomeViewController: UIViewController, UIScrollViewDelegate { navigationBarView.alarmButtonTap .bind(with: self) { owner, _ in - self.navigationController?.pushViewController(PushViewController(), animated: true) + if UserDefaults.standard.bool(forKey: .isLogin) { + self.navigationController?.pushViewController(PushViewController(), animated: true) + } else { + owner.navigationController?.pushViewController(LoginViewController(signUpFrom: "sell"), animated: true) + owner.view.showToast(message: "로그인이 필요한 서비스 입니다.", at: 50) + } } .disposed(by: disposeBag) } From 7a8a440ad928a4ce35dc864acc0bf3727d3c40fa Mon Sep 17 00:00:00 2001 From: Zoe Date: Sun, 22 Sep 2024 22:41:20 +0900 Subject: [PATCH 17/20] =?UTF-8?q?[Fix/#42]=20=EC=A0=95=EB=B3=B4=EB=B6=88?= =?UTF-8?q?=EB=9F=AC=EC=98=A4=EA=B8=B0=20=EC=8B=A4=ED=8C=A8=20=EC=8B=9C=20?= =?UTF-8?q?=EB=A1=9C=EA=B7=B8=EC=95=84=EC=9B=83=EC=B2=98=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Presentation/Mypage/View/MyPage/MyPageViewController.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DDANZI_iOS/DDANZI_iOS/Presentation/Mypage/View/MyPage/MyPageViewController.swift b/DDANZI_iOS/DDANZI_iOS/Presentation/Mypage/View/MyPage/MyPageViewController.swift index 344f0dd..dd2d1db 100644 --- a/DDANZI_iOS/DDANZI_iOS/Presentation/Mypage/View/MyPage/MyPageViewController.swift +++ b/DDANZI_iOS/DDANZI_iOS/Presentation/Mypage/View/MyPage/MyPageViewController.swift @@ -109,7 +109,7 @@ final class MyPageViewController: UIViewController { private func fetchUser() { Providers.MypageProvider.request(target: .fetchUser, instance: BaseResponse.self) { result in - if result.status == 403 { + if result.status != 200 { self.isLogin = false self.tableView.reloadData() } From 3542e44ebabdda9dd3fc164f8f7ab06b056f1217 Mon Sep 17 00:00:00 2001 From: Zoe Date: Sun, 22 Sep 2024 23:56:30 +0900 Subject: [PATCH 18/20] =?UTF-8?q?[Fix/#42]=20DTO=20=EC=98=A4=EB=A5=98=20?= =?UTF-8?q?=ED=95=B4=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../DDANZI_iOS/Data/DTO/Mypage/UserAccountRequestDTO.swift | 2 +- .../Mypage/View/Info/AccountAddViewController.swift | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/DDANZI_iOS/DDANZI_iOS/Data/DTO/Mypage/UserAccountRequestDTO.swift b/DDANZI_iOS/DDANZI_iOS/Data/DTO/Mypage/UserAccountRequestDTO.swift index 54e8e19..5cc1b9f 100644 --- a/DDANZI_iOS/DDANZI_iOS/Data/DTO/Mypage/UserAccountRequestDTO.swift +++ b/DDANZI_iOS/DDANZI_iOS/Data/DTO/Mypage/UserAccountRequestDTO.swift @@ -8,7 +8,7 @@ import Foundation struct UserAccountRequestDTO: Codable { - let acountName: String + let accountName: String let bank: String let accountNumber: String } diff --git a/DDANZI_iOS/DDANZI_iOS/Presentation/Mypage/View/Info/AccountAddViewController.swift b/DDANZI_iOS/DDANZI_iOS/Presentation/Mypage/View/Info/AccountAddViewController.swift index 99ae33c..88f0d76 100644 --- a/DDANZI_iOS/DDANZI_iOS/Presentation/Mypage/View/Info/AccountAddViewController.swift +++ b/DDANZI_iOS/DDANZI_iOS/Presentation/Mypage/View/Info/AccountAddViewController.swift @@ -155,7 +155,7 @@ final class AccountAddViewController: UIViewController { } private func editAccount(accountId: Int, accountName: String, bank: String, accountNumber: String) { - let body = UserAccountRequestDTO(acountName: accountName, bank: bank, accountNumber: accountNumber) + let body = UserAccountRequestDTO(accountName: accountName, bank: bank, accountNumber: accountNumber) Providers.MypageProvider.request(target: .editUserAccount(accountId, body), instance: BaseResponse.self) { response in guard let data = response.data else { return } if response.status != 200 || response.status != 201 { @@ -167,7 +167,7 @@ final class AccountAddViewController: UIViewController { } private func conformAccount(accountName: String, bank: String, accountNumber: String) { - let body = UserAccountRequestDTO(acountName: accountName, bank: bank, accountNumber: accountNumber) + let body = UserAccountRequestDTO(accountName: accountName, bank: bank, accountNumber: accountNumber) Providers.MypageProvider.request(target: .addUserAccount(body), instance: BaseResponse.self) { response in guard let data = response.data else { return } if response.status != 200 || response.status != 201 { From 6f3454ee79de3c08f1e2c42943fc70ea43ac7139 Mon Sep 17 00:00:00 2001 From: Zoe Date: Mon, 23 Sep 2024 00:00:22 +0900 Subject: [PATCH 19/20] =?UTF-8?q?[Feat/#42]=20=ED=86=A0=ED=81=B0=20?= =?UTF-8?q?=EC=9E=AC=EB=B0=9C=EA=B8=89=20=EC=98=A4=EB=A5=98=20=ED=95=B4?= =?UTF-8?q?=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../DDANZI_iOS.xcodeproj/project.pbxproj | 4 + .../DTO/Auth/RefreshTokenRequestDTO.swift | 12 +++ .../Data/Endpoint/AuthEndpoint.swift | 6 +- .../Data/Network/Foundation/Interceptor.swift | 79 ++++++++++--------- 4 files changed, 59 insertions(+), 42 deletions(-) create mode 100644 DDANZI_iOS/DDANZI_iOS/Data/DTO/Auth/RefreshTokenRequestDTO.swift diff --git a/DDANZI_iOS/DDANZI_iOS.xcodeproj/project.pbxproj b/DDANZI_iOS/DDANZI_iOS.xcodeproj/project.pbxproj index 4691798..4a48cfe 100644 --- a/DDANZI_iOS/DDANZI_iOS.xcodeproj/project.pbxproj +++ b/DDANZI_iOS/DDANZI_iOS.xcodeproj/project.pbxproj @@ -78,6 +78,7 @@ 363F1A232C9F15EB007527E2 /* RxGesture in Frameworks */ = {isa = PBXBuildFile; productRef = 363F1A222C9F15EB007527E2 /* RxGesture */; }; 363F1A252C9F1BE2007527E2 /* BankList.swift in Sources */ = {isa = PBXBuildFile; fileRef = 363F1A242C9F1BE2007527E2 /* BankList.swift */; }; 363F1A272C9F57D4007527E2 /* CustomAlertView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 363F1A262C9F57D4007527E2 /* CustomAlertView.swift */; }; + 363F1A292CA067C7007527E2 /* RefreshTokenRequestDTO.swift in Sources */ = {isa = PBXBuildFile; fileRef = 363F1A282CA067C7007527E2 /* RefreshTokenRequestDTO.swift */; }; 3648954E2C6281BB00AAA8E2 /* HomeItemsResponseDTO.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3648954D2C6281BB00AAA8E2 /* HomeItemsResponseDTO.swift */; }; 364895502C62822200AAA8E2 /* ProductDetailResponseDTO.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3648954F2C62822200AAA8E2 /* ProductDetailResponseDTO.swift */; }; 364895522C62826200AAA8E2 /* SearchItemsResponseDTO.swift in Sources */ = {isa = PBXBuildFile; fileRef = 364895512C62826200AAA8E2 /* SearchItemsResponseDTO.swift */; }; @@ -317,6 +318,7 @@ 363F1A1D2C9F072F007527E2 /* UserAccountRequestDTO.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserAccountRequestDTO.swift; sourceTree = ""; }; 363F1A242C9F1BE2007527E2 /* BankList.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BankList.swift; sourceTree = ""; }; 363F1A262C9F57D4007527E2 /* CustomAlertView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomAlertView.swift; sourceTree = ""; }; + 363F1A282CA067C7007527E2 /* RefreshTokenRequestDTO.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RefreshTokenRequestDTO.swift; sourceTree = ""; }; 3648954D2C6281BB00AAA8E2 /* HomeItemsResponseDTO.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeItemsResponseDTO.swift; sourceTree = ""; }; 3648954F2C62822200AAA8E2 /* ProductDetailResponseDTO.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProductDetailResponseDTO.swift; sourceTree = ""; }; 364895512C62826200AAA8E2 /* SearchItemsResponseDTO.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchItemsResponseDTO.swift; sourceTree = ""; }; @@ -1196,6 +1198,7 @@ 363F1A0B2C9ADD22007527E2 /* RefreshTokenDTO.swift */, 363F1A0D2C9B10AF007527E2 /* WithDrawDTO.swift */, 363F1A0F2C9B10BA007527E2 /* LogoutDTO.swift */, + 363F1A282CA067C7007527E2 /* RefreshTokenRequestDTO.swift */, ); path = Auth; sourceTree = ""; @@ -1672,6 +1675,7 @@ 36542E732C2E88F500D5BFEB /* SellListViewController.swift in Sources */, 362864E72C8EDF0000029452 /* SellDetailDTO.swift in Sources */, 362864CC2C8EA7B700029452 /* CheckItemViewController.swift in Sources */, + 363F1A292CA067C7007527E2 /* RefreshTokenRequestDTO.swift in Sources */, 36EB5FA52C1ECDED00FAF995 /* String+.swift in Sources */, 362864CA2C8E985400029452 /* LandingViewController.swift in Sources */, 36542E792C2E892500D5BFEB /* CsCenterViewController.swift in Sources */, diff --git a/DDANZI_iOS/DDANZI_iOS/Data/DTO/Auth/RefreshTokenRequestDTO.swift b/DDANZI_iOS/DDANZI_iOS/Data/DTO/Auth/RefreshTokenRequestDTO.swift new file mode 100644 index 0000000..66dc826 --- /dev/null +++ b/DDANZI_iOS/DDANZI_iOS/Data/DTO/Auth/RefreshTokenRequestDTO.swift @@ -0,0 +1,12 @@ +// +// RefreshTokenRequestDTO.swift +// DDANZI_iOS +// +// Created by 이지희 on 9/22/24. +// + +import Foundation + +struct RefreshTokenRequestDTO: Codable { + let refreshtoken : String +} diff --git a/DDANZI_iOS/DDANZI_iOS/Data/Endpoint/AuthEndpoint.swift b/DDANZI_iOS/DDANZI_iOS/Data/Endpoint/AuthEndpoint.swift index 532cb93..d6a0e4d 100644 --- a/DDANZI_iOS/DDANZI_iOS/Data/Endpoint/AuthEndpoint.swift +++ b/DDANZI_iOS/DDANZI_iOS/Data/Endpoint/AuthEndpoint.swift @@ -14,7 +14,7 @@ enum AuthEndpoint { case certification(VerificationRequestDTO) case revoke case logout - case refreshToken + case refreshToken(RefreshTokenRequestDTO) } extension AuthEndpoint: BaseTargetType { @@ -73,8 +73,8 @@ extension AuthEndpoint: BaseTargetType { return .requestPlain case .logout: return .requestPlain - case .refreshToken: - return .requestPlain + case let .refreshToken(dto): + return .requestJSONEncodable(dto) } } diff --git a/DDANZI_iOS/DDANZI_iOS/Data/Network/Foundation/Interceptor.swift b/DDANZI_iOS/DDANZI_iOS/Data/Network/Foundation/Interceptor.swift index 05e205e..f7a4de7 100644 --- a/DDANZI_iOS/DDANZI_iOS/Data/Network/Foundation/Interceptor.swift +++ b/DDANZI_iOS/DDANZI_iOS/Data/Network/Foundation/Interceptor.swift @@ -21,56 +21,57 @@ final class AuthInterceptor: RequestInterceptor { } func retry(_ request: Request, for session: Session, dueTo error: Error, completion: @escaping (RetryResult) -> Void) { - print("-------🔧retry 시작🔧-------") - guard let statusCode = request.response?.statusCode else { - print("🚨status code 오류") - return completion(.doNotRetry) - } - - if request.retryCount < retryLimit { - if statusCode == 401 { - refreshToken { success in - if success { - // Retry the request if token refresh was successful - completion(.retry) - } else { - // Token refresh failed; do not retry - completion(.doNotRetry) - } - } + print("-------🔧retry 시작🔧-------") + guard let statusCode = request.response?.statusCode else { + print("🚨status code 오류") + return completion(.doNotRetry) + } + + if request.retryCount < retryLimit { + if statusCode == 401 { + refreshToken { success in + if success { + // Retry the request if token refresh was successful + completion(.retry) } else { - completion(.doNotRetryWithError(error)) + // Token refresh failed; do not retry + completion(.doNotRetry) } + } } else { - completion(.doNotRetry) + completion(.doNotRetryWithError(error)) } + } else { + completion(.doNotRetry) + } } - + } extension AuthInterceptor { private func refreshToken(completion: @escaping (Bool) -> Void) { - Providers.AuthProvider.request(target: .refreshToken, instance: BaseResponse.self) { response in - guard let data = response.data else { - // Token refresh failed - self.handleTokenRefreshFailure() - completion(false) // Indicate failure - return - } - - if let accessToken = data.accesstoken { - KeychainWrapper.shared.setAccessToken(accessToken) - UserDefaults.standard.set(data.refreshtoken, forKey: .refreshToken) - } - - if response.status == 401 { - UserDefaults.standard.set(data.refreshtoken, forKey: .refreshToken) - } - - completion(true) // Indicate success + let body = RefreshTokenRequestDTO(refreshtoken: UserDefaults.standard.string(forKey: .refreshToken) ?? "") + Providers.AuthProvider.request(target: .refreshToken(body), instance: BaseResponse.self) { response in + guard let data = response.data else { + // Token refresh failed + self.handleTokenRefreshFailure() + completion(false) // Indicate failure + return } + + if let accessToken = data.accesstoken { + KeychainWrapper.shared.setAccessToken(accessToken) + UserDefaults.standard.set(data.refreshtoken, forKey: .refreshToken) + } + + if response.status == 401 { + UserDefaults.standard.set(data.refreshtoken, forKey: .refreshToken) + } + + completion(true) // Indicate success + } } - + private func handleTokenRefreshFailure() { // Clear tokens From 78757049908af6c33f8c0be6a7ca55b7c216343b Mon Sep 17 00:00:00 2001 From: Zoe Date: Mon, 23 Sep 2024 03:31:33 +0900 Subject: [PATCH 20/20] =?UTF-8?q?[Feat/#42]=20=EC=98=B5=EC=85=98=20?= =?UTF-8?q?=EC=84=A0=ED=83=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../OptionSelectViewController.swift | 31 +++++++++++-------- .../ProductDetailViewController.swift | 6 ++-- .../TableViewCell/TermsTableViewCell.swift | 2 +- 3 files changed, 22 insertions(+), 17 deletions(-) diff --git a/DDANZI_iOS/DDANZI_iOS/Presentation/ProductDetail/ViewControllers/OptionSelect/OptionSelectViewController.swift b/DDANZI_iOS/DDANZI_iOS/Presentation/ProductDetail/ViewControllers/OptionSelect/OptionSelectViewController.swift index fcc1137..f130962 100644 --- a/DDANZI_iOS/DDANZI_iOS/Presentation/ProductDetail/ViewControllers/OptionSelect/OptionSelectViewController.swift +++ b/DDANZI_iOS/DDANZI_iOS/Presentation/ProductDetail/ViewControllers/OptionSelect/OptionSelectViewController.swift @@ -115,7 +115,8 @@ final class OptionSelectViewController: UIViewController { bottomButton.button.rx.tap .bind { self.dismiss(animated: true) { - self.delegate?.optionViewControllerDidFinish(self) + let unwrappedOptions = self.selectedOptions.compactMap { $0 } + self.delegate?.optionViewControllerDidFinish(self, optionList: unwrappedOptions) Amplitude.instance().logEvent("click_option_next") } } @@ -154,26 +155,30 @@ final class OptionSelectViewController: UIViewController { optionCollectionView.rx.itemSelected .bind(with: self) { owner, indexPath in - if let cell = owner.optionCollectionView.cellForItem(at: indexPath) as? OptionCollectionViewCell { - cell.isSelectedRelay.accept(true) - owner.selectedOptions[indexPath.section] = self.option[indexPath.section].optionDetailList[indexPath.row].optionDetailID - owner.updateButtonState() + // 섹션 내 이전 선택 해제 + if let selectedIndex = owner.selectedOptions[indexPath.section] { + let deselectedIndexPath = IndexPath(row: selectedIndex, section: indexPath.section) + if let cell = owner.optionCollectionView.cellForItem(at: deselectedIndexPath) as? OptionCollectionViewCell { + cell.isSelectedRelay.accept(false) // 이전 선택 해제 + } } - } - .disposed(by: disposeBag) - - optionCollectionView.rx.itemDeselected - .bind(with: self) { owner, indexPath in + + // 선택한 옵션을 섹션별로 저장 + let selectedOptionId = owner.option[indexPath.section].optionDetailList[indexPath.row].optionDetailID + owner.selectedOptions[indexPath.section] = selectedOptionId // optionDetailId 저장 + if let cell = owner.optionCollectionView.cellForItem(at: indexPath) as? OptionCollectionViewCell { - cell.isSelectedRelay.accept(false) - owner.selectedOptions[indexPath.section] = nil - owner.updateButtonState() + cell.isSelectedRelay.accept(true) // 새로운 선택 적용 } + + owner.updateButtonState() // 버튼 상태 업데이트 } .disposed(by: disposeBag) + } private func updateButtonState() { + print(selectedOptions) let allSectionsSelected = selectedOptions.allSatisfy { $0 != nil } bottomButton.button.isEnabled = allSectionsSelected bottomButton.button.backgroundColor = allSectionsSelected ? .black : .gray2 diff --git a/DDANZI_iOS/DDANZI_iOS/Presentation/ProductDetail/ViewControllers/ProductDetailViewController.swift b/DDANZI_iOS/DDANZI_iOS/Presentation/ProductDetail/ViewControllers/ProductDetailViewController.swift index 9920a0c..4fbbb0b 100644 --- a/DDANZI_iOS/DDANZI_iOS/Presentation/ProductDetail/ViewControllers/ProductDetailViewController.swift +++ b/DDANZI_iOS/DDANZI_iOS/Presentation/ProductDetail/ViewControllers/ProductDetailViewController.swift @@ -16,7 +16,7 @@ import Amplitude // MARK: - OptionDelegate protocol OptionViewControllerDelegate: AnyObject { - func optionViewControllerDidFinish(_ viewController: OptionSelectViewController) + func optionViewControllerDidFinish(_ viewController: OptionSelectViewController, optionList: [Int]) } final class ProductDetailViewController: UIViewController { @@ -324,9 +324,9 @@ final class ProductDetailViewController: UIViewController { } extension ProductDetailViewController: OptionViewControllerDelegate { - func optionViewControllerDidFinish(_ viewController: OptionSelectViewController) { + func optionViewControllerDidFinish(_ viewController: OptionSelectViewController, optionList: [Int]) { let purchaseVC = PurchaseViewController() - purchaseVC.orderModel = .init(productId: productId, optionList: optionList.map({ $0.optionID })) + purchaseVC.orderModel = .init(productId: productId, optionList: optionList) self.navigationController?.pushViewController(purchaseVC, animated: true) } } diff --git a/DDANZI_iOS/DDANZI_iOS/Presentation/Purchase/TableViewCell/TermsTableViewCell.swift b/DDANZI_iOS/DDANZI_iOS/Presentation/Purchase/TableViewCell/TermsTableViewCell.swift index ba50c18..2d7838e 100644 --- a/DDANZI_iOS/DDANZI_iOS/Presentation/Purchase/TableViewCell/TermsTableViewCell.swift +++ b/DDANZI_iOS/DDANZI_iOS/Presentation/Purchase/TableViewCell/TermsTableViewCell.swift @@ -51,7 +51,7 @@ final class TermsTableViewCell: UITableViewCell { private func setConstraints() { containerView.snp.makeConstraints { $0.height.equalTo(38) - $0.horizontalEdges.equalToSuperview().inset(20) + $0.horizontalEdges.equalToSuperview() $0.verticalEdges.equalToSuperview().inset(5) }