Skip to content

Commit 8b01e87

Browse files
authored
Merge pull request #359 from Team-Capple/feat/#358-today-question
2 parents 3bf9a0f + cb0c0bd commit 8b01e87

File tree

7 files changed

+224
-31
lines changed

7 files changed

+224
-31
lines changed

Qapple/Qapple/Resource/Constant/Constant.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,5 +17,6 @@ enum Constant {
1717

1818
extension Constant {
1919
static let isSignIn = "isSignIn"
20+
static let recentQuestionID = "recentQuestionID"
2021
static let userRandomID = "userRandomID"
2122
}

Qapple/Qapple/SourceCode/Entity/QuestionState.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -40,9 +40,9 @@ enum QuestionState: Codable {
4040
/// 질문 및 답변 여부에 따라 변화하는 버튼 문자열
4141
func buttonTitle(isAnswerd: Bool) -> String {
4242
switch self {
43-
case .creating: isAnswerd ? "다른 답변 둘러보기" : "이전 질문 답변하기"
44-
case .ready: "질문에 답변하기"
45-
case .complete: "다른 답변 둘러보기"
43+
case .creating: isAnswerd ? "둘러보기" : "답변하기"
44+
case .ready: "답변하기"
45+
case .complete: "둘러보기"
4646
}
4747
}
4848
}

Qapple/Qapple/SourceCode/Feature/2.QuestionTab/2-2.TodayQuestion/TodayQuestionFeature.swift

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,10 @@ struct TodayQuestionFeature {
1919
var timeRemainingForQuestion: TimeInterval = 0
2020
var isLoading = true
2121
var isFirstLaunch = true
22+
var isNewQuestion = false
2223
@Presents var sheet: Sheet.State?
2324
@Presents var alert: AlertState<Action.Alert>?
25+
@Shared(.appStorage(Constant.recentQuestionID)) var recentQuestionID = 0
2426
}
2527

2628
enum Action {
@@ -79,6 +81,14 @@ struct TodayQuestionFeature {
7981
case let .mainQuestionResponse(mainQuestion):
8082
state.isFirstLaunch = false
8183
state.todayQuestion = mainQuestion
84+
85+
if mainQuestion.id != state.recentQuestionID {
86+
state.isNewQuestion = true
87+
state.$recentQuestionID.withLock { $0 = mainQuestion.id }
88+
} else {
89+
state.isNewQuestion = false
90+
}
91+
8292
if isQuestionLiveTime {
8393
state.questionState = mainQuestion.isAnswered ? .complete : .ready
8494
return .none

Qapple/Qapple/SourceCode/Feature/2.QuestionTab/2-2.TodayQuestion/TodayQuestionView.swift

Lines changed: 103 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -13,18 +13,19 @@ struct TodayQuestionView: View {
1313
@Bindable var store: StoreOf<TodayQuestionFeature>
1414

1515
var body: some View {
16-
ZStack {
17-
Color.second.ignoresSafeArea()
18-
19-
ScrollView {
20-
VStack(spacing: 0) {
21-
HeaderView(store: store)
22-
QuestionButton(store: store)
23-
AnswerPreviewList(store: store)
16+
ScrollView {
17+
VStack(spacing: 0) {
18+
if store.isNewQuestion {
19+
LargeHeaderView(store: store)
20+
LargeQuestionButton(store: store)
21+
} else {
22+
SmallHeaderView(store: store)
2423
}
24+
AnswerPreviewList(store: store)
2525
}
26-
.scrollIndicators(.hidden)
2726
}
27+
.background(.second)
28+
.scrollIndicators(.hidden)
2829
.onAppear {
2930
store.send(.onAppear)
3031
}
@@ -36,20 +37,98 @@ struct TodayQuestionView: View {
3637
}
3738
.loadingIndicator(isLoading: store.isLoading)
3839
.alert($store.scope(state: \.alert, action: \.alert))
39-
.sheet(item: $store.scope(
40-
state: \.sheet,
41-
action: \.sheet)
42-
) { store in
40+
.sheet(item: $store.scope(state: \.sheet, action: \.sheet)) { store in
4341
switch store.case {
4442
case let .seeMore(store): SeeMoreSheet(store: store)
4543
}
4644
}
4745
}
4846
}
4947

50-
// MARK: - HeaderView
48+
// MARK: - SmallHeaderView
49+
50+
private struct SmallHeaderView: View {
51+
52+
let store: StoreOf<TodayQuestionFeature>
53+
54+
var body: some View {
55+
ZStack {
56+
Color.first.ignoresSafeArea()
57+
58+
HStack(spacing: 8) {
59+
Image(store.questionState.graphicImage)
60+
.resizable()
61+
.scaledToFill()
62+
.frame(width: 40, height: 40)
63+
64+
Text(store.questionState.mainTitle)
65+
.font(.pretendard(.semiBold, size: 18))
66+
.foregroundStyle(.wh)
67+
.tracking(-1)
68+
69+
Spacer()
70+
71+
if store.questionState == .creating {
72+
QuestionTimer()
73+
} else {
74+
AnsweringButton()
75+
}
76+
}
77+
.padding(.horizontal, 24)
78+
.frame(maxWidth: .infinity)
79+
.frame(height: 90)
80+
.background(.second)
81+
.cornerRadius(32, corners: [.bottomLeft, .bottomRight])
82+
}
83+
}
84+
85+
/// 질문 타이머
86+
private func QuestionTimer() -> some View {
87+
Text(store.timeRemainingForQuestion.timerFormat)
88+
.font(.pretendard(.bold, size: 22))
89+
.foregroundStyle(LinearGradient.timer)
90+
.monospacedDigit()
91+
.kerning(-2)
92+
}
93+
94+
/// 답변하기 버튼
95+
private func AnsweringButton() -> some View {
96+
Button {
97+
store.send(.questionButtonTapped(store.todayQuestion))
98+
} label: {
99+
Text(title)
100+
.font(.pretendard(.semiBold, size: 15))
101+
.frame(width: 84)
102+
.padding(.vertical, 10)
103+
.foregroundStyle(.main)
104+
.background(backgroundColor)
105+
.clipShape(RoundedRectangle(cornerRadius: 20))
106+
}
107+
.opacity(store.isLoading ? 0 : 1)
108+
.buttonStyle(ScalableButtonStyle())
109+
}
110+
111+
/// 버튼 제목
112+
private var title: String {
113+
store.questionState.buttonTitle(
114+
isAnswerd: store.todayQuestion.isAnswered
115+
)
116+
}
117+
118+
/// 버튼 배경 색상
119+
private var backgroundColor: Color {
120+
switch store.questionState {
121+
case .creating:
122+
store.todayQuestion.isAnswered ? .secondaryButton : .button
123+
case .ready: .button
124+
case .complete: .secondaryButton
125+
}
126+
}
127+
}
128+
129+
// MARK: - LargeHeaderView
51130

52-
private struct HeaderView: View {
131+
private struct LargeHeaderView: View {
53132

54133
@State private var offsetY: CGFloat = 0
55134

@@ -93,9 +172,9 @@ private struct HeaderView: View {
93172
}
94173
}
95174

96-
// MARK: - QuestionButton
175+
// MARK: - LargeQuestionButton
97176

98-
private struct QuestionButton: View {
177+
private struct LargeQuestionButton: View {
99178

100179
let store: StoreOf<TodayQuestionFeature>
101180

@@ -141,7 +220,6 @@ private struct QuestionButton: View {
141220
}
142221
}
143222
}
144-
145223
// MARK: - AnswerPreviewList
146224

147225
private struct AnswerPreviewList: View {
@@ -165,7 +243,7 @@ private struct AnswerPreviewList: View {
165243
if store.answerPreviewList.isEmpty {
166244
Spacer()
167245

168-
Text("아직 답변이 달리지않았어요\n 답변을 달아보세요!")
246+
Text(" 답변을 달아보세요!")
169247
.font(.pretendard(.semiBold, size: 14))
170248
.foregroundStyle(.sub4)
171249
.multilineTextAlignment(.center)
@@ -221,6 +299,12 @@ private struct AnswerPreviewList: View {
221299
state: .normal,
222300
seeMoreAction: {
223301
store.send(.seeMoreAnswerButtonTapped(answer))
302+
},
303+
likeAction: {
304+
305+
},
306+
commentAction: {
307+
224308
}
225309
)
226310
}

Qapple/Qapple/SourceCode/Feature/2.QuestionTab/2-6.AnswerList/AnswerListView.swift

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,12 @@ private struct AnswerList: View {
139139
state: .normal,
140140
seeMoreAction: {
141141
store.send(.seeMoreAction(answer))
142+
},
143+
likeAction: {
144+
145+
},
146+
commentAction: {
147+
142148
}
143149
)
144150
.configurePagination(

Qapple/Qapple/SourceCode/Feature/5.Profile/5-3.MyAnswerList/MyAnswerListView.swift

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,12 @@ private struct MyAnswerList: View {
7070
state: .written,
7171
seeMoreAction:{
7272
store.send(.seeMoreAction(answer))
73+
},
74+
likeAction: {
75+
76+
},
77+
commentAction: {
78+
7379
}
7480
)
7581
.configurePagination(

0 commit comments

Comments
 (0)