From 79f6f287a992dc6b7361e3c4787f80683a5403f3 Mon Sep 17 00:00:00 2001 From: heoseungjun Date: Wed, 18 Feb 2026 21:55:52 +0900 Subject: [PATCH 01/20] =?UTF-8?q?setting:=20#360=20=EA=B3=B5=ED=86=B5?= =?UTF-8?q?=ED=80=98=EC=8A=A4=ED=8A=B8=20UI=EC=97=90=20=ED=95=84=EC=9A=94?= =?UTF-8?q?=ED=95=9C=20=EC=9D=B4=EB=AF=B8=EC=A7=80=20=EC=84=B8=ED=8C=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../next_off.imageset/Contents.json | 21 +++++++++++++++++++ .../IconSystem/next_off.imageset/next_off.svg | 4 ++++ .../IconSystem/next_on.imageset/Contents.json | 21 +++++++++++++++++++ .../IconSystem/next_on.imageset/next_on.svg | 4 ++++ .../previous_on.imageset/Contents.json | 21 +++++++++++++++++++ .../previous_on.imageset/previous_on.svg | 4 ++++ .../Assets.xcassets/Profile/Contents.json | 6 ++++++ .../relieved_badge.imageset/Contents.json | 21 +++++++++++++++++++ .../relieved_badge.imageset/relieved.svg | 4 ++++ .../sadness_badge.imageset/Contents.json | 21 +++++++++++++++++++ .../sadness_badge.imageset/sadness.svg | 5 +++++ .../Contents.json | 21 +++++++++++++++++++ .../self_understanding.svg | 5 +++++ .../Profile/soso_badge.imageset/Contents.json | 21 +++++++++++++++++++ .../Profile/soso_badge.imageset/soso.svg | 5 +++++ 15 files changed, 184 insertions(+) create mode 100644 ByeBoo-iOS/ByeBoo-iOS/Resource/Assets.xcassets/IconSystem/next_off.imageset/Contents.json create mode 100644 ByeBoo-iOS/ByeBoo-iOS/Resource/Assets.xcassets/IconSystem/next_off.imageset/next_off.svg create mode 100644 ByeBoo-iOS/ByeBoo-iOS/Resource/Assets.xcassets/IconSystem/next_on.imageset/Contents.json create mode 100644 ByeBoo-iOS/ByeBoo-iOS/Resource/Assets.xcassets/IconSystem/next_on.imageset/next_on.svg create mode 100644 ByeBoo-iOS/ByeBoo-iOS/Resource/Assets.xcassets/IconSystem/previous_on.imageset/Contents.json create mode 100644 ByeBoo-iOS/ByeBoo-iOS/Resource/Assets.xcassets/IconSystem/previous_on.imageset/previous_on.svg create mode 100644 ByeBoo-iOS/ByeBoo-iOS/Resource/Assets.xcassets/Profile/Contents.json create mode 100644 ByeBoo-iOS/ByeBoo-iOS/Resource/Assets.xcassets/Profile/relieved_badge.imageset/Contents.json create mode 100644 ByeBoo-iOS/ByeBoo-iOS/Resource/Assets.xcassets/Profile/relieved_badge.imageset/relieved.svg create mode 100644 ByeBoo-iOS/ByeBoo-iOS/Resource/Assets.xcassets/Profile/sadness_badge.imageset/Contents.json create mode 100644 ByeBoo-iOS/ByeBoo-iOS/Resource/Assets.xcassets/Profile/sadness_badge.imageset/sadness.svg create mode 100644 ByeBoo-iOS/ByeBoo-iOS/Resource/Assets.xcassets/Profile/self_understanding_badge.imageset/Contents.json create mode 100644 ByeBoo-iOS/ByeBoo-iOS/Resource/Assets.xcassets/Profile/self_understanding_badge.imageset/self_understanding.svg create mode 100644 ByeBoo-iOS/ByeBoo-iOS/Resource/Assets.xcassets/Profile/soso_badge.imageset/Contents.json create mode 100644 ByeBoo-iOS/ByeBoo-iOS/Resource/Assets.xcassets/Profile/soso_badge.imageset/soso.svg diff --git a/ByeBoo-iOS/ByeBoo-iOS/Resource/Assets.xcassets/IconSystem/next_off.imageset/Contents.json b/ByeBoo-iOS/ByeBoo-iOS/Resource/Assets.xcassets/IconSystem/next_off.imageset/Contents.json new file mode 100644 index 00000000..785bb348 --- /dev/null +++ b/ByeBoo-iOS/ByeBoo-iOS/Resource/Assets.xcassets/IconSystem/next_off.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "next_off.svg", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/ByeBoo-iOS/ByeBoo-iOS/Resource/Assets.xcassets/IconSystem/next_off.imageset/next_off.svg b/ByeBoo-iOS/ByeBoo-iOS/Resource/Assets.xcassets/IconSystem/next_off.imageset/next_off.svg new file mode 100644 index 00000000..d2d44bec --- /dev/null +++ b/ByeBoo-iOS/ByeBoo-iOS/Resource/Assets.xcassets/IconSystem/next_off.imageset/next_off.svg @@ -0,0 +1,4 @@ + + + + diff --git a/ByeBoo-iOS/ByeBoo-iOS/Resource/Assets.xcassets/IconSystem/next_on.imageset/Contents.json b/ByeBoo-iOS/ByeBoo-iOS/Resource/Assets.xcassets/IconSystem/next_on.imageset/Contents.json new file mode 100644 index 00000000..0569b10d --- /dev/null +++ b/ByeBoo-iOS/ByeBoo-iOS/Resource/Assets.xcassets/IconSystem/next_on.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "next_on.svg", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/ByeBoo-iOS/ByeBoo-iOS/Resource/Assets.xcassets/IconSystem/next_on.imageset/next_on.svg b/ByeBoo-iOS/ByeBoo-iOS/Resource/Assets.xcassets/IconSystem/next_on.imageset/next_on.svg new file mode 100644 index 00000000..d33bd381 --- /dev/null +++ b/ByeBoo-iOS/ByeBoo-iOS/Resource/Assets.xcassets/IconSystem/next_on.imageset/next_on.svg @@ -0,0 +1,4 @@ + + + + diff --git a/ByeBoo-iOS/ByeBoo-iOS/Resource/Assets.xcassets/IconSystem/previous_on.imageset/Contents.json b/ByeBoo-iOS/ByeBoo-iOS/Resource/Assets.xcassets/IconSystem/previous_on.imageset/Contents.json new file mode 100644 index 00000000..121c9c29 --- /dev/null +++ b/ByeBoo-iOS/ByeBoo-iOS/Resource/Assets.xcassets/IconSystem/previous_on.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "previous_on.svg", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/ByeBoo-iOS/ByeBoo-iOS/Resource/Assets.xcassets/IconSystem/previous_on.imageset/previous_on.svg b/ByeBoo-iOS/ByeBoo-iOS/Resource/Assets.xcassets/IconSystem/previous_on.imageset/previous_on.svg new file mode 100644 index 00000000..cd76ce50 --- /dev/null +++ b/ByeBoo-iOS/ByeBoo-iOS/Resource/Assets.xcassets/IconSystem/previous_on.imageset/previous_on.svg @@ -0,0 +1,4 @@ + + + + diff --git a/ByeBoo-iOS/ByeBoo-iOS/Resource/Assets.xcassets/Profile/Contents.json b/ByeBoo-iOS/ByeBoo-iOS/Resource/Assets.xcassets/Profile/Contents.json new file mode 100644 index 00000000..73c00596 --- /dev/null +++ b/ByeBoo-iOS/ByeBoo-iOS/Resource/Assets.xcassets/Profile/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/ByeBoo-iOS/ByeBoo-iOS/Resource/Assets.xcassets/Profile/relieved_badge.imageset/Contents.json b/ByeBoo-iOS/ByeBoo-iOS/Resource/Assets.xcassets/Profile/relieved_badge.imageset/Contents.json new file mode 100644 index 00000000..ff36ecee --- /dev/null +++ b/ByeBoo-iOS/ByeBoo-iOS/Resource/Assets.xcassets/Profile/relieved_badge.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "relieved.svg", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/ByeBoo-iOS/ByeBoo-iOS/Resource/Assets.xcassets/Profile/relieved_badge.imageset/relieved.svg b/ByeBoo-iOS/ByeBoo-iOS/Resource/Assets.xcassets/Profile/relieved_badge.imageset/relieved.svg new file mode 100644 index 00000000..4d706f26 --- /dev/null +++ b/ByeBoo-iOS/ByeBoo-iOS/Resource/Assets.xcassets/Profile/relieved_badge.imageset/relieved.svg @@ -0,0 +1,4 @@ + + + + diff --git a/ByeBoo-iOS/ByeBoo-iOS/Resource/Assets.xcassets/Profile/sadness_badge.imageset/Contents.json b/ByeBoo-iOS/ByeBoo-iOS/Resource/Assets.xcassets/Profile/sadness_badge.imageset/Contents.json new file mode 100644 index 00000000..76d3cdc3 --- /dev/null +++ b/ByeBoo-iOS/ByeBoo-iOS/Resource/Assets.xcassets/Profile/sadness_badge.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "sadness.svg", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/ByeBoo-iOS/ByeBoo-iOS/Resource/Assets.xcassets/Profile/sadness_badge.imageset/sadness.svg b/ByeBoo-iOS/ByeBoo-iOS/Resource/Assets.xcassets/Profile/sadness_badge.imageset/sadness.svg new file mode 100644 index 00000000..3c9547bb --- /dev/null +++ b/ByeBoo-iOS/ByeBoo-iOS/Resource/Assets.xcassets/Profile/sadness_badge.imageset/sadness.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/ByeBoo-iOS/ByeBoo-iOS/Resource/Assets.xcassets/Profile/self_understanding_badge.imageset/Contents.json b/ByeBoo-iOS/ByeBoo-iOS/Resource/Assets.xcassets/Profile/self_understanding_badge.imageset/Contents.json new file mode 100644 index 00000000..7bb22db9 --- /dev/null +++ b/ByeBoo-iOS/ByeBoo-iOS/Resource/Assets.xcassets/Profile/self_understanding_badge.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "self_understanding.svg", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/ByeBoo-iOS/ByeBoo-iOS/Resource/Assets.xcassets/Profile/self_understanding_badge.imageset/self_understanding.svg b/ByeBoo-iOS/ByeBoo-iOS/Resource/Assets.xcassets/Profile/self_understanding_badge.imageset/self_understanding.svg new file mode 100644 index 00000000..f5279adc --- /dev/null +++ b/ByeBoo-iOS/ByeBoo-iOS/Resource/Assets.xcassets/Profile/self_understanding_badge.imageset/self_understanding.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/ByeBoo-iOS/ByeBoo-iOS/Resource/Assets.xcassets/Profile/soso_badge.imageset/Contents.json b/ByeBoo-iOS/ByeBoo-iOS/Resource/Assets.xcassets/Profile/soso_badge.imageset/Contents.json new file mode 100644 index 00000000..89f6e5f4 --- /dev/null +++ b/ByeBoo-iOS/ByeBoo-iOS/Resource/Assets.xcassets/Profile/soso_badge.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "soso.svg", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/ByeBoo-iOS/ByeBoo-iOS/Resource/Assets.xcassets/Profile/soso_badge.imageset/soso.svg b/ByeBoo-iOS/ByeBoo-iOS/Resource/Assets.xcassets/Profile/soso_badge.imageset/soso.svg new file mode 100644 index 00000000..83965cbf --- /dev/null +++ b/ByeBoo-iOS/ByeBoo-iOS/Resource/Assets.xcassets/Profile/soso_badge.imageset/soso.svg @@ -0,0 +1,5 @@ + + + + + From 47cb1d7d29108d255ee80f28420539aab613f18b Mon Sep 17 00:00:00 2001 From: heoseungjun Date: Sun, 22 Feb 2026 16:18:49 +0900 Subject: [PATCH 02/20] =?UTF-8?q?feat:=20=EB=82=A0=EC=A7=9C=EB=B3=84=20?= =?UTF-8?q?=EA=B3=B5=ED=86=B5=ED=80=98=EC=8A=A4=ED=8A=B8=20=EC=A1=B0?= =?UTF-8?q?=ED=9A=8C=20API=20=EC=97=B0=EB=8F=99=EC=9D=84=20=EC=9C=84?= =?UTF-8?q?=ED=95=9C=20=EC=A4=80=EB=B9=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Data/Repository/QuestsRepository.swift | 9 +++ .../Domain/DomainDependencyAssembler.swift | 4 + .../Entity/CommonQuestAnswersEntity.swift | 46 +++++++++++ .../Domain/Interface/QuestsInterface.swift | 1 + .../FetchCommonQuestByDateUseCase.swift | 30 +++++++ .../ViewModel/CommonQuestViewModel.swift | 80 +++++++++++++++++++ .../PresentationDependencyAssembler.swift | 9 +++ 7 files changed, 179 insertions(+) create mode 100644 ByeBoo-iOS/ByeBoo-iOS/Domain/Entity/CommonQuestAnswersEntity.swift create mode 100644 ByeBoo-iOS/ByeBoo-iOS/Domain/UseCase/FetchCommonQuestByDateUseCase.swift create mode 100644 ByeBoo-iOS/ByeBoo-iOS/Presentation/Feature/Quest/ViewModel/CommonQuestViewModel.swift diff --git a/ByeBoo-iOS/ByeBoo-iOS/Data/Repository/QuestsRepository.swift b/ByeBoo-iOS/ByeBoo-iOS/Data/Repository/QuestsRepository.swift index f63b2a65..b7ef2bdd 100644 --- a/ByeBoo-iOS/ByeBoo-iOS/Data/Repository/QuestsRepository.swift +++ b/ByeBoo-iOS/ByeBoo-iOS/Data/Repository/QuestsRepository.swift @@ -8,6 +8,7 @@ import Foundation struct DefaultQuestRepository: QuestsInterface { + private let network: NetworkService private let userDefaultsService: UserDefaultService @@ -118,6 +119,10 @@ struct DefaultQuestRepository: QuestsInterface { try await editQuest(questID: questID, answer: answer, imageKey: imageKey) } + func fetchCommoncQuest(date: String) async throws -> CommonQuestAnswersEntity { + .stub() + } + // MARK: private function private func makeSignedURL(imageKey: String) async throws -> String { @@ -223,4 +228,8 @@ final class MockQuestsRepository: QuestsInterface { func editActiveQuest(questID: Int, answer: String, image: Data?, imageKey: String, isImageChanged: Bool) async throws { self.editActiveQuestCalled = true } + + func fetchCommoncQuest(date: String) async throws -> CommonQuestAnswersEntity { + .stub() + } } diff --git a/ByeBoo-iOS/ByeBoo-iOS/Domain/DomainDependencyAssembler.swift b/ByeBoo-iOS/ByeBoo-iOS/Domain/DomainDependencyAssembler.swift index 31fb6cdc..058335a9 100644 --- a/ByeBoo-iOS/ByeBoo-iOS/Domain/DomainDependencyAssembler.swift +++ b/ByeBoo-iOS/ByeBoo-iOS/Domain/DomainDependencyAssembler.swift @@ -135,6 +135,10 @@ struct DomainDependencyAssembler: DependencyAssembler { DIContainer.shared.register(type: FetchCompletedQuestsUseCase.self) { _ in return DefaultFetchCompletedQuestsUseCase(repository: questRepository) } + + DIContainer.shared.register(type: FetchCommonQuestByDateUseCase.self) { _ in + return DefaultFetchCommonQuestByDateUseCase(repository: questRepository) + } DIContainer.shared.register(type: AutoLoginUseCase.self) { _ in return DefaultAutoLoginUseCase(repository: authRepository) diff --git a/ByeBoo-iOS/ByeBoo-iOS/Domain/Entity/CommonQuestAnswersEntity.swift b/ByeBoo-iOS/ByeBoo-iOS/Domain/Entity/CommonQuestAnswersEntity.swift new file mode 100644 index 00000000..af32f885 --- /dev/null +++ b/ByeBoo-iOS/ByeBoo-iOS/Domain/Entity/CommonQuestAnswersEntity.swift @@ -0,0 +1,46 @@ +// +// CommonQuestAnswersEntity.swift +// ByeBoo-iOS +// +// Created by APPLE on 2/17/26. +// + +import Foundation + +struct CommonQuestAnswersEntity { + let question: String + let answerCount: Int + let isAnswered: Bool + let answers: [CommonQuestAnswerEntity] +} + +struct CommonQuestAnswerEntity { + let answerID: Int + let writer: String + let profileIcon: String + let writtenAt: Date + let content: String +} + +extension CommonQuestAnswersEntity { + static func stub() -> Self { + .init( + question: "연애에서 반복된 문제 패턴 3가지를 생각해보아요", + answerCount: 0, + isAnswered: false, + answers: [] + ) + } +} + +extension CommonQuestAnswerEntity { + static func stub() -> Self { + .init( + answerID: 1, + writer: "장원영", + profileIcon: "SO_SO", + writtenAt: Date.now, + content: "헤어진 지 벌써 일주일이 지났습니다. 처음에는 실감이 안 나서 눈물조차 나오지 않았어요. 그저 멍하니 천장만 바라보며 시간을 보냈습니다. 그런데 오늘 아침, 습관적으로 휴대폰을 확인하다가 더 이상 '굿모닝' 인사를 보낼 사람이 없다는 사실을 깨닫고 그제야 무너져 내렸습니다. 밥알이 모래알 같아서 잘 넘어가지도 않네요. 친구들은 시간이 약이라고, 더 좋은 사람 만날 거라고 위로하지만 지금 당장은 그 어떤 말도 귀에 들어오지 않습니다." + ) + } +} diff --git a/ByeBoo-iOS/ByeBoo-iOS/Domain/Interface/QuestsInterface.swift b/ByeBoo-iOS/ByeBoo-iOS/Domain/Interface/QuestsInterface.swift index ce531b63..8478ab5d 100644 --- a/ByeBoo-iOS/ByeBoo-iOS/Domain/Interface/QuestsInterface.swift +++ b/ByeBoo-iOS/ByeBoo-iOS/Domain/Interface/QuestsInterface.swift @@ -30,4 +30,5 @@ protocol QuestsInterface { image: Data?, imageKey: String, isImageChanged: Bool) async throws + func fetchCommoncQuest(date: String) async throws -> CommonQuestAnswersEntity } diff --git a/ByeBoo-iOS/ByeBoo-iOS/Domain/UseCase/FetchCommonQuestByDateUseCase.swift b/ByeBoo-iOS/ByeBoo-iOS/Domain/UseCase/FetchCommonQuestByDateUseCase.swift new file mode 100644 index 00000000..67ad27b1 --- /dev/null +++ b/ByeBoo-iOS/ByeBoo-iOS/Domain/UseCase/FetchCommonQuestByDateUseCase.swift @@ -0,0 +1,30 @@ +// +// FetchCommonQuestByDateUseCase.swift +// ByeBoo-iOS +// +// Created by APPLE on 2/17/26. +// + +protocol FetchCommonQuestByDateUseCase { + func execute(date: String) async throws -> CommonQuestAnswersEntity +} + +struct DefaultFetchCommonQuestByDateUseCase: FetchCommonQuestByDateUseCase { + + private let repository: QuestsInterface + + init(repository: QuestsInterface) { + self.repository = repository + } + + func execute(date: String) async throws -> CommonQuestAnswersEntity { + try await repository.fetchCommoncQuest(date: date) + } +} + +struct MockFetchCommonQuestByDateUseCase: FetchCommonQuestByDateUseCase { + + func execute(date: String) async throws -> CommonQuestAnswersEntity { + .stub() + } +} diff --git a/ByeBoo-iOS/ByeBoo-iOS/Presentation/Feature/Quest/ViewModel/CommonQuestViewModel.swift b/ByeBoo-iOS/ByeBoo-iOS/Presentation/Feature/Quest/ViewModel/CommonQuestViewModel.swift new file mode 100644 index 00000000..4e30fb9d --- /dev/null +++ b/ByeBoo-iOS/ByeBoo-iOS/Presentation/Feature/Quest/ViewModel/CommonQuestViewModel.swift @@ -0,0 +1,80 @@ +// +// CommonQuestViewModel.swift +// ByeBoo-iOS +// +// Created by APPLE on 2/17/26. +// + +import UIKit + +final class CommonQuestViewModel { + + private var commonQuest: CommonQuestAnswersEntity? + private let fetchCommonQuestByDateUseCase: FetchCommonQuestByDateUseCase + + init(fetchCommonQuestByDateUseCase: FetchCommonQuestByDateUseCase) { + self.fetchCommonQuestByDateUseCase = fetchCommonQuestByDateUseCase + } + + enum Input { + case viewDidLoad + case moveDateButtonDidTap(selectedDate: String) + } + + struct Output { + let commonQuestAnswers: CommonQuestAnswersEntity + } + + func action(_ trigger: Input) -> Output { + let result: CommonQuestAnswersEntity = .stub() + commonQuest = result + return .init(commonQuestAnswers: result) + } +} + +extension CommonQuestViewModel { + + private enum ProfileIcon: String, CaseIterable { + case sad = "SAD" + case selfUnderstanding = "SELF_UNDERSTANDING" + case soso = "SO_SO" + case relieved = "RELIEVED" + + var image: UIImage { + switch self { + case .sad: + return .sadnessBadge + case .selfUnderstanding: + return .selfUnderstandingBadge + case .soso: + return .sosoBadge + case .relieved: + return .relievedBadge + } + } + } + + var question: String { + commonQuest?.question ?? "" + } + + var answersCount: Int { + commonQuest?.answerCount ?? 0 + } + + var isExistAnswer: Bool { + commonQuest?.answerCount != 0 + } + + func getAnswer(at index: Int) -> CommonQuestAnswerEntity { + commonQuest?.answers[index] ?? .stub() + } + + func getProfileIcon(at index: Int) -> UIImage? { + let iconString = commonQuest?.answers[index].profileIcon + let profileIcon = ProfileIcon.allCases + .first { $0.rawValue == iconString }? + .image + return profileIcon + } +} diff --git a/ByeBoo-iOS/ByeBoo-iOS/Presentation/PresentationDependencyAssembler.swift b/ByeBoo-iOS/ByeBoo-iOS/Presentation/PresentationDependencyAssembler.swift index 641d3ed8..52e94048 100644 --- a/ByeBoo-iOS/ByeBoo-iOS/Presentation/PresentationDependencyAssembler.swift +++ b/ByeBoo-iOS/ByeBoo-iOS/Presentation/PresentationDependencyAssembler.swift @@ -258,5 +258,14 @@ struct PresentationDependencyAssembler: DependencyAssembler { getLastJourneyUseCase: getLastJourneyUseCase ) } + + DIContainer.shared.register(type: CommonQuestViewModel.self) { container in + guard let fetchCommonQuestByDateUseCase = container.resolve(type: FetchCommonQuestByDateUseCase.self) else { + ByeBooLogger.error(ByeBooError.DIFailedError) + return + } + + return CommonQuestViewModel(fetchCommonQuestByDateUseCase: fetchCommonQuestByDateUseCase) + } } } From 2c91dbb87881975c7f1eff2c55a42f7e3d901e15 Mon Sep 17 00:00:00 2001 From: heoseungjun Date: Sun, 22 Feb 2026 16:22:14 +0900 Subject: [PATCH 03/20] =?UTF-8?q?refactor:=20#360=20CommonQuestViewControl?= =?UTF-8?q?ler=20=EC=83=9D=EC=84=B1=20=EC=8B=9C=20=EB=B7=B0=EB=AA=A8?= =?UTF-8?q?=EB=8D=B8=20=EC=A3=BC=EC=9E=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ByeBoo-iOS/Presentation/ViewControllerFactory.swift | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/ByeBoo-iOS/ByeBoo-iOS/Presentation/ViewControllerFactory.swift b/ByeBoo-iOS/ByeBoo-iOS/Presentation/ViewControllerFactory.swift index 2b1e6d38..d1e54e42 100644 --- a/ByeBoo-iOS/ByeBoo-iOS/Presentation/ViewControllerFactory.swift +++ b/ByeBoo-iOS/ByeBoo-iOS/Presentation/ViewControllerFactory.swift @@ -195,7 +195,12 @@ final class ViewControllerFactory: ViewControllerFactoryProtocol { } func makeCommonQuestViewController() -> CommonQuestViewController { - return .init() + guard let viewModel = DIContainer.shared.resolve(type: CommonQuestViewModel.self) else { + DIErrorHandle() + fatalError() + } + + return .init(viewModel: viewModel) } } From aec0bb7d3039c38fd1448bffb8013c40aa86db97 Mon Sep 17 00:00:00 2001 From: heoseungjun Date: Sun, 22 Feb 2026 16:24:05 +0900 Subject: [PATCH 04/20] =?UTF-8?q?feat:=20#360=20dequeueReusableCell=20?= =?UTF-8?q?=EB=A9=94=EC=84=9C=EB=93=9C=20=ED=99=95=EC=9E=A5=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Presentation/Extension/UITableView+.swift | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 ByeBoo-iOS/ByeBoo-iOS/Presentation/Extension/UITableView+.swift diff --git a/ByeBoo-iOS/ByeBoo-iOS/Presentation/Extension/UITableView+.swift b/ByeBoo-iOS/ByeBoo-iOS/Presentation/Extension/UITableView+.swift new file mode 100644 index 00000000..4d848671 --- /dev/null +++ b/ByeBoo-iOS/ByeBoo-iOS/Presentation/Extension/UITableView+.swift @@ -0,0 +1,22 @@ +// +// UITableView+.swift +// ByeBoo-iOS +// +// Created by APPLE on 2/22/26. +// + +import UIKit + +extension UITableView { + + func dequeueReusableCell(for indexPath: IndexPath) -> T { + guard let cell = self.dequeueReusableCell( + withIdentifier: T.identifier, + for: indexPath + ) as? T else { + fatalError("identifier에 알맞은 셀을 찾을 수 없음: \(T.identifier)") + } + + return cell + } +} From 5d157bfae6bda040f7db6b0f5cf2dcc360c04c90 Mon Sep 17 00:00:00 2001 From: heoseungjun Date: Sun, 22 Feb 2026 16:24:17 +0900 Subject: [PATCH 05/20] =?UTF-8?q?feat:=20#360=20identifier=20=ED=99=95?= =?UTF-8?q?=EC=9E=A5=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Presentation/Extension/UITableViewCell+.swift | 14 ++++++++++++++ .../Extension/UITableViewHeaderFooterView+.swift | 14 ++++++++++++++ 2 files changed, 28 insertions(+) create mode 100644 ByeBoo-iOS/ByeBoo-iOS/Presentation/Extension/UITableViewCell+.swift create mode 100644 ByeBoo-iOS/ByeBoo-iOS/Presentation/Extension/UITableViewHeaderFooterView+.swift diff --git a/ByeBoo-iOS/ByeBoo-iOS/Presentation/Extension/UITableViewCell+.swift b/ByeBoo-iOS/ByeBoo-iOS/Presentation/Extension/UITableViewCell+.swift new file mode 100644 index 00000000..8d6df180 --- /dev/null +++ b/ByeBoo-iOS/ByeBoo-iOS/Presentation/Extension/UITableViewCell+.swift @@ -0,0 +1,14 @@ +// +// UITableViewCell+.swift +// ByeBoo-iOS +// +// Created by APPLE on 2/17/26. +// + +import UIKit + +extension UITableViewCell { + static var identifier: String { + String(describing: self) + } +} diff --git a/ByeBoo-iOS/ByeBoo-iOS/Presentation/Extension/UITableViewHeaderFooterView+.swift b/ByeBoo-iOS/ByeBoo-iOS/Presentation/Extension/UITableViewHeaderFooterView+.swift new file mode 100644 index 00000000..18c09eb2 --- /dev/null +++ b/ByeBoo-iOS/ByeBoo-iOS/Presentation/Extension/UITableViewHeaderFooterView+.swift @@ -0,0 +1,14 @@ +// +// UITableViewHeaderFooterView+.swift +// ByeBoo-iOS +// +// Created by APPLE on 2/22/26. +// + +import UIKit + +extension UITableViewHeaderFooterView { + static var identifier: String { + String(describing: self) + } +} From b00061810216b288baea3b1b63bb4cab93e7adfc Mon Sep 17 00:00:00 2001 From: heoseungjun Date: Sun, 22 Feb 2026 16:25:49 +0900 Subject: [PATCH 06/20] =?UTF-8?q?style:=20#360=20=EA=B3=B5=ED=86=B5?= =?UTF-8?q?=ED=80=98=EC=8A=A4=ED=8A=B8=20=EB=B7=B0=20=EB=B0=8F=20=EB=B7=B0?= =?UTF-8?q?=EC=BB=A8=ED=8A=B8=EB=A1=A4=EB=9F=AC=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../View/CommonQuest/CommonQuestView.swift | 40 +++++ .../CommonQuestViewController.swift | 167 ++++++++++++++++++ 2 files changed, 207 insertions(+) create mode 100644 ByeBoo-iOS/ByeBoo-iOS/Presentation/Feature/Quest/View/CommonQuest/CommonQuestView.swift diff --git a/ByeBoo-iOS/ByeBoo-iOS/Presentation/Feature/Quest/View/CommonQuest/CommonQuestView.swift b/ByeBoo-iOS/ByeBoo-iOS/Presentation/Feature/Quest/View/CommonQuest/CommonQuestView.swift new file mode 100644 index 00000000..c2ca5221 --- /dev/null +++ b/ByeBoo-iOS/ByeBoo-iOS/Presentation/Feature/Quest/View/CommonQuest/CommonQuestView.swift @@ -0,0 +1,40 @@ +// +// CommonQuestView.swift +// ByeBoo-iOS +// +// Created by APPLE on 2/17/26. +// + +import UIKit + +import SnapKit + +final class CommonQuestView: BaseView { + + private(set) var commonQuestTableView = UITableView() + private(set) var headerView = CommonQuestHeaderView() + + override func setStyle() { + commonQuestTableView.do { + $0.backgroundColor = .grayscale900 + headerView.frame = CGRect( + x: 0, + y: 0, + width: UIScreen.main.bounds.width, + height: 152.adjustedH + ) + $0.tableHeaderView = headerView + $0.sectionHeaderTopPadding = 0 + } + } + + override func setUI() { + addSubview(commonQuestTableView) + } + + override func setLayout() { + commonQuestTableView.snp.makeConstraints { + $0.edges.equalToSuperview() + } + } +} diff --git a/ByeBoo-iOS/ByeBoo-iOS/Presentation/Feature/Quest/ViewController/CommonQuestViewController.swift b/ByeBoo-iOS/ByeBoo-iOS/Presentation/Feature/Quest/ViewController/CommonQuestViewController.swift index 2fefe288..f4da5408 100644 --- a/ByeBoo-iOS/ByeBoo-iOS/Presentation/Feature/Quest/ViewController/CommonQuestViewController.swift +++ b/ByeBoo-iOS/ByeBoo-iOS/Presentation/Feature/Quest/ViewController/CommonQuestViewController.swift @@ -5,15 +5,182 @@ // Created by APPLE on 2/12/26. // +import UIKit + final class CommonQuestViewController: BaseViewController { + private let rootView = CommonQuestView() + private let viewModel: CommonQuestViewModel + + init(viewModel: CommonQuestViewModel) { + self.viewModel = viewModel + super.init(nibName: nil, bundle: nil) + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + override func loadView() { + view = rootView + } + override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) self.navigationController?.setNavigationBarHidden(true, animated: false) } + override func viewDidLoad() { + super.viewDidLoad() + + let _ = viewModel.action(.viewDidLoad) + } + override func viewWillDisappear(_ animated: Bool) { super.viewWillDisappear(animated) self.navigationController?.setNavigationBarHidden(false, animated: false) } + + override func setAddTarget() { + rootView.headerView.historyButton.addTarget( + self, + action: #selector(myAnswerHistoryButtonDidTap), + for: .touchUpInside + ) + } + + override func setDelegate() { + rootView.commonQuestTableView.do { + $0.delegate = self + $0.dataSource = self + $0.register( + CommonQuestAnswersCell.self, + forCellReuseIdentifier: CommonQuestAnswersCell.identifier + ) + $0.register( + CommonQuestContentCell.self, + forCellReuseIdentifier: CommonQuestContentCell.identifier + ) + $0.register( + NoAnswerCell.self, + forCellReuseIdentifier: NoAnswerCell.identifier + ) + $0.register( + DateNavigator.self, + forHeaderFooterViewReuseIdentifier: DateNavigator.identifier + ) + } + } +} + +extension CommonQuestViewController: DateNavigatorDelegate { + + @objc + private func myAnswerHistoryButtonDidTap() {} + + @objc + private func moveWriteAnswerButtonDidTap() {} + + func dateDidChanged(to date: String) { + let _ = viewModel.action( + .moveDateButtonDidTap(selectedDate: date) + ).commonQuestAnswers + rootView.commonQuestTableView.reloadData() + } +} + +extension CommonQuestViewController: UITableViewDelegate { + + func tableView( + _ tableView: UITableView, + heightForRowAt indexPath: IndexPath + ) -> CGFloat { + indexPath.row == 0 ? 141.adjustedH : 171.adjustedH + } + + func tableView( + _ tableView: UITableView, + viewForHeaderInSection section: Int + ) -> UIView? { + guard let navigator = tableView.dequeueReusableHeaderFooterView( + withIdentifier: DateNavigator.identifier + ) as? DateNavigator else { + return nil + } + + return navigator + } + + func tableView( + _ tableView: UITableView, + heightForHeaderInSection section: Int + ) -> CGFloat { + 76.adjustedH + } +} + +extension CommonQuestViewController: UITableViewDataSource { + + func tableView( + _ tableView: UITableView, + numberOfRowsInSection section: Int + ) -> Int { + if viewModel.isExistAnswer { + return 1 + viewModel.answersCount + } + return 2 + } + + func tableView( + _ tableView: UITableView, + cellForRowAt indexPath: IndexPath + ) -> UITableViewCell { + if indexPath.row == .zero { + return dequeueQuestContentCell(from: tableView, indexPath: indexPath) + } + if viewModel.isExistAnswer { + return dequeueQuestAnswersCell(from: tableView, indexPath: indexPath) + } + return dequeueNoAnswerCell(from: tableView, indexPath: indexPath) + } + + private func dequeueQuestContentCell( + from tableView: UITableView, + indexPath: IndexPath + ) -> UITableViewCell { + let cell: CommonQuestContentCell = tableView.dequeueReusableCell(for: indexPath) + + cell.bind( + question: viewModel.question, + answersCount: viewModel.answersCount + ) + cell.moveWriteAnswerButton.addTarget( + self, + action: #selector(moveWriteAnswerButtonDidTap), + for: .touchUpInside + ) + + return cell + } + + private func dequeueQuestAnswersCell( + from tableView: UITableView, + indexPath: IndexPath + ) -> UITableViewCell { + let cell: CommonQuestAnswersCell = tableView.dequeueReusableCell(for: indexPath) + + let answer = viewModel.getAnswer(at: indexPath.row - 1) + let profileIcon = viewModel.getProfileIcon(at: indexPath.row - 1) + cell.bind(profileIcon: profileIcon, answer: answer) + + return cell + } + + private func dequeueNoAnswerCell( + from tableView: UITableView, + indexPath: IndexPath + ) -> UITableViewCell { + let cell: NoAnswerCell = tableView.dequeueReusableCell(for: indexPath) + return cell + } } From bcaf3a54f56b93f0bc6e0c974cf386ae41e6c67a Mon Sep 17 00:00:00 2001 From: heoseungjun Date: Sun, 22 Feb 2026 16:26:15 +0900 Subject: [PATCH 07/20] =?UTF-8?q?style:=20#360=20=ED=85=8C=EC=9D=B4?= =?UTF-8?q?=EB=B8=94=20=EB=B7=B0=EC=9D=98=20=ED=97=A4=EB=8D=94=20=EB=B7=B0?= =?UTF-8?q?=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../CommonQuest/CommonQuestHeaderView.swift | 77 +++++++++++++++++++ 1 file changed, 77 insertions(+) create mode 100644 ByeBoo-iOS/ByeBoo-iOS/Presentation/Feature/Quest/View/CommonQuest/CommonQuestHeaderView.swift diff --git a/ByeBoo-iOS/ByeBoo-iOS/Presentation/Feature/Quest/View/CommonQuest/CommonQuestHeaderView.swift b/ByeBoo-iOS/ByeBoo-iOS/Presentation/Feature/Quest/View/CommonQuest/CommonQuestHeaderView.swift new file mode 100644 index 00000000..7a9b5d57 --- /dev/null +++ b/ByeBoo-iOS/ByeBoo-iOS/Presentation/Feature/Quest/View/CommonQuest/CommonQuestHeaderView.swift @@ -0,0 +1,77 @@ +// +// CommonQuestHeaderView.swift +// ByeBoo-iOS +// +// Created by APPLE on 2/17/26. +// + +import UIKit + +final class CommonQuestHeaderView: BaseView { + + private let titleLabel = UILabel() + private let subtitleLabel = UILabel() + private(set) var historyButton = UIButton() + private let underline = UILabel() + + override func setStyle() { + titleLabel.do { + $0.text = "함께 이별을 극복하는 공간이에요" + $0.textColor = .grayscale50 + $0.textAlignment = .left + $0.font = FontManager.head2M22.font + $0.numberOfLines = 1 + } + subtitleLabel.do { + $0.text = "공통 퀘스트를 통해 나의 이야기를 솔직히 털어놓고,\n타인의 답변도 확인해 보세요" + $0.textColor = .grayscale300 + $0.textAlignment = .left + $0.font = FontManager.body6R14.font + $0.numberOfLines = 2 + } + historyButton.do { + $0.setTitle("나의 답변 모아보기", for: .normal) + $0.setTitleColor(.primary200, for: .normal) + $0.titleLabel?.font = FontManager.cap1M12.font + $0.layer.cornerRadius = 12 + $0.layer.borderColor = UIColor.grayscale800.cgColor + $0.backgroundColor = UIColor.white.withAlphaComponent(0.05) + } + underline.do { + $0.backgroundColor = .grayscale800 + $0.layer.borderColor = UIColor.grayscale800.cgColor + $0.layer.borderWidth = 1 + } + } + + override func setUI() { + addSubviews( + titleLabel, + subtitleLabel, + historyButton, + underline + ) + } + + override func setLayout() { + titleLabel.snp.makeConstraints { + $0.top.equalToSuperview().inset(16.adjustedH) + $0.horizontalEdges.equalToSuperview().inset(24.adjustedW) + } + subtitleLabel.snp.makeConstraints { + $0.top.equalTo(titleLabel.snp.bottom).offset(12.adjustedH) + $0.horizontalEdges.equalToSuperview().inset(24.adjustedW) + } + historyButton.snp.makeConstraints { + $0.top.equalTo(subtitleLabel.snp.bottom).offset(16.adjustedH) + $0.leading.equalToSuperview().inset(24.adjustedW) + $0.width.equalTo(123.adjustedW) + $0.height.equalTo(24.adjustedH) + } + underline.snp.makeConstraints { + $0.top.equalTo(historyButton.snp.bottom).offset(16.adjustedH) + $0.horizontalEdges.equalToSuperview().inset(24.adjustedW) + $0.height.equalTo(1.adjustedH) + } + } +} From 8666e6866c4853f8b2709e23dbe11fa9fcc717bd Mon Sep 17 00:00:00 2001 From: heoseungjun Date: Sun, 22 Feb 2026 16:26:32 +0900 Subject: [PATCH 08/20] =?UTF-8?q?style:=20#360=20=ED=85=8C=EC=9D=B4?= =?UTF-8?q?=EB=B8=94=20=EB=B7=B0=EC=9D=98=20=EC=84=B9=EC=85=98=20=ED=97=A4?= =?UTF-8?q?=EB=8D=94(=EB=82=A0=EC=A7=9C=20=EC=84=A0=ED=83=9D)=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../View/CommonQuest/DateNavigator.swift | 151 ++++++++++++++++++ 1 file changed, 151 insertions(+) create mode 100644 ByeBoo-iOS/ByeBoo-iOS/Presentation/Feature/Quest/View/CommonQuest/DateNavigator.swift diff --git a/ByeBoo-iOS/ByeBoo-iOS/Presentation/Feature/Quest/View/CommonQuest/DateNavigator.swift b/ByeBoo-iOS/ByeBoo-iOS/Presentation/Feature/Quest/View/CommonQuest/DateNavigator.swift new file mode 100644 index 00000000..804d1802 --- /dev/null +++ b/ByeBoo-iOS/ByeBoo-iOS/Presentation/Feature/Quest/View/CommonQuest/DateNavigator.swift @@ -0,0 +1,151 @@ +// +// DateNavigator.swift +// ByeBoo-iOS +// +// Created by APPLE on 2/17/26. +// + +import UIKit + +protocol DateNavigatorDelegate: AnyObject { + func dateDidChanged(to date: String) +} + +final class DateNavigator: UITableViewHeaderFooterView { + + weak var delegate: DateNavigatorDelegate? + + private let calendar = Calendar.current + private let yesterday: Int = -1 + private let tommorw: Int = 1 + private let dateFormatter: DateFormatter = { + let formatter = DateFormatter() + formatter.dateFormat = "M월 dd일" + return formatter + }() + + private(set) var currentDate: Date = .now + private let navigatorStackView = UIStackView() + private(set) var previousButton = UIButton() + private let dateLabel = UILabel() + private(set) var nextButton = UIButton() + + override init(reuseIdentifier: String?) { + super.init(reuseIdentifier: reuseIdentifier) + + setStyle() + setUI() + setLayout() + setAction() + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + private func setStyle() { + self.do { + $0.backgroundView = UIView() + $0.backgroundColor = .grayscale900 + $0.contentView.backgroundColor = .grayscale900 + } + navigatorStackView.do { + $0.axis = .horizontal + $0.spacing = 20 + $0.distribution = .fill + } + previousButton.do { + $0.setImage(.previousOn, for: .normal) + $0.backgroundColor = UIColor.white.withAlphaComponent(0.05) + $0.layer.cornerRadius = 16 + } + dateLabel.do { + $0.text = dateFormatter.string(from: currentDate) + $0.textColor = .grayscale50 + $0.font = FontManager.body2M16.font + } + nextButton.do { + $0.setImage(.nextOff, for: .normal) + $0.backgroundColor = UIColor.white.withAlphaComponent(0.05) + $0.layer.cornerRadius = 16 + $0.isEnabled = true + } + } + + private func setUI() { + addSubview(navigatorStackView) + navigatorStackView.addArrangedSubviews( + previousButton, + dateLabel, + nextButton + ) + } + + private func setLayout() { + navigatorStackView.snp.makeConstraints { + $0.top.equalToSuperview().inset(20.adjustedH) + $0.centerX.equalToSuperview() + $0.bottom.equalToSuperview().inset(24.adjustedH) + } + previousButton.snp.makeConstraints { + $0.size.equalTo(32.adjustedW) + $0.centerY.equalToSuperview() + } + dateLabel.snp.makeConstraints { + $0.centerY.equalToSuperview() + } + nextButton.snp.makeConstraints { + $0.size.equalTo(32.adjustedW) + $0.centerY.equalToSuperview() + } + } + + private func setAction() { + previousButton.addTarget( + self, + action: #selector(moveYesterday), + for: .touchUpInside + ) + nextButton.addTarget( + self, + action: #selector(moveTomorrow), + for: .touchUpInside + ) + } +} + +extension DateNavigator { + + @objc + private func moveYesterday() { + currentDate = getDate(by: yesterday) ?? .now + dateLabel.text = dateFormatter.string(from: currentDate) + updateNextButton() + + // TO-DO : 실제 날짜 형식으로 수정 + delegate?.dateDidChanged(to: currentDate.toString()) + } + + @objc + private func moveTomorrow() { + currentDate = getDate(by: tommorw) ?? .now + dateLabel.text = dateFormatter.string(from: currentDate) + updateNextButton() + + delegate?.dateDidChanged(to: currentDate.toString()) + } + + private func getDate(by value: Int) -> Date? { + calendar.date(byAdding: .day, value: value, to: currentDate) + } + + private func updateNextButton() { + let image: UIImage = isToday ? .nextOff : .nextOn + nextButton.setImage(image, for: .normal) + nextButton.isEnabled = !isToday + } + + private var isToday: Bool { + calendar.isDateInToday(currentDate) + } +} From 5de55a1a1672022e22111fb40d38fda69e75acc0 Mon Sep 17 00:00:00 2001 From: heoseungjun Date: Sun, 22 Feb 2026 16:27:11 +0900 Subject: [PATCH 09/20] =?UTF-8?q?style:=20#360=20=ED=80=98=EC=8A=A4?= =?UTF-8?q?=ED=8A=B8=20=EB=82=B4=EC=9A=A9=20=EC=85=80=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 퀘스트 질문, 마감 기한, 답변 개수, 답변 작성하기 버튼 --- .../Cells/CommonQuestContentCell.swift | 119 ++++++++++++++++++ 1 file changed, 119 insertions(+) create mode 100644 ByeBoo-iOS/ByeBoo-iOS/Presentation/Feature/Quest/View/CommonQuest/Cells/CommonQuestContentCell.swift diff --git a/ByeBoo-iOS/ByeBoo-iOS/Presentation/Feature/Quest/View/CommonQuest/Cells/CommonQuestContentCell.swift b/ByeBoo-iOS/ByeBoo-iOS/Presentation/Feature/Quest/View/CommonQuest/Cells/CommonQuestContentCell.swift new file mode 100644 index 00000000..ddb9f28a --- /dev/null +++ b/ByeBoo-iOS/ByeBoo-iOS/Presentation/Feature/Quest/View/CommonQuest/Cells/CommonQuestContentCell.swift @@ -0,0 +1,119 @@ +// +// CommonQuestContentCell.swift +// ByeBoo-iOS +// +// Created by APPLE on 2/21/26. +// + +import UIKit + +final class CommonQuestContentCell: UITableViewCell { + + private let questionView = UIView() + private let questionMarkLabel = UILabel() + private let questionContentLabel = UILabel() + private let guideTimeLabel = UILabel() + private(set) var moveWriteAnswerButton = UIButton() + private let answersCountLabel = UILabel() + + override init( + style: UITableViewCell.CellStyle, + reuseIdentifier: String? + ) { + super.init(style: style, reuseIdentifier: reuseIdentifier) + + setStyle() + setUI() + setLayout() + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + private func setStyle() { + self.do { + $0.backgroundColor = .grayscale900 + $0.selectionStyle = .none + } + questionMarkLabel.do { + $0.text = "Q." + $0.textColor = .primary200 + $0.font = FontManager.body1Sb16.font + } + questionContentLabel.do { + $0.textColor = .grayscale50 + $0.font = FontManager.sub3M18.font + $0.numberOfLines = 0 + $0.lineBreakStrategy = [] + } + guideTimeLabel.do { + $0.text = "23:59까지 답변 가능해요" + $0.textColor = .grayscale400 + $0.textAlignment = .left + $0.font = FontManager.cap2R12.font + } + moveWriteAnswerButton.do { + $0.setTitle("답변 작성하기", for: .normal) + $0.setTitleColor(.primary500, for: .normal) + $0.layer.cornerRadius = 12 + $0.backgroundColor = .primary100 + } + answersCountLabel.do { + $0.textColor = .grayscale400 + $0.textAlignment = .left + $0.font = FontManager.cap2R12.font + } + } + + private func setUI() { + addSubviews( + questionView, + guideTimeLabel, + moveWriteAnswerButton, + answersCountLabel + ) + questionView.addSubviews( + questionMarkLabel, + questionContentLabel + ) + } + + private func setLayout() { + questionView.snp.makeConstraints { + $0.top.equalToSuperview() + $0.horizontalEdges.equalToSuperview().inset(24.adjustedW) + } + questionMarkLabel.snp.makeConstraints { + $0.top.equalToSuperview() + $0.leading.equalToSuperview() + $0.width.equalTo(17.adjustedW) + } + questionContentLabel.snp.makeConstraints { + $0.verticalEdges.equalToSuperview() + $0.leading.equalTo(questionMarkLabel.snp.trailing).offset(4.adjustedW) + $0.trailing.equalToSuperview() + } + guideTimeLabel.snp.makeConstraints { + $0.top.equalTo(questionView.snp.bottom).offset(12.adjustedH) + $0.leading.equalToSuperview().inset(24.adjustedW) + } + moveWriteAnswerButton.snp.makeConstraints { + $0.top.equalTo(guideTimeLabel.snp.bottom).offset(16.adjustedH) + $0.horizontalEdges.equalToSuperview().inset(24.adjustedW) + $0.height.equalTo(53.adjustedH) + } + answersCountLabel.snp.makeConstraints { + $0.top.equalTo(moveWriteAnswerButton.snp.bottom).offset(24.adjustedH) + $0.horizontalEdges.equalToSuperview().inset(24.adjustedW) + } + } +} + +extension CommonQuestContentCell { + + func bind(question: String, answersCount: Int) { + questionContentLabel.text = question + guideTimeLabel.text = "\(answersCount)개의 답변" + } +} From b6083bc120e3acb0fb515e3e3452eb09a8694bf2 Mon Sep 17 00:00:00 2001 From: heoseungjun Date: Sun, 22 Feb 2026 16:27:35 +0900 Subject: [PATCH 10/20] =?UTF-8?q?style:=20#360=20=EA=B3=B5=ED=86=B5?= =?UTF-8?q?=ED=80=98=EC=8A=A4=ED=8A=B8=20=EB=8B=B5=EB=B3=80=EC=9D=B4=20?= =?UTF-8?q?=EC=A1=B4=EC=9E=AC=ED=95=98=EB=8A=94=20=EA=B2=BD=EC=9A=B0?= =?UTF-8?q?=EC=9D=98=20=ED=85=8C=EC=9D=B4=EB=B8=94=20=EB=B7=B0=20=EC=85=80?= =?UTF-8?q?=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Cells/CommonQuestAnswersCell.swift | 120 ++++++++++++++++++ 1 file changed, 120 insertions(+) create mode 100644 ByeBoo-iOS/ByeBoo-iOS/Presentation/Feature/Quest/View/CommonQuest/Cells/CommonQuestAnswersCell.swift diff --git a/ByeBoo-iOS/ByeBoo-iOS/Presentation/Feature/Quest/View/CommonQuest/Cells/CommonQuestAnswersCell.swift b/ByeBoo-iOS/ByeBoo-iOS/Presentation/Feature/Quest/View/CommonQuest/Cells/CommonQuestAnswersCell.swift new file mode 100644 index 00000000..c6053a58 --- /dev/null +++ b/ByeBoo-iOS/ByeBoo-iOS/Presentation/Feature/Quest/View/CommonQuest/Cells/CommonQuestAnswersCell.swift @@ -0,0 +1,120 @@ +// +// CommonQuestAnswersCell.swift +// ByeBoo-iOS +// +// Created by APPLE on 2/17/26. +// + +import UIKit + +final class CommonQuestAnswersCell: UITableViewCell { + + private let dateFormatter: DateFormatter = { + let formatter = DateFormatter() + formatter.dateFormat = "yyyy.MM.dd." + return formatter + }() + + private let containerView = UIView() + private let userIconView = UIImageView() + private let userNicknameLabel = UILabel() + private let answerContentLabel = UILabel() + private let writtenDateLabel = UILabel() + + override init( + style: UITableViewCell.CellStyle, + reuseIdentifier: String? + ) { + super.init(style: style, reuseIdentifier: reuseIdentifier) + + setStyle() + setUI() + setLayout() + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + private func setStyle() { + self.do { + $0.backgroundColor = .clear + $0.selectionStyle = .none + } + containerView.do { + $0.layer.cornerRadius = 12 + $0.backgroundColor = UIColor.white.withAlphaComponent(0.05) + } + userNicknameLabel.do { + $0.textColor = .grayscale200 + $0.font = FontManager.body6R14.font + } + answerContentLabel.do { + $0.textColor = .grayscale100 + $0.font = FontManager.body3R16.font + $0.numberOfLines = 0 + } + writtenDateLabel.do { + $0.textColor = .grayscale400 + $0.font = FontManager.body6R14.font // TO-DO : 폰트 NotoSans로 수정하기 + } + } + + private func setUI() { + addSubview(containerView) + containerView.addSubviews( + userIconView, + userNicknameLabel, + answerContentLabel, + writtenDateLabel + ) + } + + private func setLayout() { + containerView.snp.makeConstraints { + $0.top.equalToSuperview().inset(24.adjustedH) + $0.horizontalEdges.equalToSuperview().inset(24.adjustedW) + $0.bottom.equalToSuperview() + } + userIconView.snp.makeConstraints { + $0.top.equalToSuperview().inset(16.adjustedH) + $0.leading.equalToSuperview().inset(24.adjustedW) + $0.size.equalTo(20.adjustedW) + } + userNicknameLabel.snp.makeConstraints { + $0.top.equalToSuperview().inset(16.adjustedH) + $0.leading.equalTo(userIconView.snp.trailing).offset(4.adjustedW) + $0.centerY.equalTo(userIconView.snp.centerY) + } + answerContentLabel.snp.makeConstraints { + $0.top.equalTo(userIconView.snp.bottom).offset(12.adjustedH) + $0.horizontalEdges.equalToSuperview().inset(24.adjustedW) + $0.height.equalTo(47.adjustedH) + } + writtenDateLabel.snp.makeConstraints { + $0.top.equalTo(answerContentLabel.snp.bottom).offset(20.adjustedH) + $0.leading.equalToSuperview().inset(24.adjustedW) + $0.bottom.equalToSuperview().inset(16.adjustedH) + } + } +} + +extension CommonQuestAnswersCell { + + func bind( + profileIcon: UIImage?, + answer: CommonQuestAnswerEntity + ) { + if let profileIcon { + userIconView.image = profileIcon + } else { + userIconView.do { + $0.backgroundColor = .grayscale600 + $0.layer.cornerRadius = 10 + } + } + userNicknameLabel.text = answer.writer + answerContentLabel.text = answer.content + writtenDateLabel.text = dateFormatter.string(from: answer.writtenAt) + } +} From 4d5fc28a9238bf783f14411bc318dd4133dff2c1 Mon Sep 17 00:00:00 2001 From: heoseungjun Date: Sun, 22 Feb 2026 16:27:50 +0900 Subject: [PATCH 11/20] =?UTF-8?q?style:=20#360=20=EA=B3=B5=ED=86=B5?= =?UTF-8?q?=ED=80=98=EC=8A=A4=ED=8A=B8=20=EB=8B=B5=EB=B3=80=EC=9D=B4=20?= =?UTF-8?q?=EC=97=86=EB=8A=94=20=EA=B2=BD=EC=9A=B0=EC=9D=98=20=ED=85=8C?= =?UTF-8?q?=EC=9D=B4=EB=B8=94=20=EB=B7=B0=20=EC=85=80=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../View/CommonQuest/Cells/NoAnswerCell.swift | 53 +++++++++++++++++++ 1 file changed, 53 insertions(+) create mode 100644 ByeBoo-iOS/ByeBoo-iOS/Presentation/Feature/Quest/View/CommonQuest/Cells/NoAnswerCell.swift diff --git a/ByeBoo-iOS/ByeBoo-iOS/Presentation/Feature/Quest/View/CommonQuest/Cells/NoAnswerCell.swift b/ByeBoo-iOS/ByeBoo-iOS/Presentation/Feature/Quest/View/CommonQuest/Cells/NoAnswerCell.swift new file mode 100644 index 00000000..5f3b758a --- /dev/null +++ b/ByeBoo-iOS/ByeBoo-iOS/Presentation/Feature/Quest/View/CommonQuest/Cells/NoAnswerCell.swift @@ -0,0 +1,53 @@ +// +// NoAnswerView.swift +// ByeBoo-iOS +// +// Created by APPLE on 2/19/26. +// + +import UIKit + +final class NoAnswerCell: UITableViewCell { + + private let noAnswerLabel = UILabel() + + override init( + style: UITableViewCell.CellStyle, + reuseIdentifier: String? + ) { + super.init(style: style, reuseIdentifier: reuseIdentifier) + + setStyle() + setUI() + setLayout() + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + private func setStyle() { + self.do { + $0.backgroundColor = .grayscale900 + $0.selectionStyle = .none + } + noAnswerLabel.do { + $0.text = "아직 작성된 답변이 없어요!" + $0.textColor = .grayscale400 + $0.textAlignment = .center + $0.font = FontManager.body6R14.font + } + } + + private func setUI() { + addSubview(noAnswerLabel) + } + + private func setLayout() { + noAnswerLabel.snp.makeConstraints { + $0.top.equalToSuperview().inset(70.adjustedH) + $0.horizontalEdges.equalToSuperview().inset(80.adjustedW) + $0.bottom.equalToSuperview().inset(51.adjustedH) + } + } +} From 7e9654a64b859cd0b516b299f2622a880d5b710d Mon Sep 17 00:00:00 2001 From: heoseungjun Date: Sun, 22 Feb 2026 21:19:48 +0900 Subject: [PATCH 12/20] =?UTF-8?q?refactor:=20#360=20dateFormatter=EB=A5=BC?= =?UTF-8?q?=20=EB=B7=B0=EC=BB=A8=ED=8A=B8=EB=A1=A4=EB=9F=AC=EB=A1=9C=20?= =?UTF-8?q?=EC=9D=B4=EB=8F=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../CommonQuest/Cells/CommonQuestAnswersCell.swift | 13 ++++--------- .../ViewController/CommonQuestViewController.swift | 8 +++++++- .../Quest/ViewModel/CommonQuestViewModel.swift | 4 ++++ 3 files changed, 15 insertions(+), 10 deletions(-) diff --git a/ByeBoo-iOS/ByeBoo-iOS/Presentation/Feature/Quest/View/CommonQuest/Cells/CommonQuestAnswersCell.swift b/ByeBoo-iOS/ByeBoo-iOS/Presentation/Feature/Quest/View/CommonQuest/Cells/CommonQuestAnswersCell.swift index c6053a58..557c2437 100644 --- a/ByeBoo-iOS/ByeBoo-iOS/Presentation/Feature/Quest/View/CommonQuest/Cells/CommonQuestAnswersCell.swift +++ b/ByeBoo-iOS/ByeBoo-iOS/Presentation/Feature/Quest/View/CommonQuest/Cells/CommonQuestAnswersCell.swift @@ -9,12 +9,6 @@ import UIKit final class CommonQuestAnswersCell: UITableViewCell { - private let dateFormatter: DateFormatter = { - let formatter = DateFormatter() - formatter.dateFormat = "yyyy.MM.dd." - return formatter - }() - private let containerView = UIView() private let userIconView = UIImageView() private let userNicknameLabel = UILabel() @@ -56,7 +50,7 @@ final class CommonQuestAnswersCell: UITableViewCell { } writtenDateLabel.do { $0.textColor = .grayscale400 - $0.font = FontManager.body6R14.font // TO-DO : 폰트 NotoSans로 수정하기 + $0.font = FontManager.body6R14.font } } @@ -103,7 +97,8 @@ extension CommonQuestAnswersCell { func bind( profileIcon: UIImage?, - answer: CommonQuestAnswerEntity + answer: CommonQuestAnswerEntity, + writtenAt: String ) { if let profileIcon { userIconView.image = profileIcon @@ -115,6 +110,6 @@ extension CommonQuestAnswersCell { } userNicknameLabel.text = answer.writer answerContentLabel.text = answer.content - writtenDateLabel.text = dateFormatter.string(from: answer.writtenAt) + writtenDateLabel.text = writtenAt } } diff --git a/ByeBoo-iOS/ByeBoo-iOS/Presentation/Feature/Quest/ViewController/CommonQuestViewController.swift b/ByeBoo-iOS/ByeBoo-iOS/Presentation/Feature/Quest/ViewController/CommonQuestViewController.swift index f4da5408..54bae52b 100644 --- a/ByeBoo-iOS/ByeBoo-iOS/Presentation/Feature/Quest/ViewController/CommonQuestViewController.swift +++ b/ByeBoo-iOS/ByeBoo-iOS/Presentation/Feature/Quest/ViewController/CommonQuestViewController.swift @@ -9,6 +9,11 @@ import UIKit final class CommonQuestViewController: BaseViewController { + private let dateFormatter: DateFormatter = { + let formatter = DateFormatter() + formatter.dateFormat = "yyyy.MM.dd." + return formatter + }() private let rootView = CommonQuestView() private let viewModel: CommonQuestViewModel @@ -171,7 +176,8 @@ extension CommonQuestViewController: UITableViewDataSource { let answer = viewModel.getAnswer(at: indexPath.row - 1) let profileIcon = viewModel.getProfileIcon(at: indexPath.row - 1) - cell.bind(profileIcon: profileIcon, answer: answer) + let writtenAt = dateFormatter.string(from: viewModel.getWrittenAt(at: indexPath.row - 1)) + cell.bind(profileIcon: profileIcon, answer: answer, writtenAt: writtenAt) return cell } diff --git a/ByeBoo-iOS/ByeBoo-iOS/Presentation/Feature/Quest/ViewModel/CommonQuestViewModel.swift b/ByeBoo-iOS/ByeBoo-iOS/Presentation/Feature/Quest/ViewModel/CommonQuestViewModel.swift index 4e30fb9d..ad6b8b5e 100644 --- a/ByeBoo-iOS/ByeBoo-iOS/Presentation/Feature/Quest/ViewModel/CommonQuestViewModel.swift +++ b/ByeBoo-iOS/ByeBoo-iOS/Presentation/Feature/Quest/ViewModel/CommonQuestViewModel.swift @@ -77,4 +77,8 @@ extension CommonQuestViewModel { .image return profileIcon } + + func getWrittenAt(at index: Int) -> Date { + commonQuest?.answers[index].writtenAt ?? .now + } } From 1695f5a41895a71e545fa587df9f1d11bb9eb5e8 Mon Sep 17 00:00:00 2001 From: heoseungjun Date: Sun, 22 Feb 2026 21:24:26 +0900 Subject: [PATCH 13/20] =?UTF-8?q?refactor:=20#360=20fatalError=EA=B0=80=20?= =?UTF-8?q?=EB=B0=9C=EC=83=9D=ED=95=98=EC=A7=80=20=EC=95=8A=EB=8F=84?= =?UTF-8?q?=EB=A1=9D=20=EB=B0=A9=EC=A7=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ByeBoo-iOS/ByeBoo-iOS/Presentation/Extension/UITableView+.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ByeBoo-iOS/ByeBoo-iOS/Presentation/Extension/UITableView+.swift b/ByeBoo-iOS/ByeBoo-iOS/Presentation/Extension/UITableView+.swift index 4d848671..39099b9d 100644 --- a/ByeBoo-iOS/ByeBoo-iOS/Presentation/Extension/UITableView+.swift +++ b/ByeBoo-iOS/ByeBoo-iOS/Presentation/Extension/UITableView+.swift @@ -14,7 +14,7 @@ extension UITableView { withIdentifier: T.identifier, for: indexPath ) as? T else { - fatalError("identifier에 알맞은 셀을 찾을 수 없음: \(T.identifier)") + return T() } return cell From 29a1420195b9cc14b0e24548e5f1009c65d07168 Mon Sep 17 00:00:00 2001 From: heoseungjun Date: Mon, 23 Feb 2026 15:40:56 +0900 Subject: [PATCH 14/20] =?UTF-8?q?refactor:=20#360=20=EB=B2=84=ED=8A=BC=20?= =?UTF-8?q?=ED=83=80=EC=9D=B4=ED=8B=80=20=EC=83=89=EC=83=81=20=EC=84=A4?= =?UTF-8?q?=EC=A0=95=20=EC=BD=94=EB=93=9C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Presentation/Extension/UIButton+.swift | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/ByeBoo-iOS/ByeBoo-iOS/Presentation/Extension/UIButton+.swift b/ByeBoo-iOS/ByeBoo-iOS/Presentation/Extension/UIButton+.swift index f3a570e7..0c3ecacf 100644 --- a/ByeBoo-iOS/ByeBoo-iOS/Presentation/Extension/UIButton+.swift +++ b/ByeBoo-iOS/ByeBoo-iOS/Presentation/Extension/UIButton+.swift @@ -27,20 +27,18 @@ extension UIButton { text: String? = nil, color: UIColor, for state: UIControl.State = .normal) { - titleLabel?.font = style.font - titleLabel?.textColor = color let targetText = text ?? title(for: state) - guard let targetText else { return } + guard let targetText = targetText else { return } - var attributes: [NSAttributedString.Key: Any] = [ + let attributes: [NSAttributedString.Key: Any] = [ .font: style.font, - .kern: style.kern + .kern: style.kern, + .foregroundColor: color ] - if let titleColor = titleColor(for: state) { - attributes[.foregroundColor] = titleColor - } - - setAttributedTitle(NSAttributedString(string: targetText, attributes: attributes), for: state) + setAttributedTitle( + NSAttributedString(string: targetText, attributes: attributes), + for: state + ) } } From 507b27f52fbec6f78e740b24e372df9ee343d8c4 Mon Sep 17 00:00:00 2001 From: heoseungjun Date: Mon, 23 Feb 2026 15:41:15 +0900 Subject: [PATCH 15/20] =?UTF-8?q?refactor:=20#360=20applyByeBooFont=20?= =?UTF-8?q?=EB=A9=94=EC=84=9C=EB=93=9C=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Cells/CommonQuestAnswersCell.swift | 26 +++++----- .../Cells/CommonQuestContentCell.swift | 47 ++++++++++--------- .../View/CommonQuest/Cells/NoAnswerCell.swift | 12 ++--- .../CommonQuest/CommonQuestHeaderView.swift | 36 +++++++------- .../View/CommonQuest/DateNavigator.swift | 10 ++-- 5 files changed, 69 insertions(+), 62 deletions(-) diff --git a/ByeBoo-iOS/ByeBoo-iOS/Presentation/Feature/Quest/View/CommonQuest/Cells/CommonQuestAnswersCell.swift b/ByeBoo-iOS/ByeBoo-iOS/Presentation/Feature/Quest/View/CommonQuest/Cells/CommonQuestAnswersCell.swift index 557c2437..487d7061 100644 --- a/ByeBoo-iOS/ByeBoo-iOS/Presentation/Feature/Quest/View/CommonQuest/Cells/CommonQuestAnswersCell.swift +++ b/ByeBoo-iOS/ByeBoo-iOS/Presentation/Feature/Quest/View/CommonQuest/Cells/CommonQuestAnswersCell.swift @@ -39,19 +39,19 @@ final class CommonQuestAnswersCell: UITableViewCell { $0.layer.cornerRadius = 12 $0.backgroundColor = UIColor.white.withAlphaComponent(0.05) } - userNicknameLabel.do { - $0.textColor = .grayscale200 - $0.font = FontManager.body6R14.font - } - answerContentLabel.do { - $0.textColor = .grayscale100 - $0.font = FontManager.body3R16.font - $0.numberOfLines = 0 - } - writtenDateLabel.do { - $0.textColor = .grayscale400 - $0.font = FontManager.body6R14.font - } + userNicknameLabel.applyByeBooFont( + style: .body6R14, + color: .grayscale200 + ) + answerContentLabel.applyByeBooFont( + style: .body3R16, + color: .grayscale100, + numberOfLines: 0 + ) + writtenDateLabel.applyByeBooFont( + style: .body6R14, + color: .grayscale400 + ) } private func setUI() { diff --git a/ByeBoo-iOS/ByeBoo-iOS/Presentation/Feature/Quest/View/CommonQuest/Cells/CommonQuestContentCell.swift b/ByeBoo-iOS/ByeBoo-iOS/Presentation/Feature/Quest/View/CommonQuest/Cells/CommonQuestContentCell.swift index ddb9f28a..a36db95b 100644 --- a/ByeBoo-iOS/ByeBoo-iOS/Presentation/Feature/Quest/View/CommonQuest/Cells/CommonQuestContentCell.swift +++ b/ByeBoo-iOS/ByeBoo-iOS/Presentation/Feature/Quest/View/CommonQuest/Cells/CommonQuestContentCell.swift @@ -36,34 +36,39 @@ final class CommonQuestContentCell: UITableViewCell { $0.backgroundColor = .grayscale900 $0.selectionStyle = .none } - questionMarkLabel.do { - $0.text = "Q." - $0.textColor = .primary200 - $0.font = FontManager.body1Sb16.font - } + questionMarkLabel.applyByeBooFont( + style: .body1Sb16, + text: "Q.", + color: .primary200 + ) questionContentLabel.do { - $0.textColor = .grayscale50 - $0.font = FontManager.sub3M18.font - $0.numberOfLines = 0 + $0.applyByeBooFont( + style: .sub3M18, + color: .grayscale50, + numberOfLines: 0 + ) $0.lineBreakStrategy = [] } - guideTimeLabel.do { - $0.text = "23:59까지 답변 가능해요" - $0.textColor = .grayscale400 - $0.textAlignment = .left - $0.font = FontManager.cap2R12.font - } + guideTimeLabel.applyByeBooFont( + style: .cap2R12, + text: "23:59까지 답변 가능해요", + color: .grayscale400, + textAlignment: .left + ) moveWriteAnswerButton.do { - $0.setTitle("답변 작성하기", for: .normal) - $0.setTitleColor(.primary500, for: .normal) + $0.applyByeBooFont( + style: .body2M16, + text: "답변 작성하기", + color: .primary500 + ) $0.layer.cornerRadius = 12 $0.backgroundColor = .primary100 } - answersCountLabel.do { - $0.textColor = .grayscale400 - $0.textAlignment = .left - $0.font = FontManager.cap2R12.font - } + answersCountLabel.applyByeBooFont( + style: .cap2R12, + color: .grayscale400, + textAlignment: .left + ) } private func setUI() { diff --git a/ByeBoo-iOS/ByeBoo-iOS/Presentation/Feature/Quest/View/CommonQuest/Cells/NoAnswerCell.swift b/ByeBoo-iOS/ByeBoo-iOS/Presentation/Feature/Quest/View/CommonQuest/Cells/NoAnswerCell.swift index 5f3b758a..c97c76a9 100644 --- a/ByeBoo-iOS/ByeBoo-iOS/Presentation/Feature/Quest/View/CommonQuest/Cells/NoAnswerCell.swift +++ b/ByeBoo-iOS/ByeBoo-iOS/Presentation/Feature/Quest/View/CommonQuest/Cells/NoAnswerCell.swift @@ -31,12 +31,12 @@ final class NoAnswerCell: UITableViewCell { $0.backgroundColor = .grayscale900 $0.selectionStyle = .none } - noAnswerLabel.do { - $0.text = "아직 작성된 답변이 없어요!" - $0.textColor = .grayscale400 - $0.textAlignment = .center - $0.font = FontManager.body6R14.font - } + noAnswerLabel.applyByeBooFont( + style: .body6R14, + text: "아직 작성된 답변이 없어요!", + color: .grayscale400, + textAlignment: .center + ) } private func setUI() { diff --git a/ByeBoo-iOS/ByeBoo-iOS/Presentation/Feature/Quest/View/CommonQuest/CommonQuestHeaderView.swift b/ByeBoo-iOS/ByeBoo-iOS/Presentation/Feature/Quest/View/CommonQuest/CommonQuestHeaderView.swift index 7a9b5d57..295285d2 100644 --- a/ByeBoo-iOS/ByeBoo-iOS/Presentation/Feature/Quest/View/CommonQuest/CommonQuestHeaderView.swift +++ b/ByeBoo-iOS/ByeBoo-iOS/Presentation/Feature/Quest/View/CommonQuest/CommonQuestHeaderView.swift @@ -15,24 +15,26 @@ final class CommonQuestHeaderView: BaseView { private let underline = UILabel() override func setStyle() { - titleLabel.do { - $0.text = "함께 이별을 극복하는 공간이에요" - $0.textColor = .grayscale50 - $0.textAlignment = .left - $0.font = FontManager.head2M22.font - $0.numberOfLines = 1 - } - subtitleLabel.do { - $0.text = "공통 퀘스트를 통해 나의 이야기를 솔직히 털어놓고,\n타인의 답변도 확인해 보세요" - $0.textColor = .grayscale300 - $0.textAlignment = .left - $0.font = FontManager.body6R14.font - $0.numberOfLines = 2 - } + titleLabel.applyByeBooFont( + style: .head2M22, + text: "함께 이별을 극복하는 공간이에요", + color: .grayscale50, + textAlignment: .left, + numberOfLines: 1 + ) + subtitleLabel.applyByeBooFont( + style: .body6R14, + text: "공통 퀘스트를 통해 나의 이야기를 솔직히 털어놓고,\n타인의 답변도 확인해 보세요", + color: .grayscale300, + textAlignment: .left, + numberOfLines: 2 + ) historyButton.do { - $0.setTitle("나의 답변 모아보기", for: .normal) - $0.setTitleColor(.primary200, for: .normal) - $0.titleLabel?.font = FontManager.cap1M12.font + $0.applyByeBooFont( + style: .cap1M12, + text: "나의 답변 모아보기", + color: .primary200 + ) $0.layer.cornerRadius = 12 $0.layer.borderColor = UIColor.grayscale800.cgColor $0.backgroundColor = UIColor.white.withAlphaComponent(0.05) diff --git a/ByeBoo-iOS/ByeBoo-iOS/Presentation/Feature/Quest/View/CommonQuest/DateNavigator.swift b/ByeBoo-iOS/ByeBoo-iOS/Presentation/Feature/Quest/View/CommonQuest/DateNavigator.swift index 804d1802..62472745 100644 --- a/ByeBoo-iOS/ByeBoo-iOS/Presentation/Feature/Quest/View/CommonQuest/DateNavigator.swift +++ b/ByeBoo-iOS/ByeBoo-iOS/Presentation/Feature/Quest/View/CommonQuest/DateNavigator.swift @@ -59,11 +59,11 @@ final class DateNavigator: UITableViewHeaderFooterView { $0.backgroundColor = UIColor.white.withAlphaComponent(0.05) $0.layer.cornerRadius = 16 } - dateLabel.do { - $0.text = dateFormatter.string(from: currentDate) - $0.textColor = .grayscale50 - $0.font = FontManager.body2M16.font - } + dateLabel.applyByeBooFont( + style: .body2M16, + text: dateFormatter.string(from: currentDate), + color: .grayscale50 + ) nextButton.do { $0.setImage(.nextOff, for: .normal) $0.backgroundColor = UIColor.white.withAlphaComponent(0.05) From 45d9bf725e1383c33aa01a33632d325c5dfb0328 Mon Sep 17 00:00:00 2001 From: heoseungjun Date: Mon, 23 Feb 2026 15:43:59 +0900 Subject: [PATCH 16/20] =?UTF-8?q?refactor:=20#360=20white5=20=EC=83=89?= =?UTF-8?q?=EC=83=81=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Quest/View/CommonQuest/Cells/CommonQuestAnswersCell.swift | 2 +- .../Quest/View/CommonQuest/CommonQuestHeaderView.swift | 2 +- .../Feature/Quest/View/CommonQuest/DateNavigator.swift | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/ByeBoo-iOS/ByeBoo-iOS/Presentation/Feature/Quest/View/CommonQuest/Cells/CommonQuestAnswersCell.swift b/ByeBoo-iOS/ByeBoo-iOS/Presentation/Feature/Quest/View/CommonQuest/Cells/CommonQuestAnswersCell.swift index 487d7061..fc78df10 100644 --- a/ByeBoo-iOS/ByeBoo-iOS/Presentation/Feature/Quest/View/CommonQuest/Cells/CommonQuestAnswersCell.swift +++ b/ByeBoo-iOS/ByeBoo-iOS/Presentation/Feature/Quest/View/CommonQuest/Cells/CommonQuestAnswersCell.swift @@ -37,7 +37,7 @@ final class CommonQuestAnswersCell: UITableViewCell { } containerView.do { $0.layer.cornerRadius = 12 - $0.backgroundColor = UIColor.white.withAlphaComponent(0.05) + $0.backgroundColor = .white5 } userNicknameLabel.applyByeBooFont( style: .body6R14, diff --git a/ByeBoo-iOS/ByeBoo-iOS/Presentation/Feature/Quest/View/CommonQuest/CommonQuestHeaderView.swift b/ByeBoo-iOS/ByeBoo-iOS/Presentation/Feature/Quest/View/CommonQuest/CommonQuestHeaderView.swift index 295285d2..eb54018f 100644 --- a/ByeBoo-iOS/ByeBoo-iOS/Presentation/Feature/Quest/View/CommonQuest/CommonQuestHeaderView.swift +++ b/ByeBoo-iOS/ByeBoo-iOS/Presentation/Feature/Quest/View/CommonQuest/CommonQuestHeaderView.swift @@ -37,7 +37,7 @@ final class CommonQuestHeaderView: BaseView { ) $0.layer.cornerRadius = 12 $0.layer.borderColor = UIColor.grayscale800.cgColor - $0.backgroundColor = UIColor.white.withAlphaComponent(0.05) + $0.backgroundColor = .white5 } underline.do { $0.backgroundColor = .grayscale800 diff --git a/ByeBoo-iOS/ByeBoo-iOS/Presentation/Feature/Quest/View/CommonQuest/DateNavigator.swift b/ByeBoo-iOS/ByeBoo-iOS/Presentation/Feature/Quest/View/CommonQuest/DateNavigator.swift index 62472745..c923a586 100644 --- a/ByeBoo-iOS/ByeBoo-iOS/Presentation/Feature/Quest/View/CommonQuest/DateNavigator.swift +++ b/ByeBoo-iOS/ByeBoo-iOS/Presentation/Feature/Quest/View/CommonQuest/DateNavigator.swift @@ -56,7 +56,7 @@ final class DateNavigator: UITableViewHeaderFooterView { } previousButton.do { $0.setImage(.previousOn, for: .normal) - $0.backgroundColor = UIColor.white.withAlphaComponent(0.05) + $0.backgroundColor = .white5 $0.layer.cornerRadius = 16 } dateLabel.applyByeBooFont( @@ -66,7 +66,7 @@ final class DateNavigator: UITableViewHeaderFooterView { ) nextButton.do { $0.setImage(.nextOff, for: .normal) - $0.backgroundColor = UIColor.white.withAlphaComponent(0.05) + $0.backgroundColor = .white5 $0.layer.cornerRadius = 16 $0.isEnabled = true } From 04cc8a06669a976bca98cf5431456bfd531a5d9f Mon Sep 17 00:00:00 2001 From: heoseungjun Date: Mon, 23 Feb 2026 16:05:06 +0900 Subject: [PATCH 17/20] =?UTF-8?q?refactor:=20#360=20ByeBooTipTag=20?= =?UTF-8?q?=EC=95=88=EC=97=90=20=EB=93=A4=EC=96=B4=EA=B0=88=20=ED=85=8D?= =?UTF-8?q?=EC=8A=A4=ED=8A=B8=EB=A5=BC=20=EC=A3=BC=EC=9E=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ByeBoo-iOS/Presentation/Common/Tag/ByeBooTipTag.swift | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/ByeBoo-iOS/ByeBoo-iOS/Presentation/Common/Tag/ByeBooTipTag.swift b/ByeBoo-iOS/ByeBoo-iOS/Presentation/Common/Tag/ByeBooTipTag.swift index 24463e38..c038df1d 100644 --- a/ByeBoo-iOS/ByeBoo-iOS/Presentation/Common/Tag/ByeBooTipTag.swift +++ b/ByeBoo-iOS/ByeBoo-iOS/Presentation/Common/Tag/ByeBooTipTag.swift @@ -11,8 +11,11 @@ import SnapKit import Then final class ByeBooTipTag: UIButton { - override init(frame: CGRect) { - super.init(frame: frame) + + init(text: String) { + super.init(frame: .zero) + + setTitle(text, for: .normal) setStyle() setLayout() } @@ -25,7 +28,6 @@ final class ByeBooTipTag: UIButton { self.do { $0.applyByeBooFont( style: .cap1M12, - text: "작성 TIP", color: .primary200 ) $0.backgroundColor = .white5 From 075cbc8a9b7b874e4434e3e0fa57ef7c9797f54c Mon Sep 17 00:00:00 2001 From: heoseungjun Date: Mon, 23 Feb 2026 16:05:26 +0900 Subject: [PATCH 18/20] =?UTF-8?q?refactor:=20#360=20ByeBooTipTag=20?= =?UTF-8?q?=EC=B5=9C=EC=86=8C=20=EB=84=88=EB=B9=84=20=EC=84=A4=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ByeBoo-iOS/Presentation/Common/Tag/ByeBooTipTag.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ByeBoo-iOS/ByeBoo-iOS/Presentation/Common/Tag/ByeBooTipTag.swift b/ByeBoo-iOS/ByeBoo-iOS/Presentation/Common/Tag/ByeBooTipTag.swift index c038df1d..0edab116 100644 --- a/ByeBoo-iOS/ByeBoo-iOS/Presentation/Common/Tag/ByeBooTipTag.swift +++ b/ByeBoo-iOS/ByeBoo-iOS/Presentation/Common/Tag/ByeBooTipTag.swift @@ -39,7 +39,7 @@ final class ByeBooTipTag: UIButton { private func setLayout() { self.snp.makeConstraints { - $0.width.equalTo(76.adjustedW) + $0.width.greaterThanOrEqualTo(76.adjustedW) $0.height.equalTo(24.adjustedH) } } From a875874c8554b62807eab437605f0fa6b7a00587 Mon Sep 17 00:00:00 2001 From: heoseungjun Date: Mon, 23 Feb 2026 16:05:44 +0900 Subject: [PATCH 19/20] =?UTF-8?q?refactor:=20#360=20=EC=88=98=EC=A0=95?= =?UTF-8?q?=EB=90=9C=20ByeBooTipTag=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ByeBoo-iOS/Presentation/Common/Modal/QuestModalView.swift | 2 +- .../Feature/WriteQuest/Common/WriteQuestTitleView.swift | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ByeBoo-iOS/ByeBoo-iOS/Presentation/Common/Modal/QuestModalView.swift b/ByeBoo-iOS/ByeBoo-iOS/Presentation/Common/Modal/QuestModalView.swift index e5e1a9e5..bb91edc3 100644 --- a/ByeBoo-iOS/ByeBoo-iOS/Presentation/Common/Modal/QuestModalView.swift +++ b/ByeBoo-iOS/ByeBoo-iOS/Presentation/Common/Modal/QuestModalView.swift @@ -18,7 +18,7 @@ final class QuestModalView: BaseView, ModalProtocol { private let imageView = UIImageView() private let questLabel = UILabel() private let titleLabel = UILabel() - let tipButton = ByeBooTipTag() + let tipButton = ByeBooTipTag(text: "작성 TIP") private var questNumber: Int private var quest: String diff --git a/ByeBoo-iOS/ByeBoo-iOS/Presentation/Feature/WriteQuest/Common/WriteQuestTitleView.swift b/ByeBoo-iOS/ByeBoo-iOS/Presentation/Feature/WriteQuest/Common/WriteQuestTitleView.swift index b7bb5aa3..f3307d20 100644 --- a/ByeBoo-iOS/ByeBoo-iOS/Presentation/Feature/WriteQuest/Common/WriteQuestTitleView.swift +++ b/ByeBoo-iOS/ByeBoo-iOS/Presentation/Feature/WriteQuest/Common/WriteQuestTitleView.swift @@ -19,7 +19,7 @@ final class WriteQuestTitleView: BaseView { private let questNumLabel = UILabel() private let titleLabel = UILabel() - let tipTag = ByeBooTipTag() + let tipTag = ByeBooTipTag(text: "작성 TIP") init(stepNum: String, stepTitle: String, questNum: Int, title: String) { From 0e635f8900aed31a7a7b505041c2323b9658395a Mon Sep 17 00:00:00 2001 From: heoseungjun Date: Mon, 23 Feb 2026 16:06:10 +0900 Subject: [PATCH 20/20] =?UTF-8?q?refactor:=20#360=20historyButton=EC=97=90?= =?UTF-8?q?=20ByeBooTipTag=20=EC=BB=B4=ED=8F=AC=EB=84=8C=ED=8A=B8=20?= =?UTF-8?q?=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../View/CommonQuest/CommonQuestHeaderView.swift | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/ByeBoo-iOS/ByeBoo-iOS/Presentation/Feature/Quest/View/CommonQuest/CommonQuestHeaderView.swift b/ByeBoo-iOS/ByeBoo-iOS/Presentation/Feature/Quest/View/CommonQuest/CommonQuestHeaderView.swift index eb54018f..1765f4e8 100644 --- a/ByeBoo-iOS/ByeBoo-iOS/Presentation/Feature/Quest/View/CommonQuest/CommonQuestHeaderView.swift +++ b/ByeBoo-iOS/ByeBoo-iOS/Presentation/Feature/Quest/View/CommonQuest/CommonQuestHeaderView.swift @@ -11,7 +11,7 @@ final class CommonQuestHeaderView: BaseView { private let titleLabel = UILabel() private let subtitleLabel = UILabel() - private(set) var historyButton = UIButton() + private(set) var historyButton = ByeBooTipTag(text: "나의 답변 모아보기") private let underline = UILabel() override func setStyle() { @@ -29,16 +29,6 @@ final class CommonQuestHeaderView: BaseView { textAlignment: .left, numberOfLines: 2 ) - historyButton.do { - $0.applyByeBooFont( - style: .cap1M12, - text: "나의 답변 모아보기", - color: .primary200 - ) - $0.layer.cornerRadius = 12 - $0.layer.borderColor = UIColor.grayscale800.cgColor - $0.backgroundColor = .white5 - } underline.do { $0.backgroundColor = .grayscale800 $0.layer.borderColor = UIColor.grayscale800.cgColor