Skip to content

Commit

Permalink
Merge pull request #34 from boostcampwm-2022/feature/QuestRepository
Browse files Browse the repository at this point in the history
Feature/quest repository
  • Loading branch information
jinwoong16 committed Nov 23, 2022
2 parents 9ce28e3 + 31c8b09 commit 1d42a92
Show file tree
Hide file tree
Showing 26 changed files with 778 additions and 190 deletions.
166 changes: 117 additions & 49 deletions DailyQuest/DailyQuest.xcodeproj/project.pbxproj

Large diffs are not rendered by default.

4 changes: 4 additions & 0 deletions DailyQuest/DailyQuest/Application/SceneDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
//

import UIKit
import RxSwift

class SceneDelegate: UIResponder, UIWindowSceneDelegate {

Expand All @@ -26,6 +27,9 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate {
self.window?.rootViewController = tabbarController
self.window?.makeKeyAndVisible()

//_ = FirebaseService.shared.update(userCase: .currentUser, access: .quests, dto: QuestDTO(uuid: UUID(uuidString: "16AF9B21-4C85-4EF9-9DF5-B1A3385C9D56") ?? UUID(), title: "바꾸기", currentCount: 0, totalCount: 0, groupUid: UUID(uuidString: "98AC0127-5CAF-4DC7-9365-9E5F819053BE") ?? UUID()))
_ = FirebaseService.shared.create(userCase: .currentUser, access: .quests, dto: QuestDTO(uuid: UUID(), title: "", currentCount: 0, totalCount: 0, groupUid: UUID()))

self.appCoordinator = AppCoordinator(tabBarController: tabbarController,
appDIContainer: appDIContainer)
self.appCoordinator?.start()
Expand Down
12 changes: 12 additions & 0 deletions DailyQuest/DailyQuest/Data/Network/DataMapping/DTO.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
//
// DTO.swift
// DailyQuest
//
// Created by 이전희 on 2022/11/21.
//

import Foundation

protocol DTO: Codable {
var uuid: UUID { get }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
//
// QuestDTO+Mapping.swift
// DailyQuest
//
// Created by 이다연 on 2022/11/21.
//

import Foundation

struct QuestDTO: DTO {
let uuid: UUID
let title: String
let currentCount: Int
let totalCount: Int
let groupUid: UUID
}

extension QuestDTO {
func toDomain() -> Quest {
return Quest(groupId: groupUid,
uuid: uuid,
title: title,
currentCount: currentCount,
totalCount: totalCount)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ import Foundation

extension BrowseQuestEntity {
convenience init(browseQuest: BrowseQuest) {
let questsEntities = browseQuest.quests.compactMap { UserQuestEntity(quest: $0) }
let questsEntities = browseQuest.quests.compactMap { QuestEntity(quest: $0) }

self.init(uuid: browseQuest.uuid,
nickName: browseQuest.nickName,
quests: questsEntities)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ extension RealmBrowseQuestsStorage: BrowseQuestsStorage {
let browseQuestEntity = BrowseQuestEntity(browseQuest: browseQuest)

do {
try realmStorage.updateEntity(entity: browseQuestEntity)
try realmStorage.saveEntity(entity: browseQuestEntity)
single(.success(browseQuest))
} catch let error {
single(.failure(RealmStorageError.saveError(error)))
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
//
// QuestsStorage.swift
// DailyQuest
//
// Created by 이전희 on 2022/11/14.
//

import Foundation
import RxSwift

protocol QuestsStorage {
func saveQuests(with quests: [Quest]) -> Single<[Quest]>
func fetchQuests(by date: Date) -> Observable<[Quest]>
func updateQuest(with quest: Quest) -> Single<Quest>
func deleteQuest(with questId: UUID) -> Single<Quest>
func deleteQuestGroup(with groupId: UUID) -> Single<[Quest]>
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
//
// QuestEntity+Mapping.swift
// DailyQuest
//
// Created by 이전희 on 2022/11/14.
//

import Foundation

extension QuestEntity {
convenience init(quest: Quest) { // Quest에 date 들어가면 수정
self.init(
groupId: quest.groupId,
uuid: quest.uuid,
date: quest.date.toString,
title: quest.title,
currentCount: quest.currentCount,
totalCount: quest.totalCount)
}
}

extension QuestEntity {
func toDomain() -> Quest {
return Quest(groupId: groupId,
uuid: uuid,
date: date.toDate() ?? Date(),
title: title,
currentCount: currentCount,
totalCount: totalCount)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
//
// RealmQuestsStorage.swift
// DailyQuest
//
// Created by 이전희 on 2022/11/14.
//

import Foundation
import RxSwift

final class RealmQuestsStorage {

private let realmStorage: RealmStorage

init(realmStorage: RealmStorage = RealmStorage.shared) {
self.realmStorage = realmStorage
}
}

extension RealmQuestsStorage: QuestsStorage {

func saveQuests(with quests: [Quest]) -> Single<[Quest]> {
return Single.create { [weak self] single in
guard let realmStorage = self?.realmStorage else {
return Disposables.create()
}

do {
for quest in quests {
let questEntity = QuestEntity(quest: quest)
try realmStorage.saveEntity(entity: questEntity)
}
single(.success(quests))
} catch let error {
single(.failure(RealmStorageError.saveError(error)))

}
return Disposables.create()
}
}

func fetchQuests(by date: Date) -> Observable<[Quest]> {
return Observable<[Quest]>.create { [weak self] observer in
guard let realmStorage = self?.realmStorage else {
return Disposables.create()
}

do {
let quests = try realmStorage
.fetchEntities(type: QuestEntity.self, filter: NSPredicate(format: "date == %@", date.toString))
.compactMap { $0.toDomain() }
observer.onNext(quests)
observer.onCompleted()
} catch let error {
observer.onError(error)
}

return Disposables.create()
}
}

func updateQuest(with quest: Quest) -> Single<Quest> {
return Single.create { [weak self] single in
guard let realmStorage = self?.realmStorage else {
return Disposables.create()
}
let questEntity = QuestEntity(quest: quest)
do {
try realmStorage.updateEntity(entity: questEntity)
single(.success(quest))
} catch let error {
single(.failure(RealmStorageError.saveError(error)))
}

return Disposables.create()
}
}

func deleteQuest(with questId: UUID) -> Single<Quest> {
return Single.create { [weak self] single in
guard let realmStorage = self?.realmStorage else {
return Disposables.create()
}

do {
guard let entity = try realmStorage.findEntities(type: QuestEntity.self, filter: NSPredicate(format: "uuid == %@", questId as CVarArg)).first else {
throw RealmStorageError.noDataError
}
let quest = entity.toDomain()
try realmStorage.deleteEntity(entity: entity)
single(.success(quest))

} catch let error {
single(.failure(RealmStorageError.saveError(error)))
}

return Disposables.create()
}

}

func deleteQuestGroup(with groupId: UUID) -> Single<[Quest]> {
return Single.create { [weak self] single in
guard let realmStorage = self?.realmStorage else {
return Disposables.create()
}

do {
let entities = try realmStorage.findEntities(type: QuestEntity.self, filter: NSPredicate(format: "groupId == %@", groupId as CVarArg))
let quests = entities.compactMap { $0.toDomain() }
for entity in entities {
try realmStorage.deleteEntity(entity: entity)
}
single(.success(quests))

} catch let error {
single(.failure(RealmStorageError.saveError(error)))
}

return Disposables.create()
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,14 @@ import RealmSwift
final class BrowseQuestEntity: Object {
@Persisted var uuid: UUID
@Persisted var nickName: String
@Persisted var quests: List<UserQuestEntity>
@Persisted var quests: List<QuestEntity>

override init() { }

init(uuid: UUID, nickName: String, quests: [UserQuestEntity]) {
init(uuid: UUID, nickName: String, quests: [QuestEntity]) {
self.uuid = uuid
self.nickName = nickName
let realmList = List<UserQuestEntity>()
let realmList = List<QuestEntity>()
realmList.append(objectsIn: quests)
self.quests = realmList
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,26 +8,25 @@
import Foundation
import RealmSwift

final class UserQuestEntity: Object {
final class QuestEntity: Object {
@Persisted var groupId: UUID
@Persisted var uuid: UUID
@Persisted var date: String
@Persisted var title: String
@Persisted var startDay: Date
@Persisted var endDay: Date
@Persisted var `repeat`: Int
@Persisted var currentCount: Int
@Persisted var totalCount: Int

override init() { }

init(uuid: UUID, title: String, startDay: Date, endDay: Date, currentCount: Int, totalCount: Int) {
init(groupId: UUID, uuid: UUID, date: String, title: String, currentCount: Int, totalCount: Int) {
self.groupId = groupId
self.uuid = uuid
self.date = date
self.title = title
self.startDay = startDay
self.endDay = endDay
self.currentCount = currentCount
self.totalCount = totalCount
}

override class func primaryKey() -> String? {
"uuid"
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,27 +18,67 @@ enum RealmStorageError: Error {

final class RealmStorage {
static let shared = RealmStorage()

private init() {
// Realm file path
#if DEBUG
print(Realm.Configuration.defaultConfiguration.fileURL!)
#endif
}

private let persistentContainer = try? Realm()

func updateEntity(entity: Object) throws {
@discardableResult
func saveEntity<O: Object>(entity: O) throws -> O {
guard let persistentContainer = persistentContainer else {
throw RealmStorageError.realmObjectError
}
try persistentContainer.write {
persistentContainer.add(entity)
}
return entity
}

func fetchEntities<O: Object>(type: O.Type, filter: NSPredicate? = nil) throws -> [O] {
guard let persistentContainer = persistentContainer else {
throw RealmStorageError.realmObjectError
}
if let filter = filter {
print(filter)
return Array(persistentContainer.objects(type).filter(filter))
} else {
return Array(persistentContainer.objects(type))
}
}

func fetchEntities<O: Object>(type: O.Type) throws -> [O] {
@discardableResult
func updateEntity<O: Object>(entity: O) throws -> O {
guard let persistentContainer = persistentContainer else {
throw RealmStorageError.realmObjectError
}
return Array(persistentContainer.objects(type))
try persistentContainer.write {
persistentContainer.add(entity, update: .modified)
}
return entity
}

@discardableResult
func deleteEntity<O: Object>(entity: O) throws -> O {
guard let persistentContainer = persistentContainer else {
throw RealmStorageError.realmObjectError
}
try persistentContainer.write {
persistentContainer.delete(entity)
}

return entity
}

func findEntities<O: Object>(type: O.Type, filter: NSPredicate) throws -> [O] {
guard let persistentContainer = persistentContainer else {
throw RealmStorageError.realmObjectError
}
return Array(persistentContainer.objects(type).filter(filter))
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ extension RealmUserInfoStorage: UserInfoStorage {

do {
// update 성공했을 경우, success(user)
try realmStorage.updateEntity(entity: userInfo)
try realmStorage.saveEntity(entity: userInfo)
single(.success(user))
} catch let error {
// update 성공하지 못했을 경우, failure(error)
Expand Down
Loading

0 comments on commit 1d42a92

Please sign in to comment.