@@ -36,8 +36,9 @@ final class TodoService {
3636 query. isPinned != nil ? " pinned= \( query. isPinned!) " : nil ,
3737 query. completionFilter. isCompletedValue != nil ? " completed= \( query. completionFilter. isCompletedValue!) " : nil ,
3838 query. dueDateFilter != . all ? " dueDateFilter= \( query. dueDateFilter) " : nil ,
39- query. createdAtFrom != nil ? " createdAtFrom= \( query. createdAtFrom!) " : nil ,
40- query. createdAtTo != nil ? " createdAtTo= \( query. createdAtTo!) " : nil ,
39+ query. sortDateFrom != nil ? " sortDateFrom= \( query. sortDateFrom!) " : nil ,
40+ query. sortDateTo != nil ? " sortDateTo= \( query. sortDateTo!) " : nil ,
41+ query. includesDeleted ? " includesDeleted=true " : nil ,
4142 " pageSize= \( query. pageSize) " ,
4243 query. fetchAllPages ? " fetchAllPages=true " : nil ,
4344 cursor != nil ? " cursor= \( cursor!) " : nil
@@ -73,17 +74,17 @@ final class TodoService {
7374 firestoreQuery = firestoreQuery. whereField ( " dueDate " , isEqualTo: NSNull ( ) )
7475 }
7576
76- if let createdAtFrom = query. createdAtFrom {
77+ if let sortDateFrom = query. sortDateFrom {
7778 firestoreQuery = firestoreQuery. whereField (
78- " createdAt " ,
79- isGreaterThanOrEqualTo: Timestamp ( date: createdAtFrom )
79+ query . sortTarget . fieldName ,
80+ isGreaterThanOrEqualTo: Timestamp ( date: sortDateFrom )
8081 )
8182 }
8283
83- if let createdAtTo = query. createdAtTo {
84+ if let sortDateTo = query. sortDateTo {
8485 firestoreQuery = firestoreQuery. whereField (
85- " createdAt " ,
86- isLessThan: Timestamp ( date: createdAtTo )
86+ query . sortTarget . fieldName ,
87+ isLessThan: Timestamp ( date: sortDateTo )
8788 )
8889 }
8990
@@ -165,12 +166,12 @@ final class TodoService {
165166 let docRef = collection. document ( request. id)
166167 var data = try encoder. encode ( request)
167168 data. removeValue ( forKey: TodoFieldKey . id. rawValue)
168- if let number = request. number {
169- data [ TodoFieldKey . number. rawValue] = number
170- }
171169 if request. completedAt == nil {
172170 data [ TodoFieldKey . completedAt. rawValue] = NSNull ( )
173171 }
172+ if request. deletedAt == nil {
173+ data [ TodoFieldKey . deletedAt. rawValue] = NSNull ( )
174+ }
174175 if request. dueDate == nil {
175176 data [ TodoFieldKey . dueDate. rawValue] = NSNull ( )
176177 }
@@ -229,7 +230,7 @@ final class TodoService {
229230 do {
230231 let snapshot = try await store. collection ( FirestorePath . todos ( uid) )
231232 . whereField ( FieldPath . documentID ( ) , isEqualTo: todoId)
232- . whereField ( TodoFieldKey . isDeleted . rawValue, isEqualTo: false )
233+ . whereField ( TodoFieldKey . deletedAt . rawValue, isEqualTo: NSNull ( ) )
233234 . limit ( to: 1 )
234235 . getDocuments ( )
235236 guard let document = snapshot. documents. first, let todo = makeResponse ( from: document) else {
@@ -256,7 +257,7 @@ final class TodoService {
256257 group. addTask {
257258 let snapshot = try await collection
258259 . whereField ( TodoFieldKey . number. rawValue, in: chunk)
259- . whereField ( TodoFieldKey . isDeleted . rawValue, isEqualTo: false )
260+ . whereField ( TodoFieldKey . deletedAt . rawValue, isEqualTo: NSNull ( ) )
260261 . getDocuments ( )
261262 return snapshot. documents
262263 }
@@ -272,8 +273,7 @@ final class TodoService {
272273 return snapshots. reduce ( into: [ Int: TodoReferenceResponse] ( ) ) { partialResult, document in
273274 let data = document. data ( )
274275 guard
275- !( data [ TodoFieldKey . deletingAt. rawValue] is Timestamp ) ,
276- ( data [ TodoFieldKey . isDeleted. rawValue] as? Bool ) != true ,
276+ data [ TodoFieldKey . deletedAt. rawValue] is NSNull ,
277277 let response = makeResponse ( from: document)
278278 else {
279279 return
@@ -359,16 +359,19 @@ private extension TodoService {
359359 }
360360
361361 func makeQuery( uid: String , query: TodoQuery ) -> Query {
362- let collection = store. collection ( FirestorePath . todos ( uid) )
363- . whereField ( TodoFieldKey . isDeleted. rawValue, isEqualTo: false )
362+ var collection : Query = store. collection ( FirestorePath . todos ( uid) )
363+
364+ if !query. includesDeleted {
365+ collection = collection. whereField ( TodoFieldKey . deletedAt. rawValue, isEqualTo: NSNull ( ) )
366+ }
364367
365368 switch query. sortTarget {
366369 case . dueDate:
367370 return collection
368371 . order ( by: query. sortTarget. fieldName, descending: query. sortOrder. isDescending)
369372 . order ( by: " updatedAt " , descending: true )
370373 . order ( by: FieldPath . documentID ( ) )
371- case . createdAt, . updatedAt:
374+ case . createdAt, . completedAt , . deletedAt , . updatedAt:
372375 return collection
373376 . order ( by: query. sortTarget. fieldName, descending: query. sortOrder. isDescending)
374377 . order ( by: FieldPath . documentID ( ) )
@@ -389,7 +392,7 @@ private extension TodoService {
389392 Timestamp ( date: sortDate) ,
390393 cursor. documentID
391394 ]
392- case . createdAt, . updatedAt:
395+ case . createdAt, . completedAt , . deletedAt , . updatedAt:
393396 return [
394397 primaryValue,
395398 cursor. documentID
@@ -420,7 +423,7 @@ private extension TodoService {
420423 return nil
421424 }
422425 secondarySortDate = updatedAt. dateValue ( )
423- case . createdAt, . updatedAt:
426+ case . createdAt, . completedAt , . deletedAt , . updatedAt:
424427 secondarySortDate = nil
425428 }
426429
@@ -432,10 +435,6 @@ private extension TodoService {
432435 }
433436
434437 func makeResponse( from snapshot: QueryDocumentSnapshot ) -> TodoResponse ? {
435- if snapshot. data ( ) [ TodoFieldKey . deletingAt. rawValue] is Timestamp ||
436- ( snapshot. data ( ) [ TodoFieldKey . isDeleted. rawValue] as? Bool ) == true {
437- return nil
438- }
439438 return makeResponse ( documentID: snapshot. documentID, data: snapshot. data ( ) )
440439 }
441440
@@ -447,26 +446,25 @@ private extension TodoService {
447446 }
448447
449448 func makeResponse( documentID: String , data: [ String : Any ] ) -> TodoResponse ? {
450- if data [ TodoFieldKey . deletingAt. rawValue] is Timestamp ||
451- ( data [ TodoFieldKey . isDeleted. rawValue] as? Bool ) == true {
452- return nil
453- }
454449 guard
455- let isPinned = data [ TodoFieldKey . isPinned. rawValue] as? Bool ,
456- let isCompleted = data [ TodoFieldKey . isCompleted. rawValue] as? Bool ,
457- let isChecked = data [ TodoFieldKey . isChecked. rawValue] as? Bool ,
458450 let number = data [ TodoFieldKey . number. rawValue] as? Int ,
459451 let title = data [ TodoFieldKey . title. rawValue] as? String ,
460- let content = data [ TodoFieldKey . content. rawValue] as? String ,
461452 let createdAtTimestamp = data [ TodoFieldKey . createdAt. rawValue] as? Timestamp ,
462453 let updatedAtTimestamp = data [ TodoFieldKey . updatedAt. rawValue] as? Timestamp ,
463- let tags = data [ TodoFieldKey . tags. rawValue] as? [ String ] ,
464454 let category = data [ TodoFieldKey . category. rawValue] as? String else {
465455 return nil
466456 }
467457
468458 let completedAt = ( data [ TodoFieldKey . completedAt. rawValue] as? Timestamp ) ? . dateValue ( )
459+ let deletedAt = ( data [ TodoFieldKey . deletedAt. rawValue] as? Timestamp ) ? . dateValue ( )
469460 let dueDate = ( data [ TodoFieldKey . dueDate. rawValue] as? Timestamp ) ? . dateValue ( )
461+
462+ let isPinned = data [ TodoFieldKey . isPinned. rawValue] as? Bool ?? false
463+ let isCompleted = data [ TodoFieldKey . isCompleted. rawValue] as? Bool ?? ( completedAt != nil )
464+ let isChecked = data [ TodoFieldKey . isChecked. rawValue] as? Bool ?? false
465+ let content = data [ TodoFieldKey . content. rawValue] as? String ?? " "
466+ let tags = data [ TodoFieldKey . tags. rawValue] as? [ String ] ?? [ ]
467+
470468 return TodoResponse (
471469 id: documentID,
472470 isPinned: isPinned,
@@ -478,6 +476,7 @@ private extension TodoService {
478476 createdAt: createdAtTimestamp. dateValue ( ) ,
479477 updatedAt: updatedAtTimestamp. dateValue ( ) ,
480478 completedAt: completedAt,
479+ deletedAt: deletedAt,
481480 dueDate: dueDate,
482481 tags: tags,
483482 category: . raw( category)
@@ -495,11 +494,10 @@ private extension TodoService {
495494 case createdAt
496495 case updatedAt
497496 case completedAt
497+ case deletedAt
498498 case dueDate
499499 case tags
500500 case category
501- case deletingAt // 삭제 요청으로 앱의 로컬 데이터에서 deletion이 된 상태
502- case isDeleted // 삭제 요청으로 서버에서 soft deletion이 된 상태
503501 }
504502
505503 enum CounterFieldKey : String {
0 commit comments