Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions homete/Model/Domain/Cohabitant/Housework/HouseworkItem.swift
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,23 @@ struct HouseworkItem: Identifiable, Equatable, Sendable, Hashable, Codable {
)
}

func updateRejected(at now: Date, reviewer: String, comment: String) -> Self {

return .init(
id: id,
indexedDate: indexedDate,
title: title,
point: point,
state: .incomplete,
executorId: executorId,
executedAt: executedAt,
reviewerId: reviewer,
approvedAt: now,
reviewerComment: comment,
expiredAt: expiredAt
)
}

func updateIncomplete() -> Self {

return .init(
Expand Down
107 changes: 50 additions & 57 deletions homete/Model/Domain/Cohabitant/Housework/HouseworkListStore.swift
Original file line number Diff line number Diff line change
Expand Up @@ -69,74 +69,43 @@ final class HouseworkListStore {

Task.detached {

// TODO: PushNotificationContentにファクトリーメソッドを定義する
let notificationContent = PushNotificationContent(
title: "新しい家事が登録されました",
message: newItem.title
)
let notificationContent = PushNotificationContent.addNewHouseworkItem(newItem.title)
try await self.cohabitantPushNotificationClient.send(self.cohabitantId, notificationContent)
}
}

func requestReview(target: HouseworkItem, now: Date, executor: String) async throws {

let targetIndexedDate = target.indexedDate
let targetId = target.id

guard let targetItem = items.item(targetId, targetIndexedDate) else {

preconditionFailure("Not found target item(id: \(targetId), indexedDate: \(targetIndexedDate))")
}

let updatedItem = targetItem.updatePendingApproval(at: now, changer: executor)
try await houseworkClient.insertOrUpdateItem(updatedItem, cohabitantId)

Task.detached {

let notificationContent = PushNotificationContent(
title: "確認が必要な家事があります",
message: "問題なければ「\(updatedItem.title)」の完了に感謝を伝えましょう!"
)
try await self.cohabitantPushNotificationClient.send(self.cohabitantId, notificationContent)

try await updateAndSave(target: target) {
$0.updatePendingApproval(at: now, changer: executor)
} notification: {
.requestReviewMessage(houseworkTitle: target.title)
}
}

func approved(target: HouseworkItem, now: Date, reviwer: Account, comment: String) async throws {

let targetIndexedDate = target.indexedDate
let targetId = target.id

guard let targetItem = items.item(targetId, targetIndexedDate) else {

preconditionFailure("Not found target item(id: \(targetId), indexedDate: \(targetIndexedDate))")

try await updateAndSave(target: target) {
$0.updateApproved(at: now, reviewer: reviwer.id, comment: comment)
} notification: {
.approvedMessage(reviwerName: reviwer.userName, houseworkTitle: target.title, comment: comment)
}

let updatedItem = targetItem.updateApproved(at: now, reviewer: reviwer.id, comment: comment)
try await houseworkClient.insertOrUpdateItem(updatedItem, cohabitantId)

Task.detached {

let notificationContent = PushNotificationContent.approvedMessage(
reviwerName: reviwer.userName,
houseworkTitle: target.title,
comment: comment
)
try await self.cohabitantPushNotificationClient.send(self.cohabitantId, notificationContent)
}

func rejected(target: HouseworkItem, now: Date, reviwer: Account, comment: String) async throws {

try await updateAndSave(target: target) {
$0.updateRejected(at: now, reviewer: reviwer.id, comment: comment)
} notification: {
.rejectedMessage(reviwerName: reviwer.userName, houseworkTitle: target.title, comment: comment)
}
}

func returnToIncomplete(target: HouseworkItem, now: Date) async throws {

let targetIndexedDate = target.indexedDate
let targetId = target.id

guard let targetItem = items.item(targetId, targetIndexedDate) else {

preconditionFailure("Not found target item(id: \(targetId), indexedDate: \(targetIndexedDate))")

func returnToIncomplete(target: HouseworkItem) async throws {

try await updateAndSave(target: target) {
$0.updateIncomplete()
}

let updatedItem = targetItem.updateIncomplete()
try await houseworkClient.insertOrUpdateItem(updatedItem, cohabitantId)
}

func remove(_ target: HouseworkItem) async throws {
Expand All @@ -146,10 +115,34 @@ final class HouseworkListStore {
}

private extension HouseworkListStore {

func clear() async {

await houseworkClient.removeListener(houseworkObserveKey)
items.removeAll()
}

func updateAndSave(
target: HouseworkItem,
transform: (HouseworkItem) -> HouseworkItem,
notification: (() -> PushNotificationContent)? = nil
) async throws {

guard let targetItem = items.item(target) else {
preconditionFailure("Not found target item(\(target))")
}

let updatedItem = transform(targetItem)
try await houseworkClient.insertOrUpdateItem(updatedItem, cohabitantId)

if let notification {
let content = notification()
Task.detached {
try await self.cohabitantPushNotificationClient.send(
self.cohabitantId,
content
)
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,12 @@ struct StoredAllHouseworkList: Equatable, Sendable {
return .init(value: items)
}

func item(_ id: String, _ indexedDate: HouseworkIndexedDate) -> HouseworkItem? {
func item(_ item: HouseworkItem) -> HouseworkItem? {

guard let targetDayList = value.first(
where: { $0.metaData.indexedDate == indexedDate }
where: { $0.metaData.indexedDate == item.indexedDate }
),
let targetItem = targetDayList.items.first(where: { $0.id == id }) else { return nil }
let targetItem = targetDayList.items.first(where: { $0.id == item.id }) else { return nil }
return targetItem
}

Expand Down
23 changes: 22 additions & 1 deletion homete/Model/Domain/PushNotificationContent.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,32 @@ struct PushNotificationContent: Equatable {
}

extension PushNotificationContent {


static func addNewHouseworkItem(_ houseworkTitle: String) -> Self {
return .init(
title: "新しい家事が登録されました",
message: houseworkTitle
)
}

static func requestReviewMessage(houseworkTitle: String) -> Self {
return .init(
title: "確認が必要な家事があります",
message: "問題なければ「\(houseworkTitle)」の完了に感謝を伝えましょう!"
)
}

static func approvedMessage(reviwerName: String, houseworkTitle: String, comment: String) -> Self {
return .init(
title: "\(reviwerName)が「\(houseworkTitle)」を承認しました!",
message: comment
)
}

static func rejectedMessage(reviwerName: String, houseworkTitle: String, comment: String) -> Self {
return .init(
title: "「\(houseworkTitle)」を再確認してください",
message: comment
)
}
}
6 changes: 5 additions & 1 deletion homete/Resouces/Localizable.xcstrings
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,10 @@
},
"共に家事を頑張るパートナーへ、エールを送り合いませんか?" : {

},
"再確認してもらう" : {
"comment" : "A button label that triggers a request to resend a confirmation message to the executor.",
"isCommentAutoGenerated" : true
},
"削除" : {

Expand Down Expand Up @@ -309,5 +313,5 @@

}
},
"version" : "1.0"
"version" : "1.1"
}
29 changes: 25 additions & 4 deletions homete/Views/HouseworkApproval/HouseworkApprovalView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ struct HouseworkApprovalView: View {
@Environment(\.loginContext.account) var account
@Environment(\.dismiss) var dismiss
@CommonError var commonError
@LoadingState var loadingState

@State var inputMessage = ""

Expand Down Expand Up @@ -41,6 +42,7 @@ struct HouseworkApprovalView: View {
.toolbar {
navigationLeadingItem()
}
.fullScreenLoadingIndicator(loadingState)
}
}
}
Expand Down Expand Up @@ -101,7 +103,7 @@ private extension HouseworkApprovalView {
func actionButtonContent() -> some View {
VStack(spacing: .space16) {
Button {
Task {
loadingState.task {
await tappedApproveButton()
}
} label: {
Expand All @@ -110,12 +112,14 @@ private extension HouseworkApprovalView {
}
.subPrimaryButtonStyle()
Button {
// TODO: 家事を未完了に戻す
loadingState.task {
await tappedReconfirmationButton()
}
} label: {
Text("未完了に戻す")
Text("再確認してもらう")
.frame(maxWidth: .infinity)
}
.destructiveButtonStyle()
.primaryButtonStyle()
}
.disabled(inputMessage.isEmpty)
}
Expand All @@ -141,6 +145,23 @@ private extension HouseworkApprovalView {
commonError = .init(error: error)
}
}

func tappedReconfirmationButton() async {

do {

try await houseworkListStore.rejected(
target: item,
now: .now,
reviwer: account,
comment: inputMessage
)
dismiss()
} catch {

commonError = .init(error: error)
}
}
}

#Preview {
Expand Down
2 changes: 1 addition & 1 deletion homete/Views/HouseworkDetailView/HouseworkDetailView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ private extension HouseworkDetailView {

func didChangeItems() {

guard let targetItem = houseworkListStore.items.item(item.id, item.indexedDate) else { return }
guard let targetItem = houseworkListStore.items.item(item) else { return }

withAnimation {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ private extension HouseworkDetailActionContent {

do {

try await houseworkListStore.returnToIncomplete(target: item, now: .now)
try await houseworkListStore.returnToIncomplete(target: item)
} catch {

commonErrorContent = .init(error: error)
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Loading