Skip to content

Commit 84c88a6

Browse files
committed
[Feat] AlarmCheckFeature ์ž‘์„ฑ
1 parent 7190853 commit 84c88a6

File tree

4 files changed

+178
-3
lines changed

4 files changed

+178
-3
lines changed

โ€ŽTnT/Projects/Domain/Sources/Entity/AlarmItemEntity.swiftโ€Ž

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,9 @@
99
import Foundation
1010

1111
/// ์•Œ๋žŒ ํ™•์ธ์‹œ ์‚ฌ์šฉ๋˜๋Š” ์•Œ๋žŒ ์ •๋ณด ๊ตฌ์กฐ์ฒด
12-
public struct AlarmItemEntity {
12+
public struct AlarmItemEntity: Equatable {
13+
/// ์•Œ๋žŒ id
14+
public let alarmId: Int
1315
/// ์•Œ๋žŒ ํƒ€์ž…
1416
public let alarmType: AlarmType
1517
/// ์•Œ๋žŒ ๋„์ฐฉ ์‹œ๊ฐ
@@ -18,10 +20,12 @@ public struct AlarmItemEntity {
1820
public let alarmSeenBefore: Bool
1921

2022
public init(
23+
alarmId: Int,
2124
alarmType: AlarmType,
2225
alarmDate: Date,
2326
alarmSeenBefore: Bool
2427
) {
28+
self.alarmId = alarmId
2529
self.alarmType = alarmType
2630
self.alarmDate = alarmDate
2731
self.alarmSeenBefore = alarmSeenBefore

โ€ŽTnT/Projects/Domain/Sources/Entity/AlarmType.swiftโ€Ž

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
import Foundation
1010

1111
/// ์•ฑ์—์„œ ์กด์žฌํ•˜๋Š” ์•Œ๋žŒ ์œ ํ˜•์„ ์ •์˜ํ•œ ์—ด๊ฑฐํ˜•
12-
public enum AlarmType {
12+
public enum AlarmType: Equatable {
1313
/// ํŠธ๋ ˆ์ด๋‹ˆ ์—ฐ๊ฒฐ ์™„๋ฃŒ
1414
case traineeConnected(name: String)
1515
/// ํŠธ๋ ˆ์ด๋‹ˆ ์—ฐ๊ฒฐ ํ•ด์ œ
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
//
2+
// AlarmCheckFeature.swift
3+
// Presentation
4+
//
5+
// Created by ๋ฐ•๋ฏผ์„œ on 2/2/25.
6+
// Copyright ยฉ 2025 yapp25thTeamTnT. All rights reserved.
7+
//
8+
9+
import Foundation
10+
import ComposableArchitecture
11+
12+
import Domain
13+
import DesignSystem
14+
15+
@Reducer
16+
public struct AlarmCheckFeature {
17+
18+
@ObservableState
19+
public struct State: Equatable {
20+
// MARK: Data related state
21+
/// ์œ ์ € ํƒ€์ž…
22+
var userType: UserType
23+
/// ์•Œ๋žŒ ์ •๋ณด ๋ชฉ๋ก
24+
var alarmList: [AlarmItemEntity]
25+
26+
/// `AlarmCheckFeature.State`์˜ ์ƒ์„ฑ์ž
27+
/// - Parameters:
28+
/// - userType: ์œ ์ € ํƒ€์ž…
29+
/// - alarmList: ์œ ์ €์—๊ฒŒ ๋„์ฐฉํ•œ ์•Œ๋žŒ ๋ชฉ๋ก (๊ธฐ๋ณธ๊ฐ’: `[]`)
30+
public init(
31+
userType: UserType,
32+
alarmList: [AlarmItemEntity] = []
33+
) {
34+
self.userType = userType
35+
self.alarmList = alarmList
36+
}
37+
}
38+
39+
@Dependency(\.dismiss) private var dismiss
40+
41+
public enum Action: Sendable, ViewAction {
42+
/// ๋ทฐ์—์„œ ๋ฐœ์ƒํ•œ ์•ก์…˜์„ ์ฒ˜๋ฆฌํ•ฉ๋‹ˆ๋‹ค.
43+
case view(View)
44+
/// ๋„ค๋น„๊ฒŒ์ด์…˜ ์—ฌ๋ถ€ ์„ค์ •
45+
case setNavigating
46+
47+
@CasePathable
48+
public enum View: Sendable, BindableAction {
49+
/// ๋ฐ”์ธ๋”ฉ ์•ก์…˜ ์ฒ˜๋ฆฌ
50+
case binding(BindingAction<State>)
51+
/// ์•Œ๋žŒ ์•„์ดํ…œ ํƒญ ๋˜์—ˆ์„ ๋•Œ
52+
case tapAlarmItem(Int)
53+
/// ๋„ค๋น„๊ฒŒ์ด์…˜ back ๋ฒ„ํŠผ ํƒญ ๋˜์—ˆ์„ ๋•Œ
54+
case tapNavBackButton
55+
}
56+
}
57+
58+
public init() {}
59+
60+
public var body: some ReducerOf<Self> {
61+
BindingReducer(action: \.view)
62+
63+
Reduce { state, action in
64+
switch action {
65+
case .view(let action):
66+
switch action {
67+
case .binding:
68+
return .none
69+
70+
case .tapAlarmItem(let id):
71+
print("alarmId: \(id)")
72+
return .none
73+
74+
case .tapNavBackButton:
75+
return .run { _ in
76+
// TODO: ์„œ๋ฒ„ API ๋ช…์„ธ ๋‚˜์˜ค๋ฉด ์—ฐ๊ฒฐ
77+
// ํ˜„์žฌ ๋ชจ๋“  ์•Œ๋žŒ ํ™•์ธ ํ‘œ์‹œ
78+
await self.dismiss()
79+
}
80+
}
81+
case .setNavigating:
82+
return .none
83+
}
84+
}
85+
}
86+
}

โ€ŽTnT/Projects/Presentation/Sources/Alarm/AlarmCheckView.swiftโ€Ž

Lines changed: 86 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,89 @@
66
// Copyright ยฉ 2025 yapp25thTeamTnT. All rights reserved.
77
//
88

9-
import Foundation
9+
import SwiftUI
10+
import ComposableArchitecture
11+
12+
import Domain
13+
import DesignSystem
14+
15+
/// ์•Œ๋žŒ ๋ชฉ๋ก์„ ์ž…๋ ฅํ•˜๋Š” ํ™”๋ฉด
16+
/// ์œ ์ €์—๊ฒŒ ๋„์ฐฉํ•œ ์•Œ๋žŒ์„ ํ‘œ์‹œ - ์œ ์ € ํƒ€์ž…์— ๋”ฐ๋ผ ๋ถ„๋ฅ˜
17+
@ViewAction(for: AlarmCheckFeature.self)
18+
public struct AlarmCheckView: View {
19+
20+
@Bindable public var store: StoreOf<AlarmCheckFeature>
21+
@Environment(\.dismiss) var dismiss: DismissAction
22+
23+
public init(store: StoreOf<AlarmCheckFeature>) {
24+
self.store = store
25+
}
26+
27+
public var body: some View {
28+
VStack(spacing: 0) {
29+
TNavigation(
30+
type: .LButtonWithTitle(leftImage: .icnArrowLeft, centerTitle: "์•Œ๋ฆผ"),
31+
leftAction: { send(.tapNavBackButton) }
32+
)
33+
34+
ScrollView {
35+
AlarmList()
36+
Spacer()
37+
}
38+
}
39+
.navigationBarBackButtonHidden(true)
40+
}
41+
42+
// MARK: - Sections
43+
@ViewBuilder
44+
private func AlarmList() -> some View {
45+
VStack(spacing: 0) {
46+
ForEach(store.alarmList, id: \.alarmId) { item in
47+
AlarmListItem(
48+
alarmTypeText: item.alarmTypeText,
49+
alarmMainText: item.alarmMainText,
50+
alarmTimeText: item.alarmDate.timeAgoDisplay(),
51+
alarmSeenBefore: item.alarmSeenBefore
52+
)
53+
}
54+
}
55+
}
56+
}
57+
58+
private extension AlarmCheckView {
59+
struct AlarmListItem: View {
60+
/// ์—ฐ๊ฒฐ ์™„๋ฃŒ, ์—ฐ๊ฒฐ ํ•ด์ œ ๋“ฑ
61+
let alarmTypeText: String
62+
/// ์•Œ๋žŒ ๋ณธ๋ฌธ
63+
let alarmMainText: String
64+
/// ์•Œ๋žŒ ์‹œ๊ฐ
65+
let alarmTimeText: String
66+
/// ์•Œ๋žŒ ํ™•์ธ ์—ฌ๋ถ€
67+
let alarmSeenBefore: Bool
68+
69+
var body: some View {
70+
HStack(spacing: 16) {
71+
Image(.icnBombEmpty)
72+
.resizable()
73+
.scaledToFit()
74+
.frame(width: 32, height: 32)
75+
76+
VStack(alignment: .leading, spacing: 4) {
77+
HStack {
78+
Text(alarmTypeText)
79+
.typographyStyle(.label1Bold, with: .neutral400)
80+
.padding(.bottom, 3)
81+
Spacer()
82+
Text(alarmTimeText)
83+
.typographyStyle(.label1Medium, with: .neutral400)
84+
}
85+
86+
Text(alarmMainText)
87+
.typographyStyle(.body2Medium, with: .neutral800)
88+
}
89+
}
90+
.padding(20)
91+
.background(alarmSeenBefore ? Color.common0 : Color.neutral100)
92+
}
93+
}
94+
}

0 commit comments

Comments
ย (0)