Skip to content

Commit 32652e8

Browse files
committed
feat: 사용자 카테고리를 수정할 수 있도록 구현
1 parent 698ab4e commit 32652e8

3 files changed

Lines changed: 105 additions & 39 deletions

File tree

DevLog/Presentation/ViewModel/TodoManageViewModel.swift

Lines changed: 87 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -11,30 +11,53 @@ import SwiftUI
1111
final class TodoManageViewModel: Store {
1212
struct State: Equatable {
1313
var preferences: [TodoCategoryPreference]
14+
var category: UserTodoCategory?
1415
var showSheet: Bool = false
1516
var showAlert: Bool = false
16-
var deletingPreference: TodoCategoryPreference?
17-
var categoryName: String = ""
18-
var categoryColor: Color = .blue
1917
}
2018

2119
enum Action {
20+
case tapAddUserCategory
2221
case moveItem(from: IndexSet, target: Int)
2322
case tapItem(_ item: TodoCategory)
23+
case tapEditUserCategory(TodoCategoryPreference)
2424
case tapDeleteUserCategory(TodoCategoryPreference)
2525
case confirmDeleteUserCategory
2626
case setShowSheet(Bool)
2727
case setShowAlert(Bool)
2828
case setCategoryName(String)
2929
case setCategoryColor(Color)
30-
case addUserCategory
30+
case saveUserCategory
3131
}
3232

3333
enum SideEffect { }
3434

3535
private(set) var state: State
36-
var canAddUserCategory: Bool {
37-
let trimmedCategoryName = state.categoryName.trimmingCharacters(in: .whitespacesAndNewlines)
36+
37+
var isEditing: Bool {
38+
guard let userTodoCategory = state.category else {
39+
return false
40+
}
41+
42+
return state.preferences.contains { preference in
43+
guard case .user(let currentCategory) = preference.category else {
44+
return false
45+
}
46+
47+
return currentCategory.id == userTodoCategory.id
48+
}
49+
}
50+
51+
var navigationTitle: String {
52+
isEditing ? "카테고리 수정" : "카테고리 추가"
53+
}
54+
55+
var submitTitle: String {
56+
isEditing ? "저장" : "추가"
57+
}
58+
59+
var canSubmitUserCategory: Bool {
60+
let trimmedCategoryName = state.category?.name.trimmingCharacters(in: .whitespacesAndNewlines) ?? ""
3861
if trimmedCategoryName.isEmpty {
3962
return false
4063
}
@@ -52,61 +75,98 @@ final class TodoManageViewModel: Store {
5275
var state = self.state
5376

5477
switch action {
78+
case .tapAddUserCategory:
79+
state.category = UserTodoCategory(
80+
id: UUID().uuidString.lowercased(),
81+
name: "",
82+
colorHex: "#0A84FF"
83+
)
84+
state.showSheet = true
5585
case .moveItem(let from, let target):
5686
state.preferences.move(fromOffsets: from, toOffset: target)
5787
case .tapItem(let item):
5888
if let index = state.preferences.firstIndex(where: { $0.category == item }) {
5989
state.preferences[index].isVisible.toggle()
6090
}
91+
case .tapEditUserCategory(let preference):
92+
guard case .user(let userTodoCategory) = preference.category else {
93+
break
94+
}
95+
96+
state.category = userTodoCategory
97+
state.showSheet = true
6198
case .tapDeleteUserCategory(let preference):
62-
state.deletingPreference = preference
99+
guard case .user(let userTodoCategory) = preference.category else {
100+
break
101+
}
102+
103+
state.category = userTodoCategory
63104
state.showAlert = true
64105
case .confirmDeleteUserCategory:
65-
guard let preference = state.deletingPreference else {
106+
guard let userTodoCategory = state.category else {
66107
break
67108
}
68109

69110
if let index = state.preferences.firstIndex(where: {
70-
$0 == preference
111+
guard case .user(let currentCategory) = $0.category else {
112+
return false
113+
}
114+
115+
return currentCategory.id == userTodoCategory.id
71116
}) {
72117
state.preferences.remove(at: index)
73118
}
74119
state.showAlert = false
75-
state.deletingPreference = nil
120+
state.category = nil
76121
case .setShowSheet(let isPresented):
77122
state.showSheet = isPresented
78123
if !isPresented {
79-
state.categoryName = ""
80-
state.categoryColor = .blue
124+
state.category = nil
81125
}
82126
case .setShowAlert(let isPresented):
83127
state.showAlert = isPresented
84128
if !isPresented {
85-
state.deletingPreference = nil
129+
state.category = nil
86130
}
87131
case .setCategoryName(let name):
88-
state.categoryName = name
132+
state.category?.name = name
89133
case .setCategoryColor(let color):
90-
state.categoryColor = color
91-
case .addUserCategory:
92-
let trimmedCategoryName = state.categoryName.trimmingCharacters(in: .whitespacesAndNewlines)
93-
if let colorHex = state.categoryColor.hexString {
134+
state.category?.colorHex = color.hexString ?? "#0A84FF"
135+
case .saveUserCategory:
136+
guard let userTodoCategory = state.category else {
137+
break
138+
}
139+
140+
let trimmedCategoryName = userTodoCategory.name.trimmingCharacters(in: .whitespacesAndNewlines)
141+
let updatedCategory = UserTodoCategory(
142+
id: userTodoCategory.id,
143+
name: trimmedCategoryName,
144+
colorHex: userTodoCategory.colorHex
145+
)
146+
147+
if let index = state.preferences.firstIndex(where: {
148+
guard case .user(let currentCategory) = $0.category else {
149+
return false
150+
}
151+
152+
return currentCategory.id == updatedCategory.id
153+
}) {
154+
let preference = state.preferences[index]
155+
state.preferences[index] = TodoCategoryPreference(
156+
category: .user(updatedCategory),
157+
isVisible: preference.isVisible
158+
)
159+
} else {
94160
state.preferences.append(
95161
TodoCategoryPreference(
96-
category: .user(
97-
UserTodoCategory(
98-
id: UUID().uuidString.lowercased(),
99-
name: trimmedCategoryName,
100-
colorHex: colorHex
101-
)
102-
),
162+
category: .user(updatedCategory),
103163
isVisible: true
104164
)
105165
)
106166
}
167+
107168
state.showSheet = false
108-
state.categoryName = ""
109-
state.categoryColor = .blue
169+
state.category = nil
110170
}
111171

112172
if self.state != state { self.state = state }

DevLog/Resource/Localizable.xcstrings

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -456,9 +456,6 @@
456456
},
457457
"카테고리 삭제" : {
458458

459-
},
460-
"카테고리 추가" : {
461-
462459
},
463460
"카테고리명" : {
464461

DevLog/UI/Home/TodoManageView.swift

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,14 @@ struct TodoManageView: View {
2525
Text(category.localizedName)
2626
Spacer()
2727
if case .user = category {
28+
Button {
29+
viewModel.send(.tapEditUserCategory(preference))
30+
} label: {
31+
Image(systemName: "slider.horizontal.3")
32+
}
33+
.buttonStyle(.borderless)
34+
.padding(.trailing, 8)
35+
2836
Button(role: .destructive) {
2937
viewModel.send(.tapDeleteUserCategory(preference))
3038
} label: {
@@ -72,7 +80,7 @@ struct TodoManageView: View {
7280
.toolbar {
7381
ToolbarItem(placement: .navigationBarLeading) {
7482
Button {
75-
viewModel.send(.setShowSheet(true))
83+
viewModel.send(.tapAddUserCategory)
7684
} label: {
7785
Image(systemName: "plus")
7886
}
@@ -97,7 +105,7 @@ struct TodoManageView: View {
97105
TextField(
98106
"카테고리명",
99107
text: Binding(
100-
get: { viewModel.state.categoryName },
108+
get: { viewModel.state.category?.name ?? "" },
101109
set: { viewModel.send(.setCategoryName($0)) }
102110
)
103111
)
@@ -106,16 +114,17 @@ struct TodoManageView: View {
106114

107115
Section {
108116
ColorPicker(selection: Binding(
109-
get: { viewModel.state.categoryColor },
117+
get: { Color(hexString: viewModel.state.category?.colorHex ?? "#0A84FF") ?? .blue },
110118
set: { viewModel.send(.setCategoryColor($0)) }
111119
), supportsOpacity: false) {
112-
Text(viewModel.state.categoryColor.hexString ?? "#")
113-
.foregroundStyle(viewModel.state.categoryColor)
120+
let color = Color(hexString: viewModel.state.category?.colorHex ?? "#0A84FF") ?? .blue
121+
Text(viewModel.state.category?.colorHex ?? "#")
122+
.foregroundStyle(color)
114123
}
115124
.pickerStyle(.palette)
116125
}
117126
}
118-
.navigationTitle("카테고리 추가")
127+
.navigationTitle(viewModel.navigationTitle)
119128
.navigationBarTitleDisplayMode(.inline)
120129
.toolbar {
121130
ToolbarItem(placement: .navigationBarLeading) {
@@ -125,10 +134,10 @@ struct TodoManageView: View {
125134
}
126135

127136
ToolbarItem(placement: .navigationBarTrailing) {
128-
Button("추가") {
129-
viewModel.send(.addUserCategory)
137+
Button(viewModel.submitTitle) {
138+
viewModel.send(.saveUserCategory)
130139
}
131-
.disabled(!viewModel.canAddUserCategory)
140+
.disabled(!viewModel.canSubmitUserCategory)
132141
}
133142
}
134143
}

0 commit comments

Comments
 (0)