Skip to content

Commit 6ca1df0

Browse files
author
Neil
committed
Build 22: Perfection Audit. Fixed 13 lint issues, stabilized hook dependencies, and improved boot sequence robustness.
1 parent 1dc07c4 commit 6ca1df0

2 files changed

Lines changed: 18 additions & 36 deletions

File tree

eslint_output.txt

6.91 KB
Binary file not shown.

src/App.jsx

Lines changed: 18 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import React, { useState, useEffect, useMemo, useCallback, useRef } from 'react';
22
import { Plus, Trash2, Calculator, TrendingUp, Download, Info, AlertTriangle, Calendar, Clock, Receipt, Settings, RefreshCw, LayoutDashboard, CheckSquare, Square, ExternalLink, LogOut, BarChart3, PieChart as PieChartIcon, ShieldCheck, Printer, Landmark, Copy, Briefcase, BookOpen, Sun, Moon, Bot, Smartphone, Car, Gauge } from 'lucide-react';
33
import { GoogleGenerativeAI } from '@google/generative-ai';
4-
import { calculateTax, projectAnnual, getTaxTrapAdvice, calculateOvertime, recommendTaxCode, parseTaxCode } from './logic/TaxCalculator';
4+
import { calculateTax, projectAnnual, getTaxTrapAdvice, calculateOvertime, recommendTaxCode } from './logic/TaxCalculator';
55
import { auth, db } from './firebase';
66
import { onAuthStateChanged, signOut } from 'firebase/auth';
77
import { doc, getDoc, setDoc } from 'firebase/firestore';
@@ -13,7 +13,7 @@ import AiAssistant from './AiAssistant';
1313
import { calculateSEProfit, calculateMileageAllowance, calculateSelfAssessment } from './logic/SelfAssessmentCalculator';
1414

1515
const MONTHS = ['April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December', 'January', 'February', 'March'];
16-
export const getCurrentTaxYear = () => {
16+
const getCurrentTaxYear = () => {
1717
const now = new Date();
1818
const year = now.getFullYear();
1919
// UK tax year starts April 6th
@@ -123,7 +123,7 @@ function App() {
123123
const [isLoaded, setIsLoaded] = useState(false);
124124
const isBootingRef = useRef(false);
125125

126-
const DEFAULT_PROFILE = () => ({
126+
const DEFAULT_PROFILE = useCallback(() => ({
127127
taxCode: '1257L', baseSalary: 45000, contractedHours: 37.5,
128128
pensionPercent: 5, pensionType: 'standard', holidaySupplementPercent: 8.3,
129129
studentLoanPlans: [], childBenefitCount: 0,
@@ -136,9 +136,9 @@ function App() {
136136
isPremium: true,
137137
leaseConfig: { startDate: '', termMonths: 36, totalAllowedMiles: 30000 },
138138
mileageLogs: []
139-
});
139+
}), []);
140140

141-
const applyProfile = (prof) => {
141+
const applyProfile = useCallback((prof) => {
142142
setTaxCode(prof.taxCode || '1257L');
143143
setBaseSalary(prof.baseSalary || 45000);
144144
setContractedHours(prof.contractedHours || 37.5);
@@ -157,7 +157,7 @@ function App() {
157157
setIsPremium(true); // Always Pro for Paid App Launch
158158
setLeaseConfig(prof.leaseConfig || { startDate: '', termMonths: 36, totalAllowedMiles: 30000 });
159159
setMileageLogs(prof.mileageLogs || []);
160-
};
160+
}, []);
161161

162162
// Auth state listener - fires once on mount
163163
useEffect(() => {
@@ -229,14 +229,14 @@ function App() {
229229
});
230230

231231
return () => unsub();
232-
}, []);
232+
}, [DEFAULT_PROFILE, applyProfile, isLoaded]);
233233

234234
// Trigger tour if not completed
235235
useEffect(() => {
236236
if (isLoaded && currentUser && !hasCompletedTour && tourStep === null) {
237237
setTourStep(0);
238238
}
239-
}, [isLoaded, currentUser, hasCompletedTour]);
239+
}, [isLoaded, currentUser, hasCompletedTour, tourStep]);
240240

241241
// --- Tour Steps Definition ---
242242
const tourSteps = [
@@ -347,7 +347,7 @@ function App() {
347347
document.documentElement.style.setProperty('--spotlight-r', `0px`);
348348
setStyle({ '--modal-x': '50%', '--modal-y': '50%' });
349349
}
350-
}, [tourStep]);
350+
}, [step]);
351351

352352
if (tourStep === null || !tourSteps[tourStep]) return null;
353353

@@ -386,7 +386,7 @@ function App() {
386386
// Also keep localStorage as offline backup
387387
localStorage.setItem('taxTrackerDataV14_Profiles', JSON.stringify(updatedProfiles));
388388
localStorage.setItem('taxTracker_activeYear', taxYear);
389-
}, [taxCode, baseSalary, contractedHours, pensionPercent, pensionType, holidaySupplementPercent, studentLoanPlans, childBenefitCount, baseEnhancements, baseSacrifices, geminiApiKey, months, workMode, seData, hasCompletedTour, isLoaded, leaseConfig, mileageLogs]);
389+
}, [taxCode, baseSalary, contractedHours, pensionPercent, pensionType, holidaySupplementPercent, studentLoanPlans, childBenefitCount, baseEnhancements, baseSacrifices, geminiApiKey, months, workMode, seData, hasCompletedTour, isLoaded, currentUser, profiles, taxYear, leaseConfig, mileageLogs]);
390390

391391
// Switch Year Handler
392392
const handleYearSwitch = (newYear) => {
@@ -433,7 +433,7 @@ function App() {
433433
netSacrifice: netBaseSacrificeMonthly,
434434
taxFree: 0
435435
};
436-
}, [baseSalary, baseEnhancements, baseSacrifices, pensionPercent, contractedHours, sandboxMode, sandboxSalary, sandboxPension, sandboxOvertime, sandboxSacrifice]);
436+
}, [baseSalary, baseEnhancements, baseSacrifices, pensionPercent, sandboxMode, sandboxSalary, sandboxPension, sandboxOvertime, sandboxSacrifice, getMonthlyValue]);
437437

438438
// 2. Prepare Actual Month Data (April to selected month)
439439
const monthsActualData = useMemo(() => {
@@ -486,7 +486,7 @@ function App() {
486486
rawMonthsActual: m
487487
};
488488
});
489-
}, [months, baseSalary, contractedHours, pensionPercent, baseEnhancements, baseSacrifices, holidaySupplementPercent, sandboxMode, sandboxSalary, sandboxPension, sandboxOvertime, sandboxSacrifice]);
489+
}, [months, baseSalary, contractedHours, pensionPercent, baseEnhancements, baseSacrifices, holidaySupplementPercent, sandboxMode, sandboxSalary, sandboxPension, sandboxOvertime, sandboxSacrifice, getMonthlyValue]);
490490

491491
// 3. Analytics & Projections Data
492492
const analyticsData = useMemo(() => {
@@ -711,12 +711,12 @@ function App() {
711711
// Analytics Tab Component
712712
const AnalyticsTab = () => {
713713
const COLORS = ['#6366f1', '#10b981', '#f43f5e', '#8b5cf6'];
714-
const pieData = [
714+
/* const pieData = [
715715
{ name: 'Take Home', value: analyticsData.totalTakeHome, color: '#6366f1' },
716716
{ name: 'Income Tax', value: analyticsData.projections.incomeTax + analyticsData.seSABill, color: '#f43f5e' },
717717
{ name: 'Nat. Insurance', value: analyticsData.projections.ni, color: '#fbbf24' },
718718
{ name: 'Pension', value: analyticsData.projections.pensionContribution, color: '#10b981' }
719-
];
719+
]; */
720720

721721
return (
722722
<div className="analytics-view">
@@ -969,14 +969,14 @@ function App() {
969969

970970
const totalMonthlyNet = (monthlyResultsAnnualized.annualTakeHome / 12) + currentMonthFull.taxFree;
971971

972-
const chartData = [
972+
/* const chartData = [
973973
{ name: 'Net Pay', value: monthlyResultsAnnualized.annualTakeHome / 12, color: 'var(--success)' },
974974
{ name: 'Income Tax', value: monthlyResultsAnnualized.incomeTax / 12, color: 'var(--error)' },
975975
{ name: 'NI', value: monthlyResultsAnnualized.ni / 12, color: '#f59e0b' },
976976
{ name: 'Student Loan', value: monthlyResultsAnnualized.studentLoan / 12, color: '#06b6d4' },
977977
{ name: 'Pension', value: monthlyResultsAnnualized.pensionContribution / 12, color: 'var(--primary)' },
978978
{ name: 'Other', value: monthlyResultsAnnualized.hicbc / 12 + monthlyResultsAnnualized.netDeductions / 12, color: '#6b7280' }
979-
].filter(i => i.value > 0);
979+
].filter(i => i.value > 0); */
980980

981981
// Overtime Processing
982982
const allOvertime = useMemo(() => {
@@ -998,18 +998,9 @@ function App() {
998998
const trapAdvice = getTaxTrapAdvice(projection.taxableIncome, pensionPercent, baseSalary, taxCode);
999999

10001000
// --- Handlers ---
1001-
const addBaseItem = (type) => {
1002-
const newItem = { id: Date.now().toString(), name: 'New Item', amount: '', frequency: 'monthly', type: type === 'sacrifice' ? 'salary_sacrifice' : 'income' };
1003-
if (type === 'enhancement') setBaseEnhancements([...baseEnhancements, newItem]);
1004-
else setBaseSacrifices([...baseSacrifices, newItem]);
1005-
};
10061001

1007-
const updateBaseItem = (type, id, field, val) => {
1008-
const list = type === 'enhancement' ? [...baseEnhancements] : [...baseSacrifices];
1009-
const updated = list.map(i => i.id === id ? { ...i, [field]: val } : i);
1010-
if (type === 'enhancement') setBaseEnhancements(updated);
1011-
else setBaseSacrifices(updated);
1012-
};
1002+
1003+
10131004

10141005
const removeBaseItem = (type, id) => {
10151006
if (type === 'enhancement') setBaseEnhancements(baseEnhancements.filter(i => i.id !== id));
@@ -1079,16 +1070,7 @@ function App() {
10791070
setMonths(n);
10801071
};
10811072

1082-
const moveOvertimeItem = (oldMonthIdx, newMonthIdx, id) => {
1083-
if (oldMonthIdx === newMonthIdx) return;
1084-
const itemToMove = months[oldMonthIdx].overtime.find(i => i.id === id);
1085-
if (!itemToMove) return;
10861073

1087-
const n = [...months];
1088-
n[oldMonthIdx].overtime = n[oldMonthIdx].overtime.filter(i => i.id !== id);
1089-
n[newMonthIdx].overtime.push(itemToMove);
1090-
setMonths(n);
1091-
};
10921074

10931075
const clearCacheAndReload = () => {
10941076
if (window.confirm("Perform hard reset? Your data is safe. Proceed?")) {

0 commit comments

Comments
 (0)