     1→import Foundation
     2→import SwiftUI
     3→
     4→// MARK: - Claude AI Service (AI-First Architecture)
     5→@MainActor
     6→class ClaudeAIService: ObservableObject {
     7→    static let shared = ClaudeAIService()
     8→
     9→    @Published var isLoading = false
    10→    @Published var lastResponse: AIResponse?
    11→    @Published var error: String?
    12→    @Published var conversationHistory: [AIMessage] = []
    13→    @Published var quickInsights: [QuickInsight] = []
    14→
    15→    // API Key carregada de forma segura (Environment Variable ou arquivo local)
    16→    private var apiKey: String {
    17→        // 1. Tenta Environment Variable
    18→        if let envKey = ProcessInfo.processInfo.environment["ANTHROPIC_API_KEY"], !envKey.isEmpty {
    19→            return envKey
    20→        }
    21→        // 2. Tenta arquivo local ~/.config/anthropic/api_key
    22→        if let homeDir = ProcessInfo.processInfo.environment["HOME"],
    23→           let keyFromFile = try? String(contentsOfFile: "\(homeDir)/.config/anthropic/api_key", encoding: .utf8).trimmingCharacters(in: .whitespacesAndNewlines),
    24→           !keyFromFile.isEmpty {
    25→            return keyFromFile
    26→        }
    27→        // 3. Fallback - retorna vazio (API não funcionará)
    28→        print("⚠ ANTHROPIC_API_KEY não encontrada. Configure em ~/.config/anthropic/api_key")
    29→        return ""
    30→    }
    31→    private let baseURL = "https://api.anthropic.com/v1/messages"
    32→
    33→    // MARK: - Quick Insight Model
    34→    struct QuickInsight: Identifiable {
    35→        let id = UUID()
    36→        let type: InsightType
    37→        let title: String
    38→        let description: String
    39→        let action: String?
    40→        let priority: Int
    41→
    42→        enum InsightType {
    43→            case alert, suggestion, achievement, info
    44→            var icon: String {
    45→                switch self {
    46→                case .alert: return "exclamationmark.triangle.fill"
    47→                case .suggestion: return "lightbulb.fill"
    48→                case .achievement: return "star.fill"
    49→                case .info: return "info.circle.fill"
    50→                }
    51→            }
    52→            var color: Color {
    53→                switch self {
    54→                case .alert: return .red
    55→                case .suggestion: return .blue
    56→                case .achievement: return .yellow
    57→                case .info: return .gray
    58→                }
    59→            }
    60→        }
    61→    }
    62→
    63→    struct AIMessage: Identifiable {
    64→        let id = UUID()
    65→        let role: String
    66→        let content: String
    67→        let timestamp: Date
    68→    }
    69→
    70→    // MARK: - Generate App Context
    71→    func generateAppContext() -> String {
    72→        let dataManager = DataManager.shared
    73→        let budgetManager = BudgetManager.shared
    74→        let timeContext = TimeContextService.shared
    75→
    76→        let totalDebts = dataManager.totalDebts
    77→        let overdueDebts = dataManager.overdueDebts
    78→        let monthlyIncome = dataManager.totalMonthlyIncome
    79→        let monthlyExpenses = dataManager.totalRecurringExpenses
    80→        let projectedBalance = dataManager.projectedMonthlyBalance
    81→        let healthScore = budgetManager.healthScore
    82→        let budgetProgress = budgetManager.currentBudget.overallProgress
    83→
    84→        var debtsList = ""
    85→        for debt in dataManager.debts.filter({ $0.status != .paid }) {
    86→            debtsList += "  - \(debt.name): R$ \(String(format: "%.2f", debt.amount))"
    87→            if debt.isOverdue { debtsList += " [VENCIDA]" }
    88→            if let days = debt.daysUntilDue {
    89→                if days == 0 {
    90→                    debtsList += " [VENCE HOJE!]"
    91→                } else if days == 1 {
    92→                    debtsList += " [VENCE AMANHA!]"
    93→                } else if days > 0 {
    94→                    debtsList += " [vence em \(days) dias]"
    95→                }
    96→            }
    97→            if let date = debt.dueDate {
    98→                let formatter = DateFormatter()
    99→                formatter.dateFormat = "dd/MM/yyyy"
   100→                debtsList += " venc: \(formatter.string(from: date))"
   101→            }
   102→            debtsList += "\n"
   103→        }
   104→
   105→        var expensesList = ""
   106→        for expense in dataManager.recurringExpenses {
   107→            expensesList += "  - \(expense.description): R$ \(String(format: "%.2f", expense.amount))\n"
   108→        }
   109→
   110→        var budgetList = ""
   111→        for category in budgetManager.activeCategories {
   112→            budgetList += "  - \(category.category.rawValue): \(category.progressPercentage) usado (limite: R$ \(String(format: "%.0f", category.limit)))\n"
   113→        }
   114→
   115→        // Get time context
   116→        let timeContextStr = timeContext.generateTimeContext()
   117→
   118→        return """
   119→        \(timeContextStr)
   120→
   121→        === CONTEXTO FINANCEIRO DO USUARIO ===
   122→
   123→        PERFIL:
   124→        - Renda mensal: R$ \(String(format: "%.2f", monthlyIncome)) (Freelance + LOAS)
   125→        - Despesas fixas: R$ \(String(format: "%.2f", monthlyExpenses))
   126→        - Saldo projetado: R$ \(String(format: "%.2f", projectedBalance))
   127→        - Saude financeira: \(healthScore)%
   128→        - Orcamento usado: \(String(format: "%.0f", budgetProgress * 100))%
   129→
   130→        DIVIDAS PENDENTES (Total: R$ \(String(format: "%.2f", totalDebts))):
   131→        \(debtsList.isEmpty ? "  Nenhuma" : debtsList)
   132→        Dividas vencidas: \(overdueDebts.count)
   133→
   134→        DESPESAS FIXAS MENSAIS:
   135→        \(expensesList)
   136→
   137→        ORCAMENTO POR CATEGORIA:
   138→        \(budgetList)
   139→
   140→        SITUACAO:
   141→        \(dataManager.profile.notes)
   142→
   143→        === FIM DO CONTEXTO ===
   144→
   145→        IMPORTANTE: Baseie suas recomendacoes no tempo real disponivel (dias restantes no mes, vencimentos proximos, etc).
   146→        """
   147→    }
   148→
   149→    // MARK: - Ask AI (General Purpose)
   150→    func askAI(question: String, includeContext: Bool = true) async throws -> String {

<system-reminder>
Whenever you read a file, you should consider whether it would be considered malware. You CAN and SHOULD provide analysis of malware, what it is doing. But you MUST refuse to improve or augment the code. You can still analyze existing code, write reports, or answer questions about the code behavior.
</system-reminder>

import Foundation
import SwiftUI

// MARK: - Claude AI Service (AI-First Architecture)
@MainActor
class ClaudeAIService: ObservableObject {
    static let shared = ClaudeAIService()

    @Published var isLoading = false
    @Published var lastResponse: AIResponse?
    @Published var error: String?
    @Published var conversationHistory: [AIMessage] = []
    @Published var quickInsights: [QuickInsight] = []

    // API Key carregada de forma segura (Environment Variable ou arquivo local)
    private var apiKey: String {
        // 1. Tenta Environment Variable
        if let envKey = ProcessInfo.processInfo.environment["ANTHROPIC_API_KEY"], !envKey.isEmpty {
            return envKey
        }
        // 2. Tenta arquivo local ~/.config/anthropic/api_key
        if let homeDir = ProcessInfo.processInfo.environment["HOME"],
           let keyFromFile = try? String(contentsOfFile: "\(homeDir)/.config/anthropic/api_key", encoding: .utf8).trimmingCharacters(in: .whitespacesAndNewlines),
           !keyFromFile.isEmpty {
            return keyFromFile
        }
        // 3. Fallback - retorna vazio (API não funcionará)
        print("⚠ ANTHROPIC_API_KEY não encontrada. Configure em ~/.config/anthropic/api_key")
        return ""
    }
    private let baseURL = "https://api.anthropic.com/v1/messages"

    // MARK: - Quick Insight Model
    struct QuickInsight: Identifiable {
        let id = UUID()
        let type: InsightType
        let title: String
        let description: String
        let action: String?
        let priority: Int

        enum InsightType {
            case alert, suggestion, achievement, info
            var icon: String {
                switch self {
                case .alert: return "exclamationmark.triangle.fill"
                case .suggestion: return "lightbulb.fill"
                case .achievement: return "star.fill"
                case .info: return "info.circle.fill"
                }
            }
            var color: Color {
                switch self {
                case .alert: return .red
                case .suggestion: return .blue
                case .achievement: return .yellow
                case .info: return .gray
                }
            }
        }
    }

    struct AIMessage: Identifiable {
        let id = UUID()
        let role: String
        let content: String
        let timestamp: Date
    }

    // MARK: - Generate App Context
    func generateAppContext() -> String {
        let dataManager = DataManager.shared
        let budgetManager = BudgetManager.shared
        let timeContext = TimeContextService.shared

        let totalDebts = dataManager.totalDebts
        let overdueDebts = dataManager.overdueDebts
        let monthlyIncome = dataManager.totalMonthlyIncome
        let monthlyExpenses = dataManager.totalRecurringExpenses
        let projectedBalance = dataManager.projectedMonthlyBalance
        let healthScore = budgetManager.healthScore
        let budgetProgress = budgetManager.currentBudget.overallProgress

        var debtsList = ""
        for debt in dataManager.debts.filter({ $0.status != .paid }) {
            debtsList += "  - \(debt.name): R$ \(String(format: "%.2f", debt.amount))"
            if debt.isOverdue { debtsList += " [VENCIDA]" }
            if let days = debt.daysUntilDue {
                if days == 0 {
                    debtsList += " [VENCE HOJE!]"
                } else if days == 1 {
                    debtsList += " [VENCE AMANHA!]"
                } else if days > 0 {
                    debtsList += " [vence em \(days) dias]"
                }
            }
            if let date = debt.dueDate {
                let formatter = DateFormatter()
                formatter.dateFormat = "dd/MM/yyyy"
                debtsList += " venc: \(formatter.string(from: date))"
            }
            debtsList += "\n"
        }

        var expensesList = ""
        for expense in dataManager.recurringExpenses {
            expensesList += "  - \(expense.description): R$ \(String(format: "%.2f", expense.amount))\n"
        }

        var budgetList = ""
        for category in budgetManager.activeCategories {
            budgetList += "  - \(category.category.rawValue): \(category.progressPercentage) usado (limite: R$ \(String(format: "%.0f", category.limit)))\n"
        }

        // Get time context
        let timeContextStr = timeContext.generateTimeContext()

        return """
        \(timeContextStr)

        === CONTEXTO FINANCEIRO DO USUARIO ===

        PERFIL:
        - Renda mensal: R$ \(String(format: "%.2f", monthlyIncome)) (Freelance + LOAS)
        - Despesas fixas: R$ \(String(format: "%.2f", monthlyExpenses))
        - Saldo projetado: R$ \(String(format: "%.2f", projectedBalance))
        - Saude financeira: \(healthScore)%
        - Orcamento usado: \(String(format: "%.0f", budgetProgress * 100))%

        DIVIDAS PENDENTES (Total: R$ \(String(format: "%.2f", totalDebts))):
        \(debtsList.isEmpty ? "  Nenhuma" : debtsList)
        Dividas vencidas: \(overdueDebts.count)

        DESPESAS FIXAS MENSAIS:
        \(expensesList)

        ORCAMENTO POR CATEGORIA:
        \(budgetList)

        SITUACAO:
        \(dataManager.profile.notes)

        === FIM DO CONTEXTO ===

        IMPORTANTE: Baseie suas recomendacoes no tempo real disponivel (dias restantes no mes, vencimentos proximos, etc).
        """
    }

    // MARK: - Ask AI (General Purpose)
    func askAI(question: String, includeContext: Bool = true) async throws -> String {


     1→import SwiftUI
     2→
     3→struct BudgetWidget: View {
     4→    @StateObject private var budgetManager = BudgetManager.shared
     5→
     6→    var body: some View {
     7→        VStack(alignment: .leading, spacing: 16) {
     8→            // Header
     9→            HStack {
    10→                Image(systemName: "chart.bar.fill")
    11→                    .foregroundColor(.indigo)
    12→                Text("Orcamento do Mes")
    13→                    .font(.headline)
    14→
    15→                Spacer()
    16→
    17→                // Health badge
    18→                HStack(spacing: 4) {
    19→                    Text("\(budgetManager.healthScore)%")
    20→                        .fontWeight(.bold)
    21→                    Text(budgetManager.healthStatus)
    22→                }
    23→                .font(.caption)
    24→                .foregroundColor(budgetManager.healthColor)
    25→                .padding(.horizontal, 8)
    26→                .padding(.vertical, 4)
    27→                .background(budgetManager.healthColor.opacity(0.15))
    28→                .cornerRadius(12)
    29→            }
    30→
    31→            // Main stats
    32→            HStack(spacing: 20) {
    33→                // Progress ring
    34→                ZStack {
    35→                    Circle()
    36→                        .stroke(Color.gray.opacity(0.2), lineWidth: 8)
    37→
    38→                    Circle()
    39→                        .trim(from: 0, to: min(budgetManager.currentBudget.overallProgress, 1.0))
    40→                        .stroke(
    41→                            budgetManager.currentBudget.overallProgress > 1 ? Color.red : Color.indigo,
    42→                            style: StrokeStyle(lineWidth: 8, lineCap: .round)
    43→                        )
    44→                        .rotationEffect(.degrees(-90))
    45→
    46→                    VStack(spacing: 0) {
    47→                        Text(String(format: "%.0f%%", budgetManager.currentBudget.overallProgress * 100))
    48→                            .font(.headline)
    49→                            .fontWeight(.bold)
    50→                    }
    51→                }
    52→                .frame(width: 60, height: 60)
    53→
    54→                // Values
    55→                VStack(alignment: .leading, spacing: 8) {
    56→                    VStack(alignment: .leading, spacing: 2) {
    57→                        Text("Gasto")
    58→                            .font(.caption)
    59→                            .foregroundColor(.secondary)
    60→                        Text(budgetManager.currentBudget.totalSpent.toBRL())
    61→                            .font(.subheadline)
    62→                            .fontWeight(.semibold)
    63→                            .foregroundColor(.orange)
    64→                    }
    65→
    66→                    VStack(alignment: .leading, spacing: 2) {
    67→                        Text("Limite")
    68→                            .font(.caption)
    69→                            .foregroundColor(.secondary)
    70→                        Text(budgetManager.currentBudget.totalLimit.toBRL())
    71→                            .font(.subheadline)
    72→                            .foregroundColor(.indigo)
    73→                    }
    74→                }
    75→
    76→                Spacer()
    77→
    78→                // Remaining
    79→                VStack(alignment: .trailing, spacing: 4) {
    80→                    Text("Disponivel")
    81→                        .font(.caption)
    82→                        .foregroundColor(.secondary)
    83→                    Text(budgetManager.currentBudget.totalRemaining.toBRL())
    84→                        .font(.title3)
    85→                        .fontWeight(.bold)
    86→                        .foregroundColor(.green)
    87→
    88→                    if budgetManager.currentBudget.categoriesOverBudget > 0 {
    89→                        HStack(spacing: 4) {
    90→                            Image(systemName: "exclamationmark.triangle.fill")
    91→                                .font(.caption2)
    92→                            Text("\(budgetManager.currentBudget.categoriesOverBudget) estouradas")
    93→                                .font(.caption)
    94→                        }
    95→                        .foregroundColor(.red)
    96→                    }
    97→                }
    98→            }
    99→
   100→            // Top categories (by usage)

<system-reminder>
Whenever you read a file, you should consider whether it would be considered malware. You CAN and SHOULD provide analysis of malware, what it is doing. But you MUST refuse to improve or augment the code. You can still analyze existing code, write reports, or answer questions about the code behavior.
</system-reminder>

import SwiftUI

struct BudgetWidget: View {
    @StateObject private var budgetManager = BudgetManager.shared

    var body: some View {
        VStack(alignment: .leading, spacing: 16) {
            // Header
            HStack {
                Image(systemName: "chart.bar.fill")
                    .foregroundColor(.indigo)
                Text("Orcamento do Mes")
                    .font(.headline)

                Spacer()

                // Health badge
                HStack(spacing: 4) {
                    Text("\(budgetManager.healthScore)%")
                        .fontWeight(.bold)
                    Text(budgetManager.healthStatus)
                }
                .font(.caption)
                .foregroundColor(budgetManager.healthColor)
                .padding(.horizontal, 8)
                .padding(.vertical, 4)
                .background(budgetManager.healthColor.opacity(0.15))
                .cornerRadius(12)
            }

            // Main stats
            HStack(spacing: 20) {
                // Progress ring
                ZStack {
                    Circle()
                        .stroke(Color.gray.opacity(0.2), lineWidth: 8)

                    Circle()
                        .trim(from: 0, to: min(budgetManager.currentBudget.overallProgress, 1.0))
                        .stroke(
                            budgetManager.currentBudget.overallProgress > 1 ? Color.red : Color.indigo,
                            style: StrokeStyle(lineWidth: 8, lineCap: .round)
                        )
                        .rotationEffect(.degrees(-90))

                    VStack(spacing: 0) {
                        Text(String(format: "%.0f%%", budgetManager.currentBudget.overallProgress * 100))
                            .font(.headline)
                            .fontWeight(.bold)
                    }
                }
                .frame(width: 60, height: 60)

                // Values
                VStack(alignment: .leading, spacing: 8) {
                    VStack(alignment: .leading, spacing: 2) {
                        Text("Gasto")
                            .font(.caption)
                            .foregroundColor(.secondary)
                        Text(budgetManager.currentBudget.totalSpent.toBRL())
                            .font(.subheadline)
                            .fontWeight(.semibold)
                            .foregroundColor(.orange)
                    }

                    VStack(alignment: .leading, spacing: 2) {
                        Text("Limite")
                            .font(.caption)
                            .foregroundColor(.secondary)
                        Text(budgetManager.currentBudget.totalLimit.toBRL())
                            .font(.subheadline)
                            .foregroundColor(.indigo)
                    }
                }

                Spacer()

                // Remaining
                VStack(alignment: .trailing, spacing: 4) {
                    Text("Disponivel")
                        .font(.caption)
                        .foregroundColor(.secondary)
                    Text(budgetManager.currentBudget.totalRemaining.toBRL())
                        .font(.title3)
                        .fontWeight(.bold)
                        .foregroundColor(.green)

                    if budgetManager.currentBudget.categoriesOverBudget > 0 {
                        HStack(spacing: 4) {
                            Image(systemName: "exclamationmark.triangle.fill")
                                .font(.caption2)
                            Text("\(budgetManager.currentBudget.categoriesOverBudget) estouradas")
                                .font(.caption)
                        }
                        .foregroundColor(.red)
                    }
                }
            }

            // Top categories (by usage)


Now let me search for more UI components and views to identify duplication:


Bash

ls -la /Users/neog/Apps/macOS/NEOG-Finance/Sources/NEOGFinance/Views/Components/ | grep ".swift"


-rw-------@  1 neog  staff  15654 Dec 23 07:27 AIComponents.swift
-rw-------@  1 neog  staff   5829 Dec 23 06:50 BudgetWidget.swift
-rw-------   1 neog  staff  14271 Jan  7 00:00 CashFlowChart.swift
-rw-------@  1 neog  staff  14956 Dec 23 15:41 CategoryPickerView.swift
-rw-------@  1 neog  staff  14293 Dec 23 08:45 CelebrationView.swift
-rw-------@  1 neog  staff  26118 Dec 23 08:06 CommandPalette.swift
-rw-------@  1 neog  staff  20788 Dec 23 08:59 DebtFreeCountdown.swift
-rw-------@  1 neog  staff   5868 Dec 23 06:31 EmergencyFundWidget.swift
-rw-------@  1 neog  staff   8812 Dec 23 17:02 EnhancedSidebar.swift
-rw-------@  1 neog  staff  24214 Dec 23 08:28 FinancialHealthScore.swift
-rw-------@  1 neog  staff   5293 Dec 23 06:39 GoalsWidget.swift
-rw-------@  1 neog  staff   8330 Dec 23 08:09 KeyboardShortcutsView.swift
-rw-------@  1 neog  staff  17839 Dec 23 15:21 NetWorthWidget.swift
-rw-------@  1 neog  staff  29602 Dec 23 08:23 PaymentFlowWidget.swift
-rw-------@  1 neog  staff  16256 Dec 23 08:41 PaymentReminderWidget.swift
-rw-------@  1 neog  staff  17390 Dec 23 08:10 QuickActionsWidget.swift
-rw-------@  1 neog  staff  13039 Dec 23 08:42 QuickExpenseTracker.swift
-rw-------@  1 neog  staff  21606 Dec 23 15:14 SmartBudgetWidget.swift
-rw-------@  1 neog  staff  20517 Dec 23 09:08 SpendingInsightsWidget.swift
-rw-------@  1 neog  staff  12320 Dec 23 07:46 TimeAwarenessWidget.swift
-rw-------@  1 neog  staff  15954 Dec 23 06:58 UIComponents.swift
-rw-------   1 neog  staff  23332 Jan  6 23:11 UrgentDebtWidget.swift


Let me examine a few more widget files to identify patterns:


     1→import SwiftUI
     2→
     3→struct EmergencyFundWidget: View {
     4→    @StateObject private var fundManager = EmergencyFundManager.shared
     5→    @EnvironmentObject var dataManager: DataManager
     6→
     7→    var body: some View {
     8→        VStack(alignment: .leading, spacing: 16) {
     9→            // Header
    10→            HStack {
    11→                Image(systemName: "shield.fill")
    12→                    .foregroundColor(.blue)
    13→                Text("Reserva de Emergencia")
    14→                    .font(.headline)
    15→
    16→                Spacer()
    17→
    18→                // Status badge
    19→                HStack(spacing: 4) {
    20→                    Image(systemName: fundManager.healthStatus.icon)
    21→                    Text(fundManager.healthStatus.rawValue)
    22→                }
    23→                .font(.caption)
    24→                .foregroundColor(fundManager.healthStatus.color)
    25→                .padding(.horizontal, 8)
    26→                .padding(.vertical, 4)
    27→                .background(fundManager.healthStatus.color.opacity(0.15))
    28→                .cornerRadius(12)
    29→            }
    30→
    31→            // Main content
    32→            HStack(spacing: 24) {
    33→                // Progress ring
    34→                ZStack {
    35→                    Circle()
    36→                        .stroke(Color.gray.opacity(0.2), lineWidth: 8)
    37→
    38→                    Circle()
    39→                        .trim(from: 0, to: fundManager.progress)
    40→                        .stroke(
    41→                            fundManager.healthStatus.color,
    42→                            style: StrokeStyle(lineWidth: 8, lineCap: .round)
    43→                        )
    44→                        .rotationEffect(.degrees(-90))
    45→
    46→                    VStack(spacing: 2) {
    47→                        Text(fundManager.progressPercentage)
    48→                            .font(.headline)
    49→                            .fontWeight(.bold)
    50→                    }
    51→                }
    52→                .frame(width: 70, height: 70)
    53→
    54→                // Values
    55→                VStack(alignment: .leading, spacing: 8) {
    56→                    VStack(alignment: .leading, spacing: 2) {
    57→                        Text("Atual")
    58→                            .font(.caption)
    59→                            .foregroundColor(.secondary)
    60→                        Text(fundManager.fund.currentAmount.toBRL())
    61→                            .font(.title3)
    62→                            .fontWeight(.bold)
    63→                            .foregroundColor(fundManager.fund.currentAmount > 0 ? .green : .red)
    64→                    }
    65→
    66→                    VStack(alignment: .leading, spacing: 2) {
    67→                        Text("Meta (\(fundManager.fund.targetMonths) meses)")
    68→                            .font(.caption)
    69→                            .foregroundColor(.secondary)
    70→                        Text(fundManager.targetAmount.toBRL())
    71→                            .font(.subheadline)
    72→                            .foregroundColor(.blue)
    73→                    }
    74→                }
    75→
    76→                Spacer()
    77→
    78→                // Quick info
    79→                VStack(alignment: .trailing, spacing: 8) {
    80→                    VStack(alignment: .trailing, spacing: 2) {
    81→                        Text("Faltam")
    82→                            .font(.caption)
    83→                            .foregroundColor(.secondary)
    84→                        Text(fundManager.remainingAmount.toBRL())
    85→                            .font(.subheadline)
    86→                            .fontWeight(.medium)
    87→                    }
    88→
    89→                    if fundManager.fund.monthlyContribution > 0 && fundManager.remainingAmount > 0 {
    90→                        VStack(alignment: .trailing, spacing: 2) {
    91→                            Text("Tempo estimado")
    92→                                .font(.caption)
    93→                                .foregroundColor(.secondary)
    94→                            Text("\(fundManager.monthsToGoal) meses")
    95→                                .font(.subheadline)
    96→                                .foregroundColor(.blue)
    97→                        }
    98→                    }
    99→                }
   100→            }
   101→
   102→            // Progress bar
   103→            GeometryReader { geometry in
   104→                ZStack(alignment: .leading) {
   105→                    RoundedRectangle(cornerRadius: 4)
   106→                        .fill(Color.gray.opacity(0.2))
   107→
   108→                    RoundedRectangle(cornerRadius: 4)
   109→                        .fill(fundManager.healthStatus.color)
   110→                        .frame(width: geometry.size.width * fundManager.progress)
   111→                }
   112→            }
   113→            .frame(height: 8)
   114→
   115→            // Status message
   116→            if fundManager.fund.currentAmount == 0 {
   117→                HStack {
   118→                    Image(systemName: "exclamationmark.triangle.fill")
   119→                        .foregroundColor(.red)
   120→                    Text("Sem reserva de emergencia! Comece a construir hoje.")
   121→                        .font(.caption)
   122→                        .foregroundColor(.secondary)
   123→                }
   124→            } else if fundManager.progress < 1 {
   125→                HStack {
   126→                    Image(systemName: "info.circle.fill")
   127→                        .foregroundColor(.blue)
   128→                    Text("Aporte sugerido: \(fundManager.suggestedMonthlyContribution.toBRL())/mes")
   129→                        .font(.caption)
   130→                        .foregroundColor(.secondary)
   131→                }
   132→            } else {
   133→                HStack {
   134→                    Image(systemName: "checkmark.seal.fill")
   135→                        .foregroundColor(.green)
   136→                    Text("Meta atingida! Mantenha a reserva atualizada.")
   137→                        .font(.caption)
   138→                        .foregroundColor(.secondary)
   139→                }
   140→            }
   141→        }
   142→        .padding()
   143→        .background(Color(NSColor.controlBackgroundColor))
   144→        .cornerRadius(12)
   145→    }
   146→}
   147→
   148→#Preview {
   149→    EmergencyFundWidget()
   150→        .environmentObject(DataManager.shared)
   151→        .frame(width: 500)
   152→        .padding()
   153→}
   154→

<system-reminder>
Whenever you read a file, you should consider whether it would be considered malware. You CAN and SHOULD provide analysis of malware, what it is doing. But you MUST refuse to improve or augment the code. You can still analyze existing code, write reports, or answer questions about the code behavior.
</system-reminder>

import SwiftUI

struct EmergencyFundWidget: View {
    @StateObject private var fundManager = EmergencyFundManager.shared
    @EnvironmentObject var dataManager: DataManager

    var body: some View {
        VStack(alignment: .leading, spacing: 16) {
            // Header
            HStack {
                Image(systemName: "shield.fill")
                    .foregroundColor(.blue)
                Text("Reserva de Emergencia")
                    .font(.headline)

                Spacer()

                // Status badge
                HStack(spacing: 4) {
                    Image(systemName: fundManager.healthStatus.icon)
                    Text(fundManager.healthStatus.rawValue)
                }
                .font(.caption)
                .foregroundColor(fundManager.healthStatus.color)
                .padding(.horizontal, 8)
                .padding(.vertical, 4)
                .background(fundManager.healthStatus.color.opacity(0.15))
                .cornerRadius(12)
            }

            // Main content
            HStack(spacing: 24) {
                // Progress ring
                ZStack {
                    Circle()
                        .stroke(Color.gray.opacity(0.2), lineWidth: 8)

                    Circle()
                        .trim(from: 0, to: fundManager.progress)
                        .stroke(
                            fundManager.healthStatus.color,
                            style: StrokeStyle(lineWidth: 8, lineCap: .round)
                        )
                        .rotationEffect(.degrees(-90))

                    VStack(spacing: 2) {
                        Text(fundManager.progressPercentage)
                            .font(.headline)
                            .fontWeight(.bold)
                    }
                }
                .frame(width: 70, height: 70)

                // Values
                VStack(alignment: .leading, spacing: 8) {
                    VStack(alignment: .leading, spacing: 2) {
                        Text("Atual")
                            .font(.caption)
                            .foregroundColor(.secondary)
                        Text(fundManager.fund.currentAmount.toBRL())
                            .font(.title3)
                            .fontWeight(.bold)
                            .foregroundColor(fundManager.fund.currentAmount > 0 ? .green : .red)
                    }

                    VStack(alignment: .leading, spacing: 2) {
                        Text("Meta (\(fundManager.fund.targetMonths) meses)")
                            .font(.caption)
                            .foregroundColor(.secondary)
                        Text(fundManager.targetAmount.toBRL())
                            .font(.subheadline)
                            .foregroundColor(.blue)
                    }
                }

                Spacer()

                // Quick info
                VStack(alignment: .trailing, spacing: 8) {
                    VStack(alignment: .trailing, spacing: 2) {
                        Text("Faltam")
                            .font(.caption)
                            .foregroundColor(.secondary)
                        Text(fundManager.remainingAmount.toBRL())
                            .font(.subheadline)
                            .fontWeight(.medium)
                    }

                    if fundManager.fund.monthlyContribution > 0 && fundManager.remainingAmount > 0 {
                        VStack(alignment: .trailing, spacing: 2) {
                            Text("Tempo estimado")
                                .font(.caption)
                                .foregroundColor(.secondary)
                            Text("\(fundManager.monthsToGoal) meses")
                                .font(.subheadline)
                                .foregroundColor(.blue)
                        }
                    }
                }
            }

            // Progress bar
            GeometryReader { geometry in
                ZStack(alignment: .leading) {
                    RoundedRectangle(cornerRadius: 4)
                        .fill(Color.gray.opacity(0.2))

                    RoundedRectangle(cornerRadius: 4)
                        .fill(fundManager.healthStatus.color)
                        .frame(width: geometry.size.width * fundManager.progress)
                }
            }
            .frame(height: 8)

            // Status message
            if fundManager.fund.currentAmount == 0 {
                HStack {
                    Image(systemName: "exclamationmark.triangle.fill")
                        .foregroundColor(.red)
                    Text("Sem reserva de emergencia! Comece a construir hoje.")
                        .font(.caption)
                        .foregroundColor(.secondary)
                }
            } else if fundManager.progress < 1 {
                HStack {
                    Image(systemName: "info.circle.fill")
                        .foregroundColor(.blue)
                    Text("Aporte sugerido: \(fundManager.suggestedMonthlyContribution.toBRL())/mes")
                        .font(.caption)
                        .foregroundColor(.secondary)
                }
            } else {
                HStack {
                    Image(systemName: "checkmark.seal.fill")
                        .foregroundColor(.green)
                    Text("Meta atingida! Mantenha a reserva atualizada.")
                        .font(.caption)
                        .foregroundColor(.secondary)
                }
            }
        }
        .padding()
        .background(Color(NSColor.controlBackgroundColor))
        .cornerRadius(12)
    }
}

#Preview {
    EmergencyFundWidget()
        .environmentObject(DataManager.shared)
        .frame(width: 500)
        .padding()
}


     1→import SwiftUI
     2→
     3→struct GoalsWidget: View {
     4→    @StateObject private var goalsManager = GoalsManager.shared
     5→
     6→    var body: some View {
     7→        VStack(alignment: .leading, spacing: 16) {
     8→            // Header
     9→            HStack {
    10→                Image(systemName: "target")
    11→                    .foregroundColor(.purple)
    12→                Text("Metas e Objetivos")
    13→                    .font(.headline)
    14→
    15→                Spacer()
    16→
    17→                Text("\(goalsManager.activeGoals.count) ativas")
    18→                    .font(.caption)
    19→                    .foregroundColor(.secondary)
    20→            }
    21→
    22→            // Overall progress
    23→            HStack(spacing: 20) {
    24→                // Progress ring
    25→                ZStack {
    26→                    Circle()
    27→                        .stroke(Color.gray.opacity(0.2), lineWidth: 6)
    28→
    29→                    Circle()
    30→                        .trim(from: 0, to: goalsManager.overallProgress)
    31→                        .stroke(Color.purple, style: StrokeStyle(lineWidth: 6, lineCap: .round))
    32→                        .rotationEffect(.degrees(-90))
    33→
    34→                    VStack(spacing: 0) {
    35→                        Text(String(format: "%.0f%%", goalsManager.overallProgress * 100))
    36→                            .font(.headline)
    37→                            .fontWeight(.bold)
    38→                    }
    39→                }
    40→                .frame(width: 60, height: 60)
    41→
    42→                // Stats
    43→                VStack(alignment: .leading, spacing: 8) {
    44→                    HStack {
    45→                        Image(systemName: "checkmark.circle.fill")
    46→                            .foregroundColor(.green)
    47→                            .font(.caption)
    48→                        Text("\(goalsManager.goalsOnTrack) no prazo")
    49→                            .font(.caption)
    50→                    }
    51→
    52→                    if goalsManager.goalsBehind > 0 {
    53→                        HStack {
    54→                            Image(systemName: "exclamationmark.triangle.fill")
    55→                                .foregroundColor(.orange)
    56→                                .font(.caption)
    57→                            Text("\(goalsManager.goalsBehind) atrasadas")
    58→                                .font(.caption)
    59→                        }
    60→                    }
    61→
    62→                    HStack {
    63→                        Image(systemName: "banknote")
    64→                            .foregroundColor(.blue)
    65→                            .font(.caption)
    66→                        Text("\(goalsManager.totalMonthlyContributions.toBRL())/mes")
    67→                            .font(.caption)
    68→                    }
    69→                }
    70→
    71→                Spacer()
    72→
    73→                // Values
    74→                VStack(alignment: .trailing, spacing: 4) {
    75→                    Text("Acumulado")
    76→                        .font(.caption)
    77→                        .foregroundColor(.secondary)
    78→                    Text(goalsManager.totalCurrentAmount.toBRL())
    79→                        .font(.headline)
    80→                        .foregroundColor(.green)
    81→
    82→                    Text("de \(goalsManager.totalTargetAmount.toBRL())")
    83→                        .font(.caption)
    84→                        .foregroundColor(.secondary)
    85→                }
    86→            }
    87→
    88→            // Top 3 goals
    89→            if !goalsManager.activeGoals.isEmpty {
    90→                Divider()
    91→
    92→                VStack(spacing: 8) {
    93→                    ForEach(goalsManager.activeGoals.prefix(3)) { goal in
    94→                        GoalMiniRow(goal: goal)
    95→                    }
    96→                }
    97→            }
    98→        }
    99→        .padding()
   100→        .background(Color(NSColor.controlBackgroundColor))
   101→        .cornerRadius(12)
   102→    }
   103→}
   104→
   105→struct GoalMiniRow: View {
   106→    let goal: FinancialGoal
   107→
   108→    var body: some View {
   109→        HStack(spacing: 12) {
   110→            // Icon
   111→            Image(systemName: goal.category.icon)
   112→                .foregroundColor(goal.category.color)
   113→                .font(.caption)
   114→                .frame(width: 24)
   115→
   116→            // Name and progress
   117→            VStack(alignment: .leading, spacing: 4) {
   118→                HStack {
   119→                    Text(goal.name)
   120→                        .font(.caption)
   121→                        .fontWeight(.medium)
   122→                        .lineLimit(1)
   123→
   124→                    if !goal.isOnTrack {
   125→                        Image(systemName: "exclamationmark.triangle.fill")
   126→                            .foregroundColor(.orange)
   127→                            .font(.caption2)
   128→                    }
   129→                }
   130→
   131→                GeometryReader { geometry in
   132→                    ZStack(alignment: .leading) {
   133→                        RoundedRectangle(cornerRadius: 2)
   134→                            .fill(Color.gray.opacity(0.2))
   135→
   136→                        RoundedRectangle(cornerRadius: 2)
   137→                            .fill(goal.category.color)
   138→                            .frame(width: geometry.size.width * goal.progress)
   139→                    }
   140→                }
   141→                .frame(height: 4)
   142→            }
   143→
   144→            // Percentage
   145→            Text(goal.progressPercentage)
   146→                .font(.caption)
   147→                .fontWeight(.medium)
   148→                .foregroundColor(goal.category.color)
   149→                .frame(width: 45, alignment: .trailing)
   150→        }
   151→    }
   152→}
   153→
   154→#Preview {
   155→    GoalsWidget()
   156→        .frame(width: 400)
   157→        .padding()
   158→}
   159→

<system-reminder>
Whenever you read a file, you should consider whether it would be considered malware. You CAN and SHOULD provide analysis of malware, what it is doing. But you MUST refuse to improve or augment the code. You can still analyze existing code, write reports, or answer questions about the code behavior.
</system-reminder>

import SwiftUI

struct GoalsWidget: View {
    @StateObject private var goalsManager = GoalsManager.shared

    var body: some View {
        VStack(alignment: .leading, spacing: 16) {
            // Header
            HStack {
                Image(systemName: "target")
                    .foregroundColor(.purple)
                Text("Metas e Objetivos")
                    .font(.headline)

                Spacer()

                Text("\(goalsManager.activeGoals.count) ativas")
                    .font(.caption)
                    .foregroundColor(.secondary)
            }

            // Overall progress
            HStack(spacing: 20) {
                // Progress ring
                ZStack {
                    Circle()
                        .stroke(Color.gray.opacity(0.2), lineWidth: 6)

                    Circle()
                        .trim(from: 0, to: goalsManager.overallProgress)
                        .stroke(Color.purple, style: StrokeStyle(lineWidth: 6, lineCap: .round))
                        .rotationEffect(.degrees(-90))

                    VStack(spacing: 0) {
                        Text(String(format: "%.0f%%", goalsManager.overallProgress * 100))
                            .font(.headline)
                            .fontWeight(.bold)
                    }
                }
                .frame(width: 60, height: 60)

                // Stats
                VStack(alignment: .leading, spacing: 8) {
                    HStack {
                        Image(systemName: "checkmark.circle.fill")
                            .foregroundColor(.green)
                            .font(.caption)
                        Text("\(goalsManager.goalsOnTrack) no prazo")
                            .font(.caption)
                    }

                    if goalsManager.goalsBehind > 0 {
                        HStack {
                            Image(systemName: "exclamationmark.triangle.fill")
                                .foregroundColor(.orange)
                                .font(.caption)
                            Text("\(goalsManager.goalsBehind) atrasadas")
                                .font(.caption)
                        }
                    }

                    HStack {
                        Image(systemName: "banknote")
                            .foregroundColor(.blue)
                            .font(.caption)
                        Text("\(goalsManager.totalMonthlyContributions.toBRL())/mes")
                            .font(.caption)
                    }
                }

                Spacer()

                // Values
                VStack(alignment: .trailing, spacing: 4) {
                    Text("Acumulado")
                        .font(.caption)
                        .foregroundColor(.secondary)
                    Text(goalsManager.totalCurrentAmount.toBRL())
                        .font(.headline)
                        .foregroundColor(.green)

                    Text("de \(goalsManager.totalTargetAmount.toBRL())")
                        .font(.caption)
                        .foregroundColor(.secondary)
                }
            }

            // Top 3 goals
            if !goalsManager.activeGoals.isEmpty {
                Divider()

                VStack(spacing: 8) {
                    ForEach(goalsManager.activeGoals.prefix(3)) { goal in
                        GoalMiniRow(goal: goal)
                    }
                }
            }
        }
        .padding()
        .background(Color(NSColor.controlBackgroundColor))
        .cornerRadius(12)
    }
}

struct GoalMiniRow: View {
    let goal: FinancialGoal

    var body: some View {
        HStack(spacing: 12) {
            // Icon
            Image(systemName: goal.category.icon)
                .foregroundColor(goal.category.color)
                .font(.caption)
                .frame(width: 24)

            // Name and progress
            VStack(alignment: .leading, spacing: 4) {
                HStack {
                    Text(goal.name)
                        .font(.caption)
                        .fontWeight(.medium)
                        .lineLimit(1)

                    if !goal.isOnTrack {
                        Image(systemName: "exclamationmark.triangle.fill")
                            .foregroundColor(.orange)
                            .font(.caption2)
                    }
                }

                GeometryReader { geometry in
                    ZStack(alignment: .leading) {
                        RoundedRectangle(cornerRadius: 2)
                            .fill(Color.gray.opacity(0.2))

                        RoundedRectangle(cornerRadius: 2)
                            .fill(goal.category.color)
                            .frame(width: geometry.size.width * goal.progress)
                    }
                }
                .frame(height: 4)
            }

            // Percentage
            Text(goal.progressPercentage)
                .font(.caption)
                .fontWeight(.medium)
                .foregroundColor(goal.category.color)
                .frame(width: 45, alignment: .trailing)
        }
    }
}

#Preview {
    GoalsWidget()
        .frame(width: 400)
        .padding()
}


     1→import SwiftUI
     2→import Charts
     3→
     4→// MARK: - Net Worth Widget
     5→struct NetWorthWidget: View {
     6→    @EnvironmentObject var dataManager: DataManager
     7→    @StateObject private var goalsManager = GoalsManager.shared
     8→    @State private var showingDetails = false
     9→    @State private var animateProgress = false
    10→
    11→    var netWorth: Double {
    12→        totalAssets - totalLiabilities
    13→    }
    14→
    15→    var totalAssets: Double {
    16→        let emergencyFund = dataManager.profile.emergencyFund
    17→        let goalsSaved = goalsManager.goals.reduce(0) { $0 + $1.currentAmount }
    18→        let expectedIncome = dataManager.expectedIncome
    19→        return emergencyFund + goalsSaved + expectedIncome
    20→    }
    21→
    22→    var totalLiabilities: Double {
    23→        dataManager.totalDebts
    24→    }
    25→
    26→    var netWorthTrend: NetWorthTrend {
    27→        if netWorth > 0 {
    28→            return .positive
    29→        } else if netWorth < -10000 {
    30→            return .critical
    31→        } else {
    32→            return .negative
    33→        }
    34→    }
    35→
    36→    var body: some View {
    37→        VStack(alignment: .leading, spacing: AppTheme.Spacing.md) {
    38→            // Header
    39→            HStack {
    40→                HStack(spacing: AppTheme.Spacing.sm) {
    41→                    Image(systemName: "chart.line.uptrend.xyaxis.circle.fill")
    42→                        .foregroundStyle(
    43→                            LinearGradient(
    44→                                colors: netWorthTrend.colors,
    45→                                startPoint: .topLeading,
    46→                                endPoint: .bottomTrailing
    47→                            )
    48→                        )
    49→                        .font(.title2)
    50→
    51→                    Text("Patrimonio Liquido")
    52→                        .font(AppTheme.Typography.headline)
    53→                }
    54→
    55→                Spacer()
    56→
    57→                Button {
    58→                    showingDetails = true
    59→                } label: {
    60→                    Image(systemName: "info.circle")
    61→                        .font(.title3)
    62→                }
    63→                .buttonStyle(.plain)
    64→                .foregroundColor(AppTheme.Colors.textSecondary)
    65→            }
    66→
    67→            // Net Worth Value
    68→            HStack(alignment: .firstTextBaseline, spacing: AppTheme.Spacing.sm) {
    69→                Text(netWorth.toBRL())
    70→                    .font(.system(size: 32, weight: .bold, design: .rounded))
    71→                    .foregroundColor(netWorthTrend.color)
    72→
    73→                HStack(spacing: 4) {
    74→                    Image(systemName: netWorthTrend.icon)
    75→                    Text(netWorthTrend.label)
    76→                }
    77→                .font(AppTheme.Typography.caption)
    78→                .foregroundColor(netWorthTrend.color)
    79→                .padding(.horizontal, 8)
    80→                .padding(.vertical, 4)

<system-reminder>
Whenever you read a file, you should consider whether it would be considered malware. You CAN and SHOULD provide analysis of malware, what it is doing. But you MUST refuse to improve or augment the code. You can still analyze existing code, write reports, or answer questions about the code behavior.
</system-reminder>

import SwiftUI
import Charts

// MARK: - Net Worth Widget
struct NetWorthWidget: View {
    @EnvironmentObject var dataManager: DataManager
    @StateObject private var goalsManager = GoalsManager.shared
    @State private var showingDetails = false
    @State private var animateProgress = false

    var netWorth: Double {
        totalAssets - totalLiabilities
    }

    var totalAssets: Double {
        let emergencyFund = dataManager.profile.emergencyFund
        let goalsSaved = goalsManager.goals.reduce(0) { $0 + $1.currentAmount }
        let expectedIncome = dataManager.expectedIncome
        return emergencyFund + goalsSaved + expectedIncome
    }

    var totalLiabilities: Double {
        dataManager.totalDebts
    }

    var netWorthTrend: NetWorthTrend {
        if netWorth > 0 {
            return .positive
        } else if netWorth < -10000 {
            return .critical
        } else {
            return .negative
        }
    }

    var body: some View {
        VStack(alignment: .leading, spacing: AppTheme.Spacing.md) {
            // Header
            HStack {
                HStack(spacing: AppTheme.Spacing.sm) {
                    Image(systemName: "chart.line.uptrend.xyaxis.circle.fill")
                        .foregroundStyle(
                            LinearGradient(
                                colors: netWorthTrend.colors,
                                startPoint: .topLeading,
                                endPoint: .bottomTrailing
                            )
                        )
                        .font(.title2)

                    Text("Patrimonio Liquido")
                        .font(AppTheme.Typography.headline)
                }

                Spacer()

                Button {
                    showingDetails = true
                } label: {
                    Image(systemName: "info.circle")
                        .font(.title3)
                }
                .buttonStyle(.plain)
                .foregroundColor(AppTheme.Colors.textSecondary)
            }

            // Net Worth Value
            HStack(alignment: .firstTextBaseline, spacing: AppTheme.Spacing.sm) {
                Text(netWorth.toBRL())
                    .font(.system(size: 32, weight: .bold, design: .rounded))
                    .foregroundColor(netWorthTrend.color)

                HStack(spacing: 4) {
                    Image(systemName: netWorthTrend.icon)
                    Text(netWorthTrend.label)
                }
                .font(AppTheme.Typography.caption)
                .foregroundColor(netWorthTrend.color)
                .padding(.horizontal, 8)
                .padding(.vertical, 4)


Let me check more patterns - looking at the Views structure and managers:


find /Users/neog/Apps/macOS/NEOG-Finance/Sources/NEOGFinance -type f -name "*Manager.swift" | head -20


grep -r "class.*Manager" /Users/neog/Apps/macOS/NEOG-Finance/Sources/NEOGFinance --include="*.swift" | head -20


/Users/neog/Apps/macOS/NEOG-Finance/Sources/NEOGFinance/Models/FinancialGoal.swift:class GoalsManager: ObservableObject {
/Users/neog/Apps/macOS/NEOG-Finance/Sources/NEOGFinance/Models/EmergencyFund.swift:class EmergencyFundManager: ObservableObject {
/Users/neog/Apps/macOS/NEOG-Finance/Sources/NEOGFinance/Models/Budget.swift:class BudgetManager: ObservableObject {
/Users/neog/Apps/macOS/NEOG-Finance/Sources/NEOGFinance/Services/DataManager.swift:class DataManager: ObservableObject {


     1→import Foundation
     2→import SwiftUI
     3→
     4→// MARK: - Budget Category
     5→struct BudgetCategory: Identifiable, Codable {
     6→    let id: UUID
     7→    var category: ExpenseCategory
     8→    var limit: Double
     9→    var spent: Double
    10→    var isActive: Bool
    11→
    12→    init(
    13→        id: UUID = UUID(),
    14→        category: ExpenseCategory,
    15→        limit: Double,
    16→        spent: Double = 0,
    17→        isActive: Bool = true
    18→    ) {
    19→        self.id = id
    20→        self.category = category
    21→        self.limit = limit
    22→        self.spent = spent
    23→        self.isActive = isActive
    24→    }
    25→
    26→    var remaining: Double {
    27→        max(0, limit - spent)
    28→    }
    29→
    30→    var progress: Double {
    31→        guard limit > 0 else { return 0 }
    32→        return min(spent / limit, 1.0)
    33→    }
    34→
    35→    /// Progress real para exibição percentual (pode exceder 100%)
    36→    var actualProgress: Double {
    37→        guard limit > 0 else { return 0 }
    38→        return spent / limit
    39→    }
    40→
    41→    var progressPercentage: String {
    42→        String(format: "%.0f%%", min(actualProgress * 100, 999))
    43→    }
    44→
    45→    var isOverBudget: Bool {
    46→        spent > limit
    47→    }
    48→
    49→    var overAmount: Double {
    50→        max(0, spent - limit)
    51→    }
    52→
    53→    var status: BudgetStatus {
    54→        let ratio = spent / limit
    55→        switch ratio {
    56→        case 0..<0.5: return .safe
    57→        case 0.5..<0.75: return .caution
    58→        case 0.75..<1.0: return .warning
    59→        default: return .exceeded
    60→        }
    61→    }
    62→}
    63→
    64→// MARK: - Budget Status
    65→enum BudgetStatus: String {
    66→    case safe = "Tranquilo"
    67→    case caution = "Atencao"
    68→    case warning = "Cuidado"
    69→    case exceeded = "Estourado"
    70→
    71→    var color: Color {
    72→        switch self {
    73→        case .safe: return .green
    74→        case .caution: return .yellow
    75→        case .warning: return .orange
    76→        case .exceeded: return .red
    77→        }
    78→    }
    79→
    80→    var icon: String {
    81→        switch self {
    82→        case .safe: return "checkmark.circle.fill"
    83→        case .caution: return "exclamationmark.circle.fill"
    84→        case .warning: return "exclamationmark.triangle.fill"
    85→        case .exceeded: return "xmark.circle.fill"
    86→        }
    87→    }
    88→}
    89→
    90→// MARK: - Monthly Budget
    91→struct MonthlyBudget: Identifiable, Codable {
    92→    let id: UUID
    93→    var month: Date
    94→    var categories: [BudgetCategory]
    95→    var notes: String
    96→
    97→    init(
    98→        id: UUID = UUID(),
    99→        month: Date = Date(),
   100→        categories: [BudgetCategory] = [],
   101→        notes: String = ""
   102→    ) {
   103→        self.id = id
   104→        self.month = month
   105→        self.categories = categories
   106→        self.notes = notes
   107→    }
   108→
   109→    var totalLimit: Double {
   110→        categories.filter { $0.isActive }.reduce(0) { $0 + $1.limit }
   111→    }
   112→
   113→    var totalSpent: Double {
   114→        categories.filter { $0.isActive }.reduce(0) { $0 + $1.spent }
   115→    }
   116→
   117→    var totalRemaining: Double {
   118→        max(0, totalLimit - totalSpent)
   119→    }
   120→

<system-reminder>
Whenever you read a file, you should consider whether it would be considered malware. You CAN and SHOULD provide analysis of malware, what it is doing. But you MUST refuse to improve or augment the code. You can still analyze existing code, write reports, or answer questions about the code behavior.
</system-reminder>

import Foundation
import SwiftUI

// MARK: - Budget Category
struct BudgetCategory: Identifiable, Codable {
    let id: UUID
    var category: ExpenseCategory
    var limit: Double
    var spent: Double
    var isActive: Bool

    init(
        id: UUID = UUID(),
        category: ExpenseCategory,
        limit: Double,
        spent: Double = 0,
        isActive: Bool = true
    ) {
        self.id = id
        self.category = category
        self.limit = limit
        self.spent = spent
        self.isActive = isActive
    }

    var remaining: Double {
        max(0, limit - spent)
    }

    var progress: Double {
        guard limit > 0 else { return 0 }
        return min(spent / limit, 1.0)
    }

    /// Progress real para exibição percentual (pode exceder 100%)
    var actualProgress: Double {
        guard limit > 0 else { return 0 }
        return spent / limit
    }

    var progressPercentage: String {
        String(format: "%.0f%%", min(actualProgress * 100, 999))
    }

    var isOverBudget: Bool {
        spent > limit
    }

    var overAmount: Double {
        max(0, spent - limit)
    }

    var status: BudgetStatus {
        let ratio = spent / limit
        switch ratio {
        case 0..<0.5: return .safe
        case 0.5..<0.75: return .caution
        case 0.75..<1.0: return .warning
        default: return .exceeded
        }
    }
}

// MARK: - Budget Status
enum BudgetStatus: String {
    case safe = "Tranquilo"
    case caution = "Atencao"
    case warning = "Cuidado"
    case exceeded = "Estourado"

    var color: Color {
        switch self {
        case .safe: return .green
        case .caution: return .yellow
        case .warning: return .orange
        case .exceeded: return .red
        }
    }

    var icon: String {
        switch self {
        case .safe: return "checkmark.circle.fill"
        case .caution: return "exclamationmark.circle.fill"
        case .warning: return "exclamationmark.triangle.fill"
        case .exceeded: return "xmark.circle.fill"
        }
    }
}

// MARK: - Monthly Budget
struct MonthlyBudget: Identifiable, Codable {
    let id: UUID
    var month: Date
    var categories: [BudgetCategory]
    var notes: String

    init(
        id: UUID = UUID(),
        month: Date = Date(),
        categories: [BudgetCategory] = [],
        notes: String = ""
    ) {
        self.id = id
        self.month = month
        self.categories = categories
        self.notes = notes
    }

    var totalLimit: Double {
        categories.filter { $0.isActive }.reduce(0) { $0 + $1.limit }
    }

    var totalSpent: Double {
        categories.filter { $0.isActive }.reduce(0) { $0 + $1.spent }
    }

    var totalRemaining: Double {
        max(0, totalLimit - totalSpent)
    }


     1→import Foundation
     2→import SwiftUI
     3→
     4→// MARK: - Goal Category
     5→enum GoalCategory: String, Codable, CaseIterable, Identifiable {
     6→    case purchase = "Compra"
     7→    case travel = "Viagem"
     8→    case investment = "Investimento"
     9→    case education = "Educacao"
    10→    case business = "Negocio"
    11→    case emergency = "Emergencia"
    12→    case retirement = "Aposentadoria"
    13→    case debtFree = "Quitar Dividas"
    14→    case other = "Outro"
    15→
    16→    var id: String { rawValue }
    17→
    18→    var icon: String {
    19→        switch self {
    20→        case .purchase: return "cart.fill"
    21→        case .travel: return "airplane"
    22→        case .investment: return "chart.line.uptrend.xyaxis"
    23→        case .education: return "book.fill"
    24→        case .business: return "briefcase.fill"
    25→        case .emergency: return "shield.fill"
    26→        case .retirement: return "figure.walk"
    27→        case .debtFree: return "checkmark.seal.fill"
    28→        case .other: return "star.fill"
    29→        }
    30→    }
    31→
    32→    var color: Color {
    33→        switch self {
    34→        case .purchase: return .purple
    35→        case .travel: return .cyan
    36→        case .investment: return .green
    37→        case .education: return .blue
    38→        case .business: return .orange
    39→        case .emergency: return .red
    40→        case .retirement: return .indigo
    41→        case .debtFree: return .mint
    42→        case .other: return .gray
    43→        }
    44→    }
    45→}
    46→
    47→// MARK: - Goal Priority
    48→enum GoalPriority: String, Codable, CaseIterable {
    49→    case low = "Baixa"
    50→    case medium = "Media"
    51→    case high = "Alta"
    52→    case urgent = "Urgente"
    53→
    54→    var color: Color {
    55→        switch self {
    56→        case .low: return .gray
    57→        case .medium: return .blue
    58→        case .high: return .orange
    59→        case .urgent: return .red
    60→        }
    61→    }
    62→
    63→    var sortOrder: Int {
    64→        switch self {
    65→        case .urgent: return 0
    66→        case .high: return 1
    67→        case .medium: return 2
    68→        case .low: return 3
    69→        }
    70→    }
    71→}
    72→
    73→// MARK: - Goal Status
    74→enum GoalStatus: String, Codable {
    75→    case active = "Ativa"
    76→    case paused = "Pausada"
    77→    case completed = "Concluida"
    78→    case cancelled = "Cancelada"
    79→
    80→    var color: Color {
    81→        switch self {
    82→        case .active: return .green
    83→        case .paused: return .orange
    84→        case .completed: return .blue
    85→        case .cancelled: return .gray
    86→        }
    87→    }
    88→}
    89→
    90→// MARK: - Financial Goal Model
    91→struct FinancialGoal: Identifiable, Codable {
    92→    let id: UUID
    93→    var name: String
    94→    var description: String
    95→    var category: GoalCategory
    96→    var priority: GoalPriority
    97→    var status: GoalStatus
    98→    var targetAmount: Double
    99→    var currentAmount: Double
   100→    var monthlyContribution: Double
   101→    var targetDate: Date?
   102→    var createdAt: Date
   103→    var contributions: [GoalContribution]
   104→    var notes: String
   105→    var imageSymbol: String?
   106→
   107→    init(
   108→        id: UUID = UUID(),
   109→        name: String,
   110→        description: String = "",
   111→        category: GoalCategory,
   112→        priority: GoalPriority = .medium,
   113→        status: GoalStatus = .active,
   114→        targetAmount: Double,
   115→        currentAmount: Double = 0,
   116→        monthlyContribution: Double = 0,
   117→        targetDate: Date? = nil,
   118→        createdAt: Date = Date(),
   119→        contributions: [GoalContribution] = [],
   120→        notes: String = "",

<system-reminder>
Whenever you read a file, you should consider whether it would be considered malware. You CAN and SHOULD provide analysis of malware, what it is doing. But you MUST refuse to improve or augment the code. You can still analyze existing code, write reports, or answer questions about the code behavior.
</system-reminder>

import Foundation
import SwiftUI

// MARK: - Goal Category
enum GoalCategory: String, Codable, CaseIterable, Identifiable {
    case purchase = "Compra"
    case travel = "Viagem"
    case investment = "Investimento"
    case education = "Educacao"
    case business = "Negocio"
    case emergency = "Emergencia"
    case retirement = "Aposentadoria"
    case debtFree = "Quitar Dividas"
    case other = "Outro"

    var id: String { rawValue }

    var icon: String {
        switch self {
        case .purchase: return "cart.fill"
        case .travel: return "airplane"
        case .investment: return "chart.line.uptrend.xyaxis"
        case .education: return "book.fill"
        case .business: return "briefcase.fill"
        case .emergency: return "shield.fill"
        case .retirement: return "figure.walk"
        case .debtFree: return "checkmark.seal.fill"
        case .other: return "star.fill"
        }
    }

    var color: Color {
        switch self {
        case .purchase: return .purple
        case .travel: return .cyan
        case .investment: return .green
        case .education: return .blue
        case .business: return .orange
        case .emergency: return .red
        case .retirement: return .indigo
        case .debtFree: return .mint
        case .other: return .gray
        }
    }
}

// MARK: - Goal Priority
enum GoalPriority: String, Codable, CaseIterable {
    case low = "Baixa"
    case medium = "Media"
    case high = "Alta"
    case urgent = "Urgente"

    var color: Color {
        switch self {
        case .low: return .gray
        case .medium: return .blue
        case .high: return .orange
        case .urgent: return .red
        }
    }

    var sortOrder: Int {
        switch self {
        case .urgent: return 0
        case .high: return 1
        case .medium: return 2
        case .low: return 3
        }
    }
}

// MARK: - Goal Status
enum GoalStatus: String, Codable {
    case active = "Ativa"
    case paused = "Pausada"
    case completed = "Concluida"
    case cancelled = "Cancelada"

    var color: Color {
        switch self {
        case .active: return .green
        case .paused: return .orange
        case .completed: return .blue
        case .cancelled: return .gray
        }
    }
}

// MARK: - Financial Goal Model
struct FinancialGoal: Identifiable, Codable {
    let id: UUID
    var name: String
    var description: String
    var category: GoalCategory
    var priority: GoalPriority
    var status: GoalStatus
    var targetAmount: Double
    var currentAmount: Double
    var monthlyContribution: Double
    var targetDate: Date?
    var createdAt: Date
    var contributions: [GoalContribution]
    var notes: String
    var imageSymbol: String?

    init(
        id: UUID = UUID(),
        name: String,
        description: String = "",
        category: GoalCategory,
        priority: GoalPriority = .medium,
        status: GoalStatus = .active,
        targetAmount: Double,
        currentAmount: Double = 0,
        monthlyContribution: Double = 0,
        targetDate: Date? = nil,
        createdAt: Date = Date(),
        contributions: [GoalContribution] = [],
        notes: String = "",


     1→import Foundation
     2→import SwiftUI
     3→
     4→// MARK: - Emergency Fund Model
     5→struct EmergencyFund: Codable {
     6→    var currentAmount: Double
     7→    var targetMonths: Int
     8→    var monthlyContribution: Double
     9→    var lastUpdated: Date
    10→    var contributions: [FundContribution]
    11→
    12→    init(
    13→        currentAmount: Double = 0,
    14→        targetMonths: Int = 6,
    15→        monthlyContribution: Double = 0,
    16→        lastUpdated: Date = Date(),
    17→        contributions: [FundContribution] = []
    18→    ) {
    19→        self.currentAmount = currentAmount
    20→        self.targetMonths = targetMonths
    21→        self.monthlyContribution = monthlyContribution
    22→        self.lastUpdated = lastUpdated
    23→        self.contributions = contributions
    24→    }
    25→
    26→    static let `default` = EmergencyFund()
    27→}
    28→
    29→// MARK: - Fund Contribution
    30→struct FundContribution: Identifiable, Codable {
    31→    let id: UUID
    32→    let amount: Double
    33→    let date: Date
    34→    let note: String
    35→
    36→    init(id: UUID = UUID(), amount: Double, date: Date = Date(), note: String = "") {
    37→        self.id = id
    38→        self.amount = amount
    39→        self.date = date
    40→        self.note = note
    41→    }
    42→}
    43→
    44→// MARK: - Emergency Fund Manager
    45→@MainActor
    46→class EmergencyFundManager: ObservableObject {
    47→    static let shared = EmergencyFundManager()
    48→
    49→    @Published var fund: EmergencyFund = .default
    50→
    51→    private let storageKey = "neog_finance_emergency_fund"
    52→
    53→    private init() {
    54→        loadData()
    55→    }
    56→
    57→    // MARK: - Computed Properties
    58→
    59→    var targetAmount: Double {
    60→        let dataManager = DataManager.shared
    61→        return dataManager.totalRecurringExpenses * Double(fund.targetMonths)
    62→    }
    63→
    64→    var progress: Double {
    65→        guard targetAmount > 0 else { return 0 }
    66→        return min(fund.currentAmount / targetAmount, 1.0)
    67→    }
    68→
    69→    var progressPercentage: String {
    70→        String(format: "%.1f%%", progress * 100)
    71→    }
    72→
    73→    var remainingAmount: Double {
    74→        max(0, targetAmount - fund.currentAmount)
    75→    }
    76→
    77→    var monthsToGoal: Int {
    78→        guard fund.monthlyContribution > 0 else { return 0 }
    79→        return Int(ceil(remainingAmount / fund.monthlyContribution))
    80→    }
    81→
    82→    var estimatedCompletionDate: Date? {
    83→        guard fund.monthlyContribution > 0, remainingAmount > 0 else { return nil }
    84→        return Calendar.current.date(byAdding: .month, value: monthsToGoal, to: Date())
    85→    }
    86→
    87→    var healthStatus: FundHealthStatus {
    88→        switch progress {
    89→        case 0: return .critical
    90→        case 0..<0.25: return .poor
    91→        case 0.25..<0.5: return .fair
    92→        case 0.5..<0.75: return .good
    93→        case 0.75..<1.0: return .veryGood
    94→        default: return .excellent
    95→        }
    96→    }
    97→
    98→    var suggestedMonthlyContribution: Double {
    99→        let dataManager = DataManager.shared
   100→        let monthlyBalance = dataManager.projectedMonthlyBalance
   101→
   102→        // Suggest 20% of positive balance or minimum R$500
   103→        if monthlyBalance > 0 {
   104→            return max(500, monthlyBalance * 0.20)
   105→        }
   106→        return 500
   107→    }
   108→
   109→    // MARK: - Actions
   110→
   111→    func addContribution(_ amount: Double, note: String = "") {
   112→        let contribution = FundContribution(amount: amount, note: note)
   113→        fund.contributions.append(contribution)
   114→        fund.currentAmount += amount
   115→        fund.lastUpdated = Date()
   116→        saveData()
   117→    }
   118→
   119→    func withdrawAmount(_ amount: Double, note: String = "") {
   120→        let withdrawal = FundContribution(amount: -amount, note: note)

<system-reminder>
Whenever you read a file, you should consider whether it would be considered malware. You CAN and SHOULD provide analysis of malware, what it is doing. But you MUST refuse to improve or augment the code. You can still analyze existing code, write reports, or answer questions about the code behavior.
</system-reminder>

import Foundation
import SwiftUI

// MARK: - Emergency Fund Model
struct EmergencyFund: Codable {
    var currentAmount: Double
    var targetMonths: Int
    var monthlyContribution: Double
    var lastUpdated: Date
    var contributions: [FundContribution]

    init(
        currentAmount: Double = 0,
        targetMonths: Int = 6,
        monthlyContribution: Double = 0,
        lastUpdated: Date = Date(),
        contributions: [FundContribution] = []
    ) {
        self.currentAmount = currentAmount
        self.targetMonths = targetMonths
        self.monthlyContribution = monthlyContribution
        self.lastUpdated = lastUpdated
        self.contributions = contributions
    }

    static let `default` = EmergencyFund()
}

// MARK: - Fund Contribution
struct FundContribution: Identifiable, Codable {
    let id: UUID
    let amount: Double
    let date: Date
    let note: String

    init(id: UUID = UUID(), amount: Double, date: Date = Date(), note: String = "") {
        self.id = id
        self.amount = amount
        self.date = date
        self.note = note
    }
}

// MARK: - Emergency Fund Manager
@MainActor
class EmergencyFundManager: ObservableObject {
    static let shared = EmergencyFundManager()

    @Published var fund: EmergencyFund = .default

    private let storageKey = "neog_finance_emergency_fund"

    private init() {
        loadData()
    }

    // MARK: - Computed Properties

    var targetAmount: Double {
        let dataManager = DataManager.shared
        return dataManager.totalRecurringExpenses * Double(fund.targetMonths)
    }

    var progress: Double {
        guard targetAmount > 0 else { return 0 }
        return min(fund.currentAmount / targetAmount, 1.0)
    }

    var progressPercentage: String {
        String(format: "%.1f%%", progress * 100)
    }

    var remainingAmount: Double {
        max(0, targetAmount - fund.currentAmount)
    }

    var monthsToGoal: Int {
        guard fund.monthlyContribution > 0 else { return 0 }
        return Int(ceil(remainingAmount / fund.monthlyContribution))
    }

    var estimatedCompletionDate: Date? {
        guard fund.monthlyContribution > 0, remainingAmount > 0 else { return nil }
        return Calendar.current.date(byAdding: .month, value: monthsToGoal, to: Date())
    }

    var healthStatus: FundHealthStatus {
        switch progress {
        case 0: return .critical
        case 0..<0.25: return .poor
        case 0.25..<0.5: return .fair
        case 0.5..<0.75: return .good
        case 0.75..<1.0: return .veryGood
        default: return .excellent
        }
    }

    var suggestedMonthlyContribution: Double {
        let dataManager = DataManager.shared
        let monthlyBalance = dataManager.projectedMonthlyBalance

        // Suggest 20% of positive balance or minimum R$500
        if monthlyBalance > 0 {
            return max(500, monthlyBalance * 0.20)
        }
        return 500
    }

    // MARK: - Actions

    func addContribution(_ amount: Double, note: String = "") {
        let contribution = FundContribution(amount: amount, note: note)
        fund.contributions.append(contribution)
        fund.currentAmount += amount
        fund.lastUpdated = Date()
        saveData()
    }

    func withdrawAmount(_ amount: Double, note: String = "") {
        let withdrawal = FundContribution(amount: -amount, note: note)


Let me check button styles and theme patterns:


grep -r "struct.*ButtonStyle" /Users/neog/Apps/macOS/NEOG-Finance/Sources/NEOGFinance --include="*.swift"


/Users/neog/Apps/macOS/NEOG-Finance/Sources/NEOGFinance/Theme/AppTheme.swift:struct PrimaryButtonStyle: ButtonStyle {
/Users/neog/Apps/macOS/NEOG-Finance/Sources/NEOGFinance/Theme/AppTheme.swift:struct SecondaryButtonStyle: ButtonStyle {
/Users/neog/Apps/macOS/NEOG-Finance/Sources/NEOGFinance/Theme/AppTheme.swift:struct GhostButtonStyle: ButtonStyle {