{"id":43,"date":"2025-07-24T12:27:42","date_gmt":"2025-07-24T12:27:42","guid":{"rendered":"https:\/\/support.webnitix.com\/?page_id=43"},"modified":"2025-07-24T12:27:42","modified_gmt":"2025-07-24T12:27:42","slug":"finances","status":"publish","type":"page","link":"https:\/\/support.webnitix.com\/?page_id=43","title":{"rendered":"Finances"},"content":{"rendered":"\n<div class=\"wp-block-group is-layout-flow wp-block-group-is-layout-flow\">\n<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n    <title>Sole Trader Financial Tracker<\/title>\n    <!-- Tailwind CSS CDN -->\n    <script src=\"https:\/\/cdn.tailwindcss.com\"><\/script>\n    <!-- Google Fonts - Inter -->\n    <link href=\"https:\/\/fonts.googleapis.com\/css2?family=Inter:wght@400;600;700&#038;display=swap\" rel=\"stylesheet\">\n    <!-- React and ReactDOM CDNs -->\n    <script crossorigin src=\"https:\/\/unpkg.com\/react@18\/umd\/react.production.min.js\"><\/script>\n    <script crossorigin src=\"https:\/\/unpkg.com\/react-dom@18\/umd\/react-dom.production.min.js\"><\/script>\n    <!-- Babel CDN for JSX transformation in browser -->\n    <script src=\"https:\/\/unpkg.com\/@babel\/standalone\/babel.min.js\"><\/script>\n\n    <style>\n        body {\n            font-family: 'Inter', sans-serif;\n        }\n        \/* Custom styles for modals to ensure they are centered and visible *\/\n        .modal-overlay {\n            position: fixed;\n            top: 0;\n            left: 0;\n            width: 100%;\n            height: 100%;\n            background-color: rgba(0, 0, 0, 0.5);\n            display: flex;\n            align-items: center;\n            justify-content: center;\n            z-index: 9999; \/* Ensure modal is on top *\/\n        }\n        .modal-content {\n            background-color: white;\n            padding: 1.5rem;\n            border-radius: 0.5rem;\n            box-shadow: 0 10px 15px rgba(0, 0, 0, 0.1);\n            width: 90%;\n            max-width: 28rem; \/* Equivalent to max-w-md *\/\n            z-index: 10000;\n        }\n    <\/style>\n<\/head>\n<body class=\"bg-gray-100\">\n    <div id=\"root\"><\/div> <!-- This is where your React app will be mounted -->\n\n    <script type=\"text\/babel\">\n        \/\/ Main App component for the Sole Trader Financial Tracker\n        function App() {\n            \/\/ Initial annual main job income (used for default and calculations)\n            const initialAnnualMainJobIncome = 28500;\n\n            \/\/ State to store all transactions (one-time and monthly recurring)\n            \/\/ Loads from localStorage or initializes as empty array\n            const [transactions, setTransactions] = React.useState(() => {\n                const savedTransactions = localStorage.getItem('soleTraderTransactions');\n                return savedTransactions ? JSON.parse(savedTransactions) : [];\n            });\n\n            \/\/ State to store monthly main job income, calculated based on changes\n            \/\/ Loads from localStorage or initializes with default annual income divided by 12\n            const [monthlyMainJobIncome, setMonthlyMainJobIncome] = React.useState(() => {\n                const savedMonthlyIncome = localStorage.getItem('soleTraderMonthlyMainJobIncome');\n                if (savedMonthlyIncome) {\n                    return JSON.parse(savedMonthlyIncome);\n                } else {\n                    return Array(12).fill(initialAnnualMainJobIncome \/ 12);\n                }\n            });\n\n            \/\/ State to store calculated annual totals and tax\/NI\n            const [annualSummary, setAnnualSummary] = React.useState({\n                totalBusinessIncome: 0,\n                totalBusinessExpenses: 0,\n                totalBusinessProfit: 0,\n                totalMainJobIncome: 0,\n                totalAnnualIncome: 0,\n                estimatedIncomeTax: 0,\n                estimatedClass4NIC: 0,\n                totalTaxAndNI: 0,\n            });\n\n            \/\/ UK Tax Year 2025\/2026 Assumed Rates (based on 2024\/2025)\n            const personalAllowance = 12570; \/\/ Amount of income before tax\n            const basicRateBandLimit = 50270; \/\/ Upper limit of basic rate band\n            const higherRateBandLimit = 125140; \/\/ Upper limit of higher rate band\n\n            \/\/ Class 4 National Insurance thresholds and rates\n            const class4LowerProfitLimit = 12570; \/\/ Profits below this pay 0% Class 4 NIC\n            const class4UpperProfitLimit = 50270; \/\/ Profits above this pay 2% on the excess\n            const class4Rate1 = 0.06; \/\/ 6% on profits between lower and upper limits\n            const class4Rate2 = 0.02; \/\/ 2% on profits above upper limit\n\n            \/\/ Array of month names for display, starting with UK financial year (April)\n            const monthNames = [\n                'April', 'May', 'June', 'July', 'August', 'September',\n                'October', 'November', 'December', 'January', 'February', 'March'\n            ];\n\n            \/\/ Function to add a new one-time transaction entry for a specific month\n            const addOneTimeTransaction = (type, monthIndex) => {\n                setTransactions(prevTransactions => [\n                    ...prevTransactions,\n                    {\n                        id: Date.now() + Math.random(), \/\/ Unique ID for the transaction\n                        type: type, \/\/ 'income' or 'expense'\n                        description: '',\n                        amount: 0,\n                        frequency: 'one-time', \/\/ Explicitly 'one-time'\n                        monthIndex: monthIndex, \/\/ Specific month for one-time entry\n                        documentRef: '', \/\/ Placeholder for document reference\n                    },\n                ]);\n            };\n\n            \/\/ Function to add a new monthly recurring transaction entry\n            const addMonthlyRecurringTransaction = (description, amount, type) => {\n                const newRecurringTransactions = [];\n                const baseId = Date.now(); \/\/ Base ID for this set of recurring transactions\n\n                \/\/ Create 12 identical entries, one for each month\n                for (let i = 0; i < 12; i++) {\n                    newRecurringTransactions.push({\n                        id: `${baseId}-${i}`, \/\/ Unique ID for each monthly instance\n                        type: type,\n                        description: description,\n                        amount: amount,\n                        frequency: 'monthly-recurring', \/\/ Explicitly 'monthly-recurring'\n                        monthIndex: i, \/\/ Assign to each month\n                        documentRef: '', \/\/ Placeholder for document reference\n                    });\n                }\n                setTransactions(prevTransactions => [...prevTransactions, ...newRecurringTransactions]);\n            };\n\n            \/\/ Function to handle changes in a specific transaction entry\n            const handleTransactionChange = (id, field, value) => {\n                setTransactions(prevTransactions =>\n                    prevTransactions.map(transaction =>\n                        transaction.id === id\n                            ? { ...transaction, [field]: field === 'amount' ? parseFloat(value) || 0 : value }\n                            : transaction\n                    )\n                );\n            };\n\n            \/\/ Function to remove a transaction entry\n            const removeTransaction = (id) => {\n                setTransactions(prevTransactions => prevTransactions.filter(transaction => transaction.id !== id));\n            };\n\n            \/\/ Function to update main job income based on new annual salary and effective month\n            const updateMainJobIncome = (newAnnualSalary, effectiveMonthIndex) => {\n                const newMonthlyIncomeArray = Array(12).fill(0);\n                const oldMonthlyRate = initialAnnualMainJobIncome \/ 12;\n                const newMonthlyRate = newAnnualSalary \/ 12;\n\n                for (let i = 0; i < 12; i++) {\n                    if (i < effectiveMonthIndex) {\n                        newMonthlyIncomeArray[i] = oldMonthlyRate;\n                    } else {\n                        newMonthlyIncomeArray[i] = newMonthlyRate;\n                    }\n                }\n                setMonthlyMainJobIncome(newMonthlyIncomeArray);\n            };\n\n            \/\/ Callback function to calculate tax and NI\n            const calculateTaxAndNI = React.useCallback(() => {\n                let totalBusinessIncome = 0;\n                let totalBusinessExpenses = 0;\n\n                \/\/ Sum up all income and expenses from all transactions\n                transactions.forEach(transaction => {\n                    if (transaction.type === 'income') {\n                        totalBusinessIncome += transaction.amount;\n                    } else if (transaction.type === 'expense') {\n                        totalBusinessExpenses += transaction.amount;\n                    }\n                });\n\n                const totalBusinessProfit = totalBusinessIncome - totalBusinessExpenses;\n\n                \/\/ Calculate total main job income for the year from the monthly array\n                const totalMainJobIncome = monthlyMainJobIncome.reduce((sum, income) => sum + income, 0);\n\n                const totalAnnualIncome = totalMainJobIncome + totalBusinessProfit;\n\n                \/\/ --- Income Tax Calculation ---\n                let estimatedIncomeTax = 0;\n                \/\/ Taxable income after personal allowance applied to the total annual income\n                const taxableIncome = Math.max(0, totalAnnualIncome - personalAllowance);\n\n                \/\/ Calculate how much of the personal allowance is used by main job income\n                const mainJobIncomeAfterPA = Math.max(0, totalMainJobIncome - personalAllowance);\n\n                \/\/ Calculate how much of the basic rate band is used by main job income\n                const mainJobIncomeInBasicRate = Math.min(mainJobIncomeAfterPA, basicRateBandLimit - personalAllowance);\n\n                \/\/ Calculate remaining basic rate band for business profit\n                const remainingBasicRateBandForBusiness = Math.max(0, (basicRateBandLimit - personalAllowance) - mainJobIncomeInBasicRate);\n\n                \/\/ Calculate tax on business profit\n                if (totalBusinessProfit > 0) {\n                    if (totalBusinessProfit <= remainingBasicRateBandForBusiness) {\n                        \/\/ All business profit falls within the remaining basic rate band\n                        estimatedIncomeTax = totalBusinessProfit * 0.20;\n                    } else {\n                        \/\/ Part of business profit is in basic rate, rest in higher rate or above\n                        estimatedIncomeTax = remainingBasicRateBandForBusiness * 0.20;\n                        let remainingProfitForTax = totalBusinessProfit - remainingBasicRateBandForBusiness;\n\n                        \/\/ Check if remaining profit pushes into higher rate band\n                        if (remainingProfitForTax > 0) {\n                            \/\/ Calculate how much of the higher rate band is left after main job income\n                            const mainJobIncomeInHigherRate = Math.max(0, totalMainJobIncome - basicRateBandLimit);\n                            const remainingHigherRateBand = Math.max(0, (higherRateBandLimit - basicRateBandLimit) - mainJobIncomeInHigherRate);\n\n                            const higherRateBandAmount = Math.min(remainingProfitForTax, remainingHigherRateBand);\n                            estimatedIncomeTax += higherRateBandAmount * 0.40;\n                            remainingProfitForTax -= higherRateBandAmount;\n                        }\n\n                        \/\/ Check if remaining profit pushes into additional rate band\n                        if (remainingProfitForTax > 0) {\n                            estimatedIncomeTax += remainingProfitForTax * 0.45;\n                        }\n                    }\n                }\n\n                \/\/ --- Class 4 National Insurance Calculation ---\n                let estimatedClass4NIC = 0;\n                if (totalBusinessProfit > class4LowerProfitLimit) {\n                    \/\/ Calculate Class 4 NIC on profits between lower and upper limits\n                    const profitInFirstBand = Math.min(totalBusinessProfit, class4UpperProfitLimit) - class4LowerProfitLimit;\n                    estimatedClass4NIC += Math.max(0, profitInFirstBand) * class4Rate1;\n\n                    \/\/ Calculate Class 4 NIC on profits above the upper limit\n                    if (totalBusinessProfit > class4UpperProfitLimit) {\n                        const profitInSecondBand = totalBusinessProfit - class4UpperProfitLimit;\n                        estimatedClass4NIC += profitInSecondBand * class4Rate2;\n                    }\n                }\n\n                const totalTaxAndNI = estimatedIncomeTax + estimatedClass4NIC;\n\n                \/\/ Update the annual summary state\n                setAnnualSummary({\n                    totalBusinessIncome,\n                    totalBusinessExpenses,\n                    totalBusinessProfit,\n                    totalMainJobIncome,\n                    totalAnnualIncome,\n                    estimatedIncomeTax,\n                    estimatedClass4NIC,\n                    totalTaxAndNI,\n                });\n            }, [transactions, monthlyMainJobIncome, personalAllowance, basicRateBandLimit, higherRateBandLimit, class4LowerProfitLimit, class4UpperProfitLimit, class4Rate1, class4Rate2]);\n\n            \/\/ Save transactions to localStorage whenever they change\n            React.useEffect(() => {\n                localStorage.setItem('soleTraderTransactions', JSON.stringify(transactions));\n            }, [transactions]);\n\n            \/\/ Save monthlyMainJobIncome to localStorage whenever it changes\n            React.useEffect(() => {\n                localStorage.setItem('soleTraderMonthlyMainJobIncome', JSON.stringify(monthlyMainJobIncome));\n            }, [monthlyMainJobIncome]);\n\n            \/\/ Recalculate tax and NI whenever transactions or monthlyMainJobIncome data changes\n            React.useEffect(() => {\n                calculateTaxAndNI();\n            }, [transactions, monthlyMainJobIncome, calculateTaxAndNI]);\n\n            \/\/ State for the recurring item modal\n            const [showRecurringModal, setShowRecurringModal] = React.useState(false);\n            const [newRecurringDescription, setNewRecurringDescription] = React.useState('');\n            const [newRecurringAmount, setNewRecurringAmount] = React.useState(0);\n            const [newRecurringType, setNewRecurringType] = React.useState('expense'); \/\/ Default to expense\n\n            const handleAddRecurringSubmit = () => {\n                if (newRecurringDescription && newRecurringAmount > 0) {\n                    addMonthlyRecurringTransaction(newRecurringDescription, newRecurringAmount, newRecurringType);\n                    setNewRecurringDescription('');\n                    setNewRecurringAmount(0);\n                    setNewRecurringType('expense');\n                    setShowRecurringModal(false);\n                } else {\n                    \/\/ In a real app, you'd show a user-friendly error message\n                    console.error(\"Please enter a description and a valid amount for recurring item.\");\n                }\n            };\n\n            \/\/ State for the main job income change modal\n            const [showMainJobIncomeModal, setShowMainJobIncomeModal] = React.useState(false);\n            const [newAnnualMainJobSalary, setNewAnnualMainJobSalary] = React.useState(initialAnnualMainJobIncome);\n            const [effectiveMonthIndex, setEffectiveMonthIndex] = React.useState(0); \/\/ Default to April\n\n            const handleUpdateMainJobIncomeSubmit = () => {\n                if (newAnnualMainJobSalary >= 0) {\n                    updateMainJobIncome(newAnnualMainJobSalary, effectiveMonthIndex);\n                    setShowMainJobIncomeModal(false);\n                } else {\n                    console.error(\"Please enter a valid annual salary.\");\n                }\n            };\n\n            \/\/ Helper function to escape CSV values\n            const escapeCsvValue = (value) => {\n                if (value === null || value === undefined) {\n                    return '';\n                }\n                let stringValue = String(value);\n                \/\/ If the value contains a comma, double quote, or newline, enclose it in double quotes\n                \/\/ and escape any existing double quotes by doubling them.\n                if (stringValue.includes(',') || stringValue.includes('\"') || stringValue.includes('\\n')) {\n                    return `\"${stringValue.replace(\/\"\/g, '\"\"')}\"`;\n                }\n                return stringValue;\n            };\n\n            \/\/ Function to export data to CSV\n            const exportToCsv = () => {\n                let csvContent = \"\";\n\n                \/\/ Main Header Row\n                csvContent += \"Month,Category,Description,Amount,Frequency,Document Reference\\n\";\n\n                monthNames.forEach((month, monthIndex) => {\n                    \/\/ Add a blank row for visual separation between months\n                    if (monthIndex > 0) {\n                        csvContent += \",,,,,\\n\";\n                    }\n\n                    \/\/ Main Job Income Section\n                    csvContent += `${escapeCsvValue(month)},${escapeCsvValue(\"Main Job Income\")},,${escapeCsvValue(monthlyMainJobIncome[monthIndex].toFixed(2))},${escapeCsvValue(\"Recurring\")},\\n`;\n\n                    \/\/ Business Income Section Header\n                    const incomes = transactions.filter(t => t.type === 'income' && t.monthIndex === monthIndex);\n                    if (incomes.length > 0) {\n                        csvContent += `${escapeCsvValue(month)},${escapeCsvValue(\"Business Income\")},,,,\\n`;\n                        incomes.forEach(transaction => {\n                            csvContent += `${escapeCsvValue(month)},,${escapeCsvValue(transaction.description)},${escapeCsvValue(transaction.amount.toFixed(2))},${escapeCsvValue(transaction.frequency)},${escapeCsvValue(transaction.documentRef)}\\n`;\n                        });\n                    }\n\n\n                    \/\/ Business Expense Section Header\n                    const expenses = transactions.filter(t => t.type === 'expense' && t.monthIndex === monthIndex);\n                    if (expenses.length > 0) {\n                        csvContent += `${escapeCsvValue(month)},${escapeCsvValue(\"Business Expense\")},,,,\\n`;\n                        expenses.forEach(transaction => {\n                            csvContent += `${escapeCsvValue(month)},,${escapeCsvValue(transaction.description)},${escapeCsvValue(transaction.amount.toFixed(2))},${escapeCsvValue(transaction.frequency)},${escapeCsvValue(transaction.documentRef)}\\n`;\n                        });\n                    }\n                });\n\n                \/\/ Add Annual Summary\n                csvContent += \"\\nAnnual Summary,,,,,\\n\";\n                csvContent += `Total Business Income,,,${escapeCsvValue(annualSummary.totalBusinessIncome.toFixed(2))},,\\n`;\n                csvContent += `Total Business Expenses,,,${escapeCsvValue(annualSummary.totalBusinessExpenses.toFixed(2))},,\\n`;\n                csvContent += `Net Business Profit,,,${escapeCsvValue(annualSummary.totalBusinessProfit.toFixed(2))},,\\n`;\n                csvContent += `Total Main Job Income,,,${escapeCsvValue(annualSummary.totalMainJobIncome.toFixed(2))},,\\n`;\n                csvContent += `Total Annual Income (Business + Main Job),,,${escapeCsvValue(annualSummary.totalAnnualIncome.toFixed(2))},,\\n`;\n                csvContent += `Estimated Income Tax Due,,,${escapeCsvValue(annualSummary.estimatedIncomeTax.toFixed(2))},,\\n`;\n                csvContent += `Estimated Class 4 NIC Due,,,${escapeCsvValue(annualSummary.estimatedClass4NIC.toFixed(2))},,\\n`;\n                csvContent += `Total Estimated Tax & NI,,,${escapeCsvValue(annualSummary.totalTaxAndNI.toFixed(2))},,\\n`;\n\n\n                const blob = new Blob([csvContent], { type: 'text\/csv;charset=utf-8;' });\n                const link = document.createElement('a');\n                if (link.download !== undefined) { \/\/ Feature detection for download attribute\n                    const url = URL.createObjectURL(blob);\n                    link.setAttribute('href', url);\n                    link.setAttribute('download', 'sole_trader_finances.csv');\n                    link.style.visibility = 'hidden';\n                    document.body.appendChild(link);\n                    link.click();\n                    document.body.removeChild(link);\n                }\n            };\n\n            \/\/ Function to clear all data from local storage and reset state\n            const clearAllData = () => {\n                if (window.confirm('Are you sure you want to clear all saved data? This action cannot be undone.')) {\n                    localStorage.removeItem('soleTraderTransactions');\n                    localStorage.removeItem('soleTraderMonthlyMainJobIncome');\n                    setTransactions([]);\n                    setMonthlyMainJobIncome(Array(12).fill(initialAnnualMainJobIncome \/ 12));\n                    \/\/ Recalculate summary will happen automatically due to state change\n                }\n            };\n\n            return (\n                <div className=\"min-h-screen bg-gray-100 p-4 font-sans text-gray-800 flex flex-col items-center\">\n                    <div className=\"w-full max-w-5xl bg-white shadow-lg rounded-xl p-6 mb-8\">\n                        <h1 className=\"text-3xl font-bold text-center text-blue-700 mb-4\">Sole Trader Financial Tracker<\/h1>\n                        <p className=\"text-center text-gray-600 mb-6\">\n                            Enter your business income and expenses below, and adjust your main job income as needed. Your estimated tax and National Insurance will be calculated automatically based on the UK financial year (April - March).\n                        <\/p>\n                        <div className=\"bg-blue-50 border border-blue-200 text-blue-800 p-4 rounded-lg mb-6\">\n                            <p className=\"font-semibold\">Important Notes:<\/p>\n                            <ul className=\"list-disc list-inside text-sm\">\n                                <li>This tool uses UK tax year 2025\/2026 assumed rates for Personal Allowance (\u00a312,570), Income Tax (20%, 40%, 45%), and Class 4 National Insurance (6%, 2%).<\/li>\n                                <li>You can adjust your main job income using the \"Change Main Job Income\" button. The new salary will apply from the selected month onwards.<\/li>\n                                <li>Class 2 National Insurance is not automatically calculated as it is often voluntary or not applicable for profits above the threshold.<\/li>\n                                <li>The \"Document Reference\" field is for noting where you store your documents (e.g., a link to a cloud storage file, or a local file path); actual file uploads are not supported in this application.<\/li>\n                                <li>\"Monthly Recurring\" items added via the top button will appear in all 12 months, allowing you to track individual invoices for each month.<\/li>\n                                <li>**Your data is now saved automatically in your browser's local storage and will persist across refreshes.**<\/li>\n                                <li>This is an estimate and should not replace professional tax advice. Always verify with HMRC guidelines.<\/li>\n                            <\/ul>\n                        <\/div>\n\n                        {\/* Buttons for Modals and Export *\/}\n                        <div className=\"flex justify-center space-x-4 mb-8\">\n                            <button\n                                onClick={() => setShowRecurringModal(true)}\n                                className=\"bg-purple-600 text-white py-3 px-6 rounded-lg shadow-md hover:bg-purple-700 transition-colors text-lg font-semibold\"\n                            >\n                                Add Monthly Recurring Item\n                            <\/button>\n                            <button\n                                onClick={() => setShowMainJobIncomeModal(true)}\n                                className=\"bg-blue-600 text-white py-3 px-6 rounded-lg shadow-md hover:bg-blue-700 transition-colors text-lg font-semibold\"\n                            >\n                                Change Main Job Income\n                            <\/button>\n                            <button\n                                onClick={exportToCsv}\n                                className=\"bg-green-600 text-white py-3 px-6 rounded-lg shadow-md hover:bg-green-700 transition-colors text-lg font-semibold\"\n                            >\n                                Export to CSV (Excel)\n                            <\/button>\n                            <button\n                                onClick={clearAllData}\n                                className=\"bg-red-600 text-white py-3 px-6 rounded-lg shadow-md hover:bg-red-700 transition-colors text-lg font-semibold\"\n                            >\n                                Clear All Data\n                            <\/button>\n                        <\/div>\n\n                        {\/* Monthly Recurring Item Modal *\/}\n                        {showRecurringModal && (\n                            <div className=\"modal-overlay\">\n                                <div className=\"modal-content\">\n                                    <h3 className=\"text-xl font-semibold text-blue-700 mb-4\">Add Monthly Recurring Transaction<\/h3>\n                                    <div className=\"mb-4\">\n                                        <label htmlFor=\"recurring-description\" className=\"block text-sm font-medium text-gray-700 mb-1\">Description<\/label>\n                                        <input\n                                            type=\"text\"\n                                            id=\"recurring-description\"\n                                            value={newRecurringDescription}\n                                            onChange={(e) => setNewRecurringDescription(e.target.value)}\n                                            className=\"w-full p-2 border border-gray-300 rounded-md\"\n                                            placeholder=\"e.g., Software Subscription, Hosting Costs\"\n                                        \/>\n                                    <\/div>\n                                    <div className=\"mb-4\">\n                                        <label htmlFor=\"recurring-amount\" className=\"block text-sm font-medium text-gray-700 mb-1\">Amount (\u00a3)<\/label>\n                                        <input\n                                            type=\"number\"\n                                            id=\"recurring-amount\"\n                                            value={newRecurringAmount}\n                                            onChange={(e) => setNewRecurringAmount(parseFloat(e.target.value) || 0)}\n                                            className=\"w-full p-2 border border-gray-300 rounded-md\"\n                                            min=\"0\"\n                                        \/>\n                                    <\/div>\n                                    <div className=\"mb-6\">\n                                        <label htmlFor=\"recurring-type\" className=\"block text-sm font-medium text-gray-700 mb-1\">Type<\/label>\n                                        <select\n                                            id=\"recurring-type\"\n                                            value={newRecurringType}\n                                            onChange={(e) => setNewRecurringType(e.target.value)}\n                                            className=\"w-full p-2 border border-gray-300 rounded-md\"\n                                        >\n                                            <option value=\"expense\">Expense<\/option>\n                                            <option value=\"income\">Income<\/option>\n                                        <\/select>\n                                    <\/div>\n                                    <div className=\"flex justify-end space-x-3\">\n                                        <button\n                                            onClick={() => setShowRecurringModal(false)}\n                                            className=\"bg-gray-300 text-gray-800 py-2 px-4 rounded-md hover:bg-gray-400 transition-colors\"\n                                        >\n                                            Cancel\n                                        <\/button>\n                                        <button\n                                            onClick={handleAddRecurringSubmit}\n                                            className=\"bg-purple-600 text-white py-2 px-4 rounded-md hover:bg-purple-700 transition-colors\"\n                                        >\n                                            Add Item\n                                        <\/button>\n                                    <\/div>\n                                <\/div>\n                            <\/div>\n                        )}\n\n                        {\/* Main Job Income Change Modal *\/}\n                        {showMainJobIncomeModal && (\n                            <div className=\"modal-overlay\">\n                                <div className=\"modal-content\">\n                                    <h3 className=\"text-xl font-semibold text-blue-700 mb-4\">Change Main Job Income<\/h3>\n                                    <div className=\"mb-4\">\n                                        <label htmlFor=\"new-annual-salary\" className=\"block text-sm font-medium text-gray-700 mb-1\">New Annual Salary (\u00a3)<\/label>\n                                        <input\n                                            type=\"number\"\n                                            id=\"new-annual-salary\"\n                                            value={newAnnualMainJobSalary}\n                                            onChange={(e) => setNewAnnualMainJobSalary(parseFloat(e.target.value) || 0)}\n                                            className=\"w-full p-2 border border-gray-300 rounded-md\"\n                                            min=\"0\"\n                                        \/>\n                                    <\/div>\n                                    <div className=\"mb-6\">\n                                        <label htmlFor=\"effective-month\" className=\"block text-sm font-medium text-gray-700 mb-1\">Effective From Month<\/label>\n                                        <select\n                                            id=\"effective-month\"\n                                            value={effectiveMonthIndex}\n                                            onChange={(e) => setEffectiveMonthIndex(parseInt(e.target.value))}\n                                            className=\"w-full p-2 border border-gray-300 rounded-md\"\n                                        >\n                                            {monthNames.map((month, index) => (\n                                                <option key={index} value={index}>{month}<\/option>\n                                            ))}\n                                        <\/select>\n                                    <\/div>\n                                    <div className=\"flex justify-end space-x-3\">\n                                        <button\n                                            onClick={() => setShowMainJobIncomeModal(false)}\n                                            className=\"bg-gray-300 text-gray-800 py-2 px-4 rounded-md hover:bg-gray-400 transition-colors\"\n                                        >\n                                            Cancel\n                                        <\/button>\n                                        <button\n                                            onClick={handleUpdateMainJobIncomeSubmit}\n                                            className=\"bg-blue-600 text-white py-2 px-4 rounded-md hover:bg-blue-700 transition-colors\"\n                                        >\n                                            Update Income\n                                        <\/button>\n                                    <\/div>\n                                <\/div>\n                            <\/div>\n                        )}\n\n                        <h2 className=\"text-2xl font-semibold text-blue-600 mb-4 text-center\">Monthly Breakdown<\/h2>\n                        <div className=\"grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6 mb-8\">\n                            {\/* Render 12 monthly tables *\/}\n                            {monthNames.map((month, index) => (\n                                <div key={index} className=\"bg-gray-50 border border-gray-200 rounded-lg p-4 shadow-sm flex flex-col\">\n                                    <h3 className=\"text-lg font-semibold text-gray-700 mb-3\">{month}<\/h3>\n\n                                    {\/* Display Main Job Income for the month *\/}\n                                    <div className=\"mb-4 p-2 bg-blue-100 rounded-md border border-blue-200\">\n                                        <span className=\"block text-sm font-medium text-gray-700 mb-1\">Main Job Income:<\/span>\n                                        <span className=\"block text-lg font-semibold text-blue-800\">\n                                            \u00a3{monthlyMainJobIncome[index].toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })}\n                                        <\/span>\n                                    <\/div>\n\n                                    {\/* Income Entries *\/}\n                                    <div className=\"mb-4\">\n                                        <h4 className=\"text-md font-medium text-gray-600 mb-2\">Business Income<\/h4>\n                                        {transactions\n                                            .filter(t => t.type === 'income' && t.monthIndex === index)\n                                            .map(transaction => (\n                                                <div key={transaction.id} className={`bg-white p-3 rounded-md shadow-sm mb-2 border ${transaction.frequency === 'monthly-recurring' ? 'border-purple-200' : 'border-green-100'}`}>\n                                                    <span className=\"text-xs font-semibold text-gray-500 mb-1 block\">\n                                                        {transaction.frequency === 'monthly-recurring' ? 'Monthly Recurring' : 'One-time'}\n                                                    <\/span>\n                                                    <input\n                                                        type=\"text\"\n                                                        placeholder=\"Description\"\n                                                        value={transaction.description}\n                                                        onChange={(e) => handleTransactionChange(transaction.id, 'description', e.target.value)}\n                                                        className=\"w-full p-1 border border-gray-300 rounded-md text-sm mb-1\"\n                                                    \/>\n                                                    <input\n                                                        type=\"number\"\n                                                        placeholder=\"Amount (\u00a3)\"\n                                                        value={transaction.amount}\n                                                        onChange={(e) => handleTransactionChange(transaction.id, 'amount', e.target.value)}\n                                                        className=\"w-full p-1 border border-gray-300 rounded-md text-sm mb-1\"\n                                                        min=\"0\"\n                                                    \/>\n                                                    <input\n                                                        type=\"text\"\n                                                        placeholder=\"Document Reference (e.g., Invoice #)\"\n                                                        value={transaction.documentRef}\n                                                        onChange={(e) => handleTransactionChange(transaction.id, 'documentRef', e.target.value)}\n                                                        className=\"w-full p-1 border border-gray-300 rounded-md text-sm mb-2\"\n                                                    \/>\n                                                    <button\n                                                        onClick={() => removeTransaction(transaction.id)}\n                                                        className=\"w-full bg-red-500 text-white text-sm py-1 px-2 rounded-md hover:bg-red-600 transition-colors\"\n                                                    >\n                                                        Remove\n                                                    <\/button>\n                                                <\/div>\n                                            ))}\n                                        <button\n                                            onClick={() => addOneTimeTransaction('income', index)}\n                                            className=\"w-full bg-green-500 text-white py-2 px-4 rounded-md hover:bg-green-600 transition-colors mt-2\"\n                                        >\n                                            Add One-time Income\n                                        <\/button>\n                                    <\/div>\n\n                                    {\/* Expense Entries *\/}\n                                    <div>\n                                        <h4 className=\"text-md font-medium text-gray-600 mb-2\">Business Expense<\/h4>\n                                        {transactions\n                                            .filter(t => t.type === 'expense' && t.monthIndex === index)\n                                            .map(transaction => (\n                                                <div key={transaction.id} className={`bg-white p-3 rounded-md shadow-sm mb-2 border ${transaction.frequency === 'monthly-recurring' ? 'border-purple-200' : 'border-red-100'}`}>\n                                                    <span className=\"text-xs font-semibold text-gray-500 mb-1 block\">\n                                                        {transaction.frequency === 'monthly-recurring' ? 'Monthly Recurring' : 'One-time'}\n                                                    <\/span>\n                                                    <input\n                                                        type=\"text\"\n                                                        placeholder=\"Description\"\n                                                        value={transaction.description}\n                                                        onChange={(e) => handleTransactionChange(transaction.id, 'description', e.target.value)}\n                                                        className=\"w-full p-1 border border-gray-300 rounded-md text-sm mb-1\"\n                                                    \/>\n                                                    <input\n                                                        type=\"number\"\n                                                        placeholder=\"Amount (\u00a3)\"\n                                                        value={transaction.amount}\n                                                        onChange={(e) => handleTransactionChange(transaction.id, 'amount', e.target.value)}\n                                                        className=\"w-full p-1 border border-gray-300 rounded-md text-sm mb-1\"\n                                                        min=\"0\"\n                                                    \/>\n                                                    <input\n                                                        type=\"text\"\n                                                        placeholder=\"Document Reference (e.g., Receipt #)\"\n                                                        value={transaction.documentRef}\n                                                        onChange={(e) => handleTransactionChange(transaction.id, 'documentRef', e.target.value)}\n                                                        className=\"w-full p-1 border border-gray-300 rounded-md text-sm mb-2\"\n                                                    \/>\n                                                    <button\n                                                        onClick={() => removeTransaction(transaction.id)}\n                                                        className=\"w-full bg-red-500 text-white text-sm py-1 px-2 rounded-md hover:bg-red-600 transition-colors\"\n                                                    >\n                                                        Remove\n                                                    <\/button>\n                                                <\/div>\n                                            ))}\n                                        <button\n                                            onClick={() => addOneTimeTransaction('expense', index)}\n                                            className=\"w-full bg-red-500 text-white py-2 px-4 rounded-md hover:bg-red-600 transition-colors mt-2\"\n                                        >\n                                            Add One-time Expense\n                                        <\/button>\n                                    <\/div>\n                                <\/div>\n                            ))}\n                        <\/div>\n\n                        <h2 className=\"text-2xl font-semibold text-blue-600 mb-4 text-center\">Annual Summary<\/h2>\n                        <div className=\"bg-blue-100 border border-blue-300 rounded-xl p-6 shadow-md\">\n                            <div className=\"grid grid-cols-1 sm:grid-cols-2 gap-4 text-lg\">\n                                <div className=\"flex justify-between items-center py-2 border-b border-blue-200\">\n                                    <span className=\"font-medium text-blue-800\">Total Business Income:<\/span>\n                                    <span className=\"text-blue-900 font-bold\">\u00a3{annualSummary.totalBusinessIncome.toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })}<\/span>\n                                <\/div>\n                                <div className=\"flex justify-between items-center py-2 border-b border-blue-200\">\n                                    <span className=\"font-medium text-blue-800\">Total Business Expenses:<\/span>\n                                    <span className=\"text-blue-900 font-bold\">\u00a3{annualSummary.totalBusinessExpenses.toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })}<\/span>\n                                <\/div>\n                                <div className=\"flex justify-between items-center py-2 border-b border-blue-200\">\n                                    <span className=\"font-medium text-blue-800\">Net Business Profit:<\/span>\n                                    <span className=\"text-blue-900 font-bold\">\u00a3{annualSummary.totalBusinessProfit.toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })}<\/span>\n                                <\/div>\n                                <div className=\"flex justify-between items-center py-2 border-b border-blue-200\">\n                                    <span className=\"font-medium text-blue-800\">Total Main Job Income:<\/span>\n                                    <span className=\"text-blue-900 font-bold\">\u00a3{annualSummary.totalMainJobIncome.toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })}<\/span>\n                                <\/div>\n                                <div className=\"flex justify-between items-center py-2 border-b border-blue-200 col-span-1 sm:col-span-2\">\n                                    <span className=\"font-medium text-blue-800\">Total Annual Income (Business + Main Job):<\/span>\n                                    <span className=\"text-blue-900 font-bold\">\u00a3{annualSummary.totalAnnualIncome.toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })}<\/span>\n                                <\/div>\n                                <div className=\"flex justify-between items-center py-2 border-b border-blue-200 col-span-1 sm:col-span-2\">\n                                    <span className=\"font-medium text-blue-800\">Estimated Income Tax Due:<\/span>\n                                    <span className=\"text-red-700 font-bold\">\u00a3{annualSummary.estimatedIncomeTax.toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })}<\/span>\n                                <\/div>\n                                <div className=\"flex justify-between items-center py-2 border-b border-blue-200 col-span-1 sm:col-span-2\">\n                                    <span className=\"font-medium text-blue-800\">Estimated Class 4 NIC Due:<\/span>\n                                    <span className=\"text-red-700 font-bold\">\u00a3{annualSummary.estimatedClass4NIC.toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })}<\/span>\n                                <\/div>\n                                <div className=\"flex justify-between items-center py-2 col-span-1 sm:col-span-2 bg-blue-200 rounded-md px-3\">\n                                    <span className=\"font-bold text-xl text-blue-900\">Total Estimated Tax & NI:<\/span>\n                                    <span className=\"font-bold text-xl text-red-800\">\u00a3{annualSummary.totalTaxAndNI.toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })}<\/span>\n                                <\/div>\n                            <\/div>\n                        <\/div>\n                    <\/div>\n                <\/div>\n            );\n        }\n\n        \/\/ Mount the React App to the 'root' div\n        \/\/ Ensure the DOM is fully loaded before rendering the React app\n        window.onload = function() {\n            ReactDOM.render(<App \/>, document.getElementById('root'));\n        };\n    <\/script>\n<\/body>\n<\/html>\n\n<\/div>\n","protected":false},"excerpt":{"rendered":"<p>Sole Trader Financial Tracker<\/p>\n","protected":false},"author":1,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"footnotes":""},"class_list":["post-43","page","type-page","status-publish","hentry"],"_links":{"self":[{"href":"https:\/\/support.webnitix.com\/index.php?rest_route=\/wp\/v2\/pages\/43","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/support.webnitix.com\/index.php?rest_route=\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/support.webnitix.com\/index.php?rest_route=\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/support.webnitix.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/support.webnitix.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=43"}],"version-history":[{"count":5,"href":"https:\/\/support.webnitix.com\/index.php?rest_route=\/wp\/v2\/pages\/43\/revisions"}],"predecessor-version":[{"id":48,"href":"https:\/\/support.webnitix.com\/index.php?rest_route=\/wp\/v2\/pages\/43\/revisions\/48"}],"wp:attachment":[{"href":"https:\/\/support.webnitix.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=43"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}