feat: add initial application structure with configuration, UI components, and state management

This commit is contained in:
Jennie Robinson Faber 2025-08-09 18:13:16 +01:00
parent fadf94002c
commit 0af6b17792
56 changed files with 6137 additions and 129 deletions

View file

@ -0,0 +1,74 @@
/**
* Calculates percentage of savings target met
* Formula: savings ÷ (savings_target_months × monthly burn)
*/
export const useReserveProgress = () => {
const calculateReserveProgress = (
currentSavings: number,
savingsTargetMonths: number,
monthlyBurn: number
): number => {
const targetAmount = savingsTargetMonths * monthlyBurn
if (targetAmount <= 0) return 100
return Math.min((currentSavings / targetAmount) * 100, 100)
}
const getReserveProgressStatus = (progressPct: number): 'green' | 'yellow' | 'red' => {
if (progressPct >= 80) return 'green'
if (progressPct >= 50) return 'yellow'
return 'red'
}
const getReserveProgressMessage = (status: 'green' | 'yellow' | 'red'): string => {
switch (status) {
case 'red':
return 'Build savings to your target before increasing paid hours.'
case 'yellow':
return 'Savings progress is moderate. Continue building reserves.'
case 'green':
return 'Savings target nearly reached or exceeded.'
}
}
const calculateTargetAmount = (savingsTargetMonths: number, monthlyBurn: number): number => {
return savingsTargetMonths * monthlyBurn
}
const calculateShortfall = (
currentSavings: number,
savingsTargetMonths: number,
monthlyBurn: number
): number => {
const targetAmount = calculateTargetAmount(savingsTargetMonths, monthlyBurn)
return Math.max(0, targetAmount - currentSavings)
}
const analyzeReserveProgress = (
currentSavings: number,
savingsTargetMonths: number,
monthlyBurn: number
) => {
const progressPct = calculateReserveProgress(currentSavings, savingsTargetMonths, monthlyBurn)
const status = getReserveProgressStatus(progressPct)
const targetAmount = calculateTargetAmount(savingsTargetMonths, monthlyBurn)
const shortfall = calculateShortfall(currentSavings, savingsTargetMonths, monthlyBurn)
return {
progressPct: Math.round(progressPct),
status,
message: getReserveProgressMessage(status),
currentSavings,
targetAmount,
shortfall
}
}
return {
calculateReserveProgress,
getReserveProgressStatus,
getReserveProgressMessage,
calculateTargetAmount,
calculateShortfall,
analyzeReserveProgress
}
}