From 995bc132211d91b538c84c5675f47e0eefb1e15f Mon Sep 17 00:00:00 2001 From: ahmermughal Date: Sat, 2 Aug 2025 16:07:01 +0200 Subject: [PATCH] default category and minor code opt --- app/dime/Data/DataController.swift | 171 ++++++++++++--------------- app/dime/Views/TransactionView.swift | 5 + 2 files changed, 80 insertions(+), 96 deletions(-) diff --git a/app/dime/Data/DataController.swift b/app/dime/Data/DataController.swift index 88878d2..1f53174 100644 --- a/app/dime/Data/DataController.swift +++ b/app/dime/Data/DataController.swift @@ -417,6 +417,13 @@ class DataController: ObservableObject { } } + func fetchRequestForDefaultCategory(income: Bool) -> NSFetchRequest { + let itemRequest: NSFetchRequest = Category.fetchRequest() + itemRequest.sortDescriptors = [NSSortDescriptor(key: "order", ascending: true)] + itemRequest.predicate = NSPredicate(format: "income = %d AND name == %@", income, "Default") + return itemRequest + } + func fetchRequestForCategories(income: Bool) -> NSFetchRequest { let itemRequest: NSFetchRequest = Category.fetchRequest() itemRequest.sortDescriptors = [NSSortDescriptor(key: "order", ascending: true)] @@ -509,6 +516,31 @@ class DataController: ObservableObject { throw CustomError.notFound } } + + func getDefaultCategory(income: Bool) -> Category? { + + let request = fetchRequestForDefaultCategory(income: income) + + do { + let results = try container.viewContext.fetch(request) + if let category = results.first { + return category + } else { + let category = Category(context: self.container.viewContext) + category.name = "Default" + category.emoji = "🏷️" + category.dateCreated = Date.now + category.id = UUID() + category.income = income + category.colour = "#9E9E9E" + + self.save() + return getDefaultCategory(income: income) + } + } catch { + return nil + } + } func categoryCheck(name: String, emoji: String, income: Bool) -> (error: CategoryError, order: Int64) { if name.trimmingCharacters(in: .whitespacesAndNewlines) == "" && emoji == "" { @@ -518,51 +550,26 @@ class DataController: ObservableObject { } else if emoji == "" { return (CategoryError.missingEmoji, 0) } - - if income { - let fetchRequest = fetchRequestForCategories(income: true) - let incomeCategories = results(for: fetchRequest) - - var emojiArray = [String]() - var nameArray = [String]() - - incomeCategories.forEach { category in - emojiArray.append(category.wrappedEmoji) - nameArray.append(category.wrappedName) - } - - if emojiArray.contains(emoji) && nameArray.contains(name) { - return (CategoryError.duplicate, 0) - } else if emojiArray.contains(emoji) { - return (CategoryError.duplicateEmoji, 0) - } else if nameArray.contains(name) { - return (CategoryError.duplicateName, 0) - } else { - let newItemOrder = (incomeCategories.last?.order ?? 0) + 1 - return (CategoryError.none, newItemOrder) - } + let fetchRequest = fetchRequestForCategories(income: income) + let categories = results(for: fetchRequest) + var emojiArray = [String]() + var nameArray = [String]() + + + categories.forEach { category in + emojiArray.append(category.wrappedEmoji) + nameArray.append(category.wrappedName) + } + + if emojiArray.contains(emoji) && nameArray.contains(name) { + return (CategoryError.duplicate, 0) + } else if emojiArray.contains(emoji) { + return (CategoryError.duplicateEmoji, 0) + } else if nameArray.contains(name) { + return (CategoryError.duplicateName, 0) } else { - let fetchRequest = fetchRequestForCategories(income: false) - let expenseCategories = results(for: fetchRequest) - - var emojiArray = [String]() - var nameArray = [String]() - - expenseCategories.forEach { category in - emojiArray.append(category.wrappedEmoji) - nameArray.append(category.wrappedName) - } - - if emojiArray.contains(emoji) && nameArray.contains(name) { - return (CategoryError.duplicate, 0) - } else if emojiArray.contains(emoji) { - return (CategoryError.duplicateEmoji, 0) - } else if nameArray.contains(name) { - return (CategoryError.duplicateName, 0) - } else { - let newItemOrder = (expenseCategories.last?.order ?? 0) + 1 - return (CategoryError.none, newItemOrder) - } + let newItemOrder = (categories.last?.order ?? 0) + 1 + return (CategoryError.none, newItemOrder) } } @@ -574,59 +581,31 @@ class DataController: ObservableObject { } else if emoji == "" { return (CategoryError.missingEmoji, 0) } - - if toEdit.income { - let fetchRequest = fetchRequestForCategories(income: true) - var incomeCategories = results(for: fetchRequest) - - if let position = incomeCategories.firstIndex(of: toEdit) { - incomeCategories.remove(at: position) - } - - var emojiArray = [String]() - var nameArray = [String]() - - incomeCategories.forEach { category in - emojiArray.append(category.wrappedEmoji) - nameArray.append(category.wrappedName) - } - - if emojiArray.contains(emoji) && nameArray.contains(name) { - return (CategoryError.duplicate, 0) - } else if emojiArray.contains(emoji) { - return (CategoryError.duplicateEmoji, 0) - } else if nameArray.contains(name) { - return (CategoryError.duplicateName, 0) - } else { - let newItemOrder = (incomeCategories.last?.order ?? 0) + 1 - return (CategoryError.none, newItemOrder) - } + + let fetchRequest = fetchRequestForCategories(income: toEdit.income) + var categories = results(for: fetchRequest) + + if let position = categories.firstIndex(of: toEdit) { + categories.remove(at: position) + } + + var emojiArray = [String]() + var nameArray = [String]() + + categories.forEach { category in + emojiArray.append(category.wrappedEmoji) + nameArray.append(category.wrappedName) + } + + if emojiArray.contains(emoji) && nameArray.contains(name) { + return (CategoryError.duplicate, 0) + } else if emojiArray.contains(emoji) { + return (CategoryError.duplicateEmoji, 0) + } else if nameArray.contains(name) { + return (CategoryError.duplicateName, 0) } else { - let fetchRequest = fetchRequestForCategories(income: false) - var expenseCategories = results(for: fetchRequest) - - if let position = expenseCategories.firstIndex(of: toEdit) { - expenseCategories.remove(at: position) - } - - var emojiArray = [String]() - var nameArray = [String]() - - expenseCategories.forEach { category in - emojiArray.append(category.wrappedEmoji) - nameArray.append(category.wrappedName) - } - - if emojiArray.contains(emoji) && nameArray.contains(name) { - return (CategoryError.duplicate, 0) - } else if emojiArray.contains(emoji) { - return (CategoryError.duplicateEmoji, 0) - } else if nameArray.contains(name) { - return (CategoryError.duplicateName, 0) - } else { - let newItemOrder = (expenseCategories.last?.order ?? 0) + 1 - return (CategoryError.none, newItemOrder) - } + let newItemOrder = (categories.last?.order ?? 0) + 1 + return (CategoryError.none, newItemOrder) } } diff --git a/app/dime/Views/TransactionView.swift b/app/dime/Views/TransactionView.swift index 5945aaf..b5ab7ea 100644 --- a/app/dime/Views/TransactionView.swift +++ b/app/dime/Views/TransactionView.swift @@ -989,6 +989,11 @@ struct TransactionView: View { func submit() { let generator = UINotificationFeedbackGenerator() + // select or create a default category if none is selected. + if self.category == nil { + self.category = self.dataController.getDefaultCategory(income: income) + } + if price == 0 && category == nil { toastImage = "questionmark.app" toastTitle = "Incomplete Entry"