From 1ff11c13b75125737767cc958439b8bfd9cfbc51 Mon Sep 17 00:00:00 2001 From: NiraliSonani Date: Fri, 29 Nov 2024 15:05:22 +0530 Subject: [PATCH] Added reason in list & detail & added focus on note only --- Splito/Localization/Localizable.xcstrings | 22 +++-- Splito/UI/Home/Expense/Note/AddNoteView.swift | 87 ++++++++++--------- .../Home/Expense/Note/AddNoteViewModel.swift | 7 +- .../Payment/GroupPaymentViewModel.swift | 4 +- .../GroupTransactionListView.swift | 12 ++- .../GroupTransactionDetailView.swift | 21 +++-- .../GroupTransactionDetailViewModel.swift | 9 +- 7 files changed, 92 insertions(+), 70 deletions(-) diff --git a/Splito/Localization/Localizable.xcstrings b/Splito/Localization/Localizable.xcstrings index 1da6cf9ad..26607fb7f 100644 --- a/Splito/Localization/Localizable.xcstrings +++ b/Splito/Localization/Localizable.xcstrings @@ -88,6 +88,16 @@ } } }, + "%@ paid %@ for '%@'" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "%1$@ paid %2$@ for '%3$@'" + } + } + } + }, "%@ people" : { "extractionState" : "manual" }, @@ -310,9 +320,6 @@ }, "Enter a description" : { "extractionState" : "manual" - }, - "Enter a reason for this payment" : { - }, "Enter a valid phone number." : { "extractionState" : "manual" @@ -337,9 +344,6 @@ }, "Enter your last name" : { "extractionState" : "manual" - }, - "Enter your note here..." : { - }, "Enter your phone number" : { "extractionState" : "manual" @@ -514,9 +518,6 @@ }, "not involved" : { - }, - "Note" : { - }, "Note:" : { @@ -601,9 +602,6 @@ }, "Reach out to your friends to get the code of the group they created." : { - }, - "Reason" : { - }, "Reauthenticate" : { "extractionState" : "manual" diff --git a/Splito/UI/Home/Expense/Note/AddNoteView.swift b/Splito/UI/Home/Expense/Note/AddNoteView.swift index a6a4275da..c75abdf9e 100644 --- a/Splito/UI/Home/Expense/Note/AddNoteView.swift +++ b/Splito/UI/Home/Expense/Note/AddNoteView.swift @@ -15,51 +15,29 @@ struct AddNoteView: View { @State private var tempNote: String = "" @State private var tempPaymentReason: String = "" + @FocusState private var isFocused: Bool var body: some View { VStack(alignment: .leading, spacing: 16) { if let paymentReason = viewModel.paymentReason { - VStack(alignment: .leading, spacing: 8) { - Text("Reason") - .font(.body3()) - .foregroundStyle(disableText) - - TextField("Enter a reason for this payment", text: $tempPaymentReason) - .font(.subTitle2()) - .foregroundStyle(primaryText) - .focused($isFocused) - .tint(primaryColor) - .autocorrectionDisabled() - .padding(16) - .overlay { - RoundedRectangle(cornerRadius: 12) - .stroke(outlineColor, lineWidth: 1) - } - } - .onAppear { - tempPaymentReason = paymentReason - } - } - - VStack(alignment: .leading, spacing: 8) { - Text("Note") - .font(.body3()) - .foregroundStyle(disableText) - - TextField("Enter your note here...", text: $tempNote, axis: .vertical) - .font(.subTitle2()) - .foregroundStyle(primaryText) - .focused($isFocused) - .tint(primaryColor) - .autocorrectionDisabled() - .padding(16) - .overlay { - RoundedRectangle(cornerRadius: 12) - .stroke(outlineColor, lineWidth: 1) + InputFieldView( + text: $tempPaymentReason, title: "Reason", + placeholder: "Enter a reason for this payment", axis: .horizontal, + onAppear: { + tempPaymentReason = paymentReason.isEmpty ? "Payment" : paymentReason } + ) } + InputFieldView( + text: $tempNote, title: "Note", placeholder: "Enter your note here...", + onAppear: { + tempNote = viewModel.note + } + ) + .focused($isFocused) + Spacer() } .padding(16) @@ -71,7 +49,6 @@ struct AddNoteView: View { .toastView(toast: $viewModel.toast) .backport.alert(isPresented: $viewModel.showAlert, alertStruct: viewModel.alert) .onAppear { - tempNote = viewModel.note isFocused = true } .toolbar { @@ -80,9 +57,8 @@ struct AddNoteView: View { } ToolbarItem(placement: .topBarTrailing) { CheckmarkButton(showLoader: viewModel.showLoader) { - viewModel.note = tempNote.trimming(spaces: .leadingAndTrailing) Task { - let isActionSucceed = await viewModel.handleSaveNoteAction() + let isActionSucceed = await viewModel.handleSaveNoteAction(tempNote: tempNote, tempPaymentReason: tempPaymentReason) if isActionSucceed { dismiss() } else { @@ -95,6 +71,37 @@ struct AddNoteView: View { } } +private struct InputFieldView: View { + + @Binding var text: String + + let title: String + let placeholder: String + var axis: Axis = .vertical + + var onAppear: (() -> Void) + + var body: some View { + VStack(alignment: .leading, spacing: 8) { + Text(title) + .font(.body3()) + .foregroundStyle(disableText) + + TextField(placeholder.localized, text: $text, axis: axis) + .font(.subTitle2()) + .foregroundStyle(primaryText) + .tint(primaryColor) + .autocorrectionDisabled() + .padding(16) + .overlay { + RoundedRectangle(cornerRadius: 12) + .stroke(outlineColor, lineWidth: 1) + } + } + .onAppear(perform: onAppear) + } +} + struct CancelButton: View { @Environment(\.dismiss) var dismiss diff --git a/Splito/UI/Home/Expense/Note/AddNoteViewModel.swift b/Splito/UI/Home/Expense/Note/AddNoteViewModel.swift index 3338126b4..ffe576c30 100644 --- a/Splito/UI/Home/Expense/Note/AddNoteViewModel.swift +++ b/Splito/UI/Home/Expense/Note/AddNoteViewModel.swift @@ -40,7 +40,10 @@ class AddNoteViewModel: BaseViewModel, ObservableObject { self.showToastFor(toast: ToastPrompt(type: .error, title: "Oops", message: "Failed to save note.")) } - func handleSaveNoteAction() async -> Bool { + func handleSaveNoteAction(tempNote: String, tempPaymentReason: String) async -> Bool { + note = tempNote.trimming(spaces: .leadingAndTrailing) + paymentReason = (tempPaymentReason == "Payment") ? nil : tempPaymentReason.trimming(spaces: .leadingAndTrailing) + if let handleSaveNoteTap { handleSaveNoteTap(note, paymentReason) return true @@ -48,7 +51,7 @@ class AddNoteViewModel: BaseViewModel, ObservableObject { if let expense, expense.note != note { return await updateExpenseNote() - } else if let payment, payment.note != note { + } else if let payment, (payment.note != note || payment.reason != paymentReason) { return await updatePaymentNote() } diff --git a/Splito/UI/Home/Groups/Group/Group Options/Settle up/Payment/GroupPaymentViewModel.swift b/Splito/UI/Home/Groups/Group/Group Options/Settle up/Payment/GroupPaymentViewModel.swift index 79fec16b7..aa2608f41 100644 --- a/Splito/UI/Home/Groups/Group/Group Options/Settle up/Payment/GroupPaymentViewModel.swift +++ b/Splito/UI/Home/Groups/Group/Group Options/Settle up/Payment/GroupPaymentViewModel.swift @@ -23,7 +23,7 @@ class GroupPaymentViewModel: BaseViewModel, ObservableObject { @Published var paymentDate = Date() @Published var paymentImage: UIImage? - @Published var paymentReason: String = "" + @Published var paymentReason: String? @Published var paymentNote: String = "" @Published private(set) var paymentImageUrl: String? @@ -155,7 +155,7 @@ class GroupPaymentViewModel: BaseViewModel, ObservableObject { func handleNoteSaveBtnTap(note: String, reason: String?) { showAddNoteEditor = false self.paymentNote = note - self.paymentReason = reason ?? "" + self.paymentReason = reason } func handlePaymentImageTap() { diff --git a/Splito/UI/Home/Groups/Group/Group Options/Transactions/GroupTransactionListView.swift b/Splito/UI/Home/Groups/Group/Group Options/Transactions/GroupTransactionListView.swift index cf77c4b43..e5ad1a8c5 100644 --- a/Splito/UI/Home/Groups/Group/Group Options/Transactions/GroupTransactionListView.swift +++ b/Splito/UI/Home/Groups/Group/Group Options/Transactions/GroupTransactionListView.swift @@ -177,9 +177,15 @@ private struct TransactionItemView: View { .padding(.trailing, 16) HStack(spacing: 0) { - Text("\(payerName.localized) paid \(receiverName.localized)") - .font(.subTitle2()) - .foregroundStyle(primaryText) + if let reason = transactionWithUser.transaction.reason, !reason.isEmpty { + Text("\(payerName.localized) paid \(receiverName.localized) for '\(reason)'") + .font(.subTitle2()) + .foregroundStyle(primaryText) + } else { + Text("\(payerName.localized) paid \(receiverName.localized)") + .font(.subTitle2()) + .foregroundStyle(primaryText) + } Spacer() diff --git a/Splito/UI/Home/Groups/Group/Group Options/Transactions/Transaction Detail/GroupTransactionDetailView.swift b/Splito/UI/Home/Groups/Group/Group Options/Transactions/Transaction Detail/GroupTransactionDetailView.swift index ab0acc511..54dab5801 100644 --- a/Splito/UI/Home/Groups/Group/Group Options/Transactions/Transaction Detail/GroupTransactionDetailView.swift +++ b/Splito/UI/Home/Groups/Group/Group Options/Transactions/Transaction Detail/GroupTransactionDetailView.swift @@ -165,7 +165,7 @@ private struct TransactionInfoView: View { .background(container2Color) .cornerRadius(16) - TransactionSummaryView(date: viewModel.transaction?.date.dateValue(), amount: viewModel.transaction?.amount, payerName: payerName, receiverName: receiverName, addedUserName: addedUserName) + TransactionSummaryView(date: viewModel.transaction?.date.dateValue(), amount: viewModel.transaction?.amount, reason: viewModel.paymentReason, payerName: payerName, receiverName: receiverName, addedUserName: addedUserName) } .multilineTextAlignment(.center) } @@ -198,17 +198,26 @@ private struct TransactionSummaryView: View { let date: Date? let amount: Double? + let reason: String? let payerName: String let receiverName: String let addedUserName: String var body: some View { VStack(spacing: 0) { - Text("\(payerName.localized) paid \(receiverName.localized)") - .font(.subTitle2()) - .foregroundStyle(primaryText) - .lineSpacing(2) - .padding(.bottom, 8) + if let reason, !reason.isEmpty { + Text("\(payerName.localized) paid \(receiverName.localized) for '\(reason)'") + .font(.subTitle2()) + .foregroundStyle(primaryText) + .lineSpacing(2) + .padding(.bottom, 8) + } else { + Text("\(payerName.localized) paid \(receiverName.localized)") + .font(.subTitle2()) + .foregroundStyle(primaryText) + .lineSpacing(2) + .padding(.bottom, 8) + } Text(amount?.formattedCurrency ?? "₹ 0") .font(.Header2()) diff --git a/Splito/UI/Home/Groups/Group/Group Options/Transactions/Transaction Detail/GroupTransactionDetailViewModel.swift b/Splito/UI/Home/Groups/Group/Group Options/Transactions/Transaction Detail/GroupTransactionDetailViewModel.swift index 5720dcfcb..a1ae9f550 100644 --- a/Splito/UI/Home/Groups/Group/Group Options/Transactions/Transaction Detail/GroupTransactionDetailViewModel.swift +++ b/Splito/UI/Home/Groups/Group/Group Options/Transactions/Transaction Detail/GroupTransactionDetailViewModel.swift @@ -16,7 +16,7 @@ class GroupTransactionDetailViewModel: BaseViewModel, ObservableObject { @Inject private var transactionRepository: TransactionRepository @Published var paymentNote: String = "" - @Published var paymentReason: String = "" + @Published var paymentReason: String? @Published private(set) var transaction: Transactions? @Published private(set) var transactionUsersData: [AppUser] = [] @@ -65,8 +65,7 @@ class GroupTransactionDetailViewModel: BaseViewModel, ObservableObject { func fetchTransaction() async { do { viewState = .loading - let transaction = try await transactionRepository.fetchTransactionBy(groupId: groupId, transactionId: transactionId) - self.transaction = transaction + self.transaction = try await transactionRepository.fetchTransactionBy(groupId: groupId, transactionId: transactionId) await setTransactionUsersData() self.viewState = .initial LogD("GroupTransactionDetailViewModel: \(#function) Payment fetched successfully.") @@ -94,7 +93,7 @@ class GroupTransactionDetailViewModel: BaseViewModel, ObservableObject { self.transactionUsersData = userData self.paymentNote = transaction.note ?? "" - self.paymentReason = transaction.reason ?? "" + self.paymentReason = transaction.reason } private func fetchUserData(for userId: String) async -> AppUser? { @@ -264,7 +263,7 @@ class GroupTransactionDetailViewModel: BaseViewModel, ObservableObject { guard let updatedTransaction = notification.object as? Transactions else { return } transaction = updatedTransaction paymentNote = updatedTransaction.note ?? "" - paymentReason = updatedTransaction.reason ?? "" + paymentReason = updatedTransaction.reason } // MARK: - Error Handling