Skip to content

Commit 61ebda5

Browse files
committed
ui: 스티키 헤더로 정렬, 필터링 옵션을 위치시킨다
1 parent 30dcaf4 commit 61ebda5

11 files changed

Lines changed: 385 additions & 179 deletions

File tree

DevLog/Data/DTO/TodoCursorDTO.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,6 @@
88
import Foundation
99

1010
struct TodoCursorDTO {
11-
let createdAt: Date
11+
let orderedAt: Date
1212
let documentID: String
1313
}

DevLog/Data/Mapper/TodoMapping.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,14 +50,14 @@ extension TodoResponse {
5050
extension TodoCursorDTO {
5151
func toDomain() -> TodoCursor {
5252
TodoCursor(
53-
createdAt: createdAt,
53+
orderedAt: orderedAt,
5454
documentID: documentID
5555
)
5656
}
5757

5858
static func fromDomain(_ cursor: TodoCursor) -> Self {
5959
TodoCursorDTO(
60-
createdAt: cursor.createdAt,
60+
orderedAt: cursor.orderedAt,
6161
documentID: cursor.documentID
6262
)
6363
}

DevLog/Domain/Entity/TodoCursor.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,6 @@
88
import Foundation
99

1010
struct TodoCursor {
11-
let createdAt: Date
11+
let orderedAt: Date
1212
let documentID: String
1313
}

DevLog/Domain/Entity/TodoQuery.swift

Lines changed: 56 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -8,31 +8,77 @@
88
import Foundation
99

1010
struct TodoQuery {
11-
let kind: TodoKind?
12-
let keyword: String?
13-
let isPinned: Bool?
14-
let createdAtFrom: Date?
15-
let createdAtTo: Date?
16-
let createdAtDescending: Bool
17-
let pageSize: Int
18-
let fetchAllPages: Bool
11+
enum SortTarget: Equatable, Hashable {
12+
case createdAt
13+
case updatedAt
14+
15+
var fieldName: String {
16+
switch self {
17+
case .createdAt:
18+
return "createdAt"
19+
case .updatedAt:
20+
return "updatedAt"
21+
}
22+
}
23+
}
24+
25+
enum SortOrder: Equatable, Hashable {
26+
case latest
27+
case oldest
28+
29+
var isDescending: Bool {
30+
self == .latest
31+
}
32+
}
33+
34+
enum CompletionFilter: Equatable, Hashable {
35+
case all
36+
case incomplete
37+
case completed
38+
39+
var isCompletedValue: Bool? {
40+
switch self {
41+
case .all:
42+
return nil
43+
case .incomplete:
44+
return false
45+
case .completed:
46+
return true
47+
}
48+
}
49+
}
50+
51+
var kind: TodoKind?
52+
var keyword: String?
53+
var isPinned: Bool?
54+
var completionFilter: CompletionFilter
55+
var createdAtFrom: Date?
56+
var createdAtTo: Date?
57+
var sortTarget: SortTarget
58+
var sortOrder: SortOrder
59+
var pageSize: Int
60+
var fetchAllPages: Bool
1961

2062
init(
2163
kind: TodoKind? = nil,
2264
keyword: String? = nil,
2365
isPinned: Bool? = nil,
66+
completionFilter: CompletionFilter = .all,
2467
createdAtFrom: Date? = nil,
2568
createdAtTo: Date? = nil,
26-
createdAtDescending: Bool = true,
69+
sortTarget: SortTarget = .createdAt,
70+
sortOrder: SortOrder = .latest,
2771
pageSize: Int = 20,
2872
fetchAllPages: Bool = false
2973
) {
3074
self.kind = kind
3175
self.keyword = keyword
3276
self.isPinned = isPinned
77+
self.completionFilter = completionFilter
3378
self.createdAtFrom = createdAtFrom
3479
self.createdAtTo = createdAtTo
35-
self.createdAtDescending = createdAtDescending
80+
self.sortTarget = sortTarget
81+
self.sortOrder = sortOrder
3682
self.pageSize = pageSize
3783
self.fetchAllPages = fetchAllPages
3884
}

DevLog/Domain/UseCase/UserData/Fetch/Todo/FetchTodosByKindUseCase.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,5 @@
66
//
77

88
protocol FetchTodosByKindUseCase {
9-
func execute(_ kind: TodoKind, cursor: TodoCursor?) async throws -> TodoPage
9+
func execute(_ query: TodoQuery, cursor: TodoCursor?) async throws -> TodoPage
1010
}

DevLog/Domain/UseCase/UserData/Fetch/Todo/FetchTodosByKindUseCaseImpl.swift

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,7 @@ final class FetchTodosByKindUseCaseImpl: FetchTodosByKindUseCase {
1212
self.repository = repository
1313
}
1414

15-
func execute(_ kind: TodoKind, cursor: TodoCursor?) async throws -> TodoPage {
16-
let query = TodoQuery(kind: kind)
15+
func execute(_ query: TodoQuery, cursor: TodoCursor?) async throws -> TodoPage {
1716
return try await repository.fetchTodos(query, cursor: cursor)
1817
}
1918
}

DevLog/Infra/Service/TodoService.swift

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,12 @@ final class TodoService {
2121

2222
let trimmedKeyword = query.keyword?.trimmingCharacters(in: .whitespacesAndNewlines) ?? ""
2323
let logComponents: [String?] = [
24-
"createdAtDescending=\(query.createdAtDescending)",
24+
"sortTarget=\(query.sortTarget.fieldName)",
25+
"sortOrder=\(query.sortOrder == .latest ? "latest" : "oldest")",
2526
query.keyword != nil ? "keywordLength=\(trimmedKeyword.count)" : nil,
2627
query.kind != nil ? "kind=\(query.kind!.rawValue)" : nil,
2728
query.isPinned != nil ? "pinned=\(query.isPinned!)" : nil,
29+
query.completionFilter.isCompletedValue != nil ? "completed=\(query.completionFilter.isCompletedValue!)" : nil,
2830
query.createdAtFrom != nil ? "createdAtFrom=\(query.createdAtFrom!)" : nil,
2931
query.createdAtTo != nil ? "createdAtTo=\(query.createdAtTo!)" : nil,
3032
"pageSize=\(query.pageSize)",
@@ -35,7 +37,7 @@ final class TodoService {
3537

3638
var firestoreQuery: Query = store
3739
.collection("users/\(uid)/todoLists/")
38-
.order(by: "createdAt", descending: query.createdAtDescending)
40+
.order(by: query.sortTarget.fieldName, descending: query.sortOrder.isDescending)
3941
.order(by: FieldPath.documentID())
4042

4143
if let kind = query.kind {
@@ -46,6 +48,10 @@ final class TodoService {
4648
firestoreQuery = firestoreQuery.whereField("isPinned", isEqualTo: isPinned)
4749
}
4850

51+
if let isCompleted = query.completionFilter.isCompletedValue {
52+
firestoreQuery = firestoreQuery.whereField("isCompleted", isEqualTo: isCompleted)
53+
}
54+
4955
if let createdAtFrom = query.createdAtFrom {
5056
firestoreQuery = firestoreQuery.whereField(
5157
"createdAt",
@@ -69,7 +75,7 @@ final class TodoService {
6975
var pageQuery = firestoreQuery
7076
if let pageCursor {
7177
pageQuery = pageQuery.start(after: [
72-
Timestamp(date: pageCursor.createdAt),
78+
Timestamp(date: pageCursor.orderedAt),
7379
pageCursor.documentID
7480
])
7581
}
@@ -83,7 +89,10 @@ final class TodoService {
8389
}
8490

8591
guard let lastDocument = snapshot.documents.last,
86-
let nextCursor = makeCursor(from: lastDocument) else {
92+
let nextCursor = makeCursor(
93+
from: lastDocument,
94+
orderField: query.sortTarget.fieldName
95+
) else {
8796
break
8897
}
8998

@@ -95,15 +104,17 @@ final class TodoService {
95104

96105
if let cursor {
97106
firestoreQuery = firestoreQuery.start(after: [
98-
Timestamp(date: cursor.createdAt),
107+
Timestamp(date: cursor.orderedAt),
99108
cursor.documentID
100109
])
101110
}
102111

103112
firestoreQuery = firestoreQuery.limit(to: query.pageSize)
104113
let snapshot = try await firestoreQuery.getDocuments()
105114
let items = snapshot.documents.compactMap { makeResponse(from: $0) }
106-
let nextCursor = snapshot.documents.last.flatMap { makeCursor(from: $0) }
115+
let nextCursor = snapshot.documents.last.flatMap {
116+
makeCursor(from: $0, orderField: query.sortTarget.fieldName)
117+
}
107118

108119
return TodoPageResponse(items: items, nextCursor: nextCursor)
109120
}
@@ -184,13 +195,16 @@ final class TodoService {
184195
}
185196

186197
private extension TodoService {
187-
func makeCursor(from document: QueryDocumentSnapshot) -> TodoCursorDTO? {
188-
guard let createdAt = document.data()[TodoFieldKey.createdAt.rawValue] as? Timestamp else {
198+
func makeCursor(
199+
from document: QueryDocumentSnapshot,
200+
orderField: String
201+
) -> TodoCursorDTO? {
202+
guard let orderedAt = document.data()[orderField] as? Timestamp else {
189203
return nil
190204
}
191205

192206
return TodoCursorDTO(
193-
createdAt: createdAt.dateValue(),
207+
orderedAt: orderedAt.dateValue(),
194208
documentID: document.documentID
195209
)
196210
}

DevLog/Presentation/Structure/TodoListItem.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,16 @@ struct TodoListItem: Identifiable, Hashable {
1313
let tags: [String]
1414
let isPinned: Bool
1515
let isCompleted: Bool
16+
let createdAt: Date
17+
let updatedAt: Date
1618

1719
init(from todo: Todo) {
1820
self.id = todo.id
1921
self.title = todo.title
2022
self.tags = todo.tags
2123
self.isPinned = todo.isPinned
2224
self.isCompleted = todo.isCompleted
25+
self.createdAt = todo.createdAt
26+
self.updatedAt = todo.updatedAt
2327
}
2428
}

0 commit comments

Comments
 (0)