refactor: enhance routing and state management in CoopBuilder, add migration checks on startup, and update Tailwind configuration for improved component styling
This commit is contained in:
parent
848386e3dd
commit
4cea1f71fe
55 changed files with 4053 additions and 1486 deletions
92
composables/useCushionForecast.ts
Normal file
92
composables/useCushionForecast.ts
Normal file
|
|
@ -0,0 +1,92 @@
|
|||
import { monthlyPayroll } from '~/types/members'
|
||||
|
||||
export function useCushionForecast() {
|
||||
const cashStore = useCashStore()
|
||||
const membersStore = useMembersStore()
|
||||
const policiesStore = usePoliciesStore()
|
||||
const budgetStore = useBudgetStore()
|
||||
|
||||
// Savings progress calculation
|
||||
const savingsProgress = computed(() => {
|
||||
const current = cashStore.currentSavings || 0
|
||||
const targetMonths = policiesStore.savingsTargetMonths || 3
|
||||
const monthlyBurn = getMonthlyBurn()
|
||||
const target = targetMonths * monthlyBurn
|
||||
|
||||
return {
|
||||
current,
|
||||
target,
|
||||
targetMonths,
|
||||
progressPct: target > 0 ? Math.min(100, (current / target) * 100) : 0,
|
||||
gap: Math.max(0, target - current),
|
||||
status: getProgressStatus(current, target)
|
||||
}
|
||||
})
|
||||
|
||||
// 13-week cushion breach forecast
|
||||
const cushionForecast = computed(() => {
|
||||
const minCushion = policiesStore.minCashCushionAmount || 5000
|
||||
const currentBalance = cashStore.currentCash || 0
|
||||
const monthlyBurn = getMonthlyBurn()
|
||||
const weeklyBurn = monthlyBurn / 4.33 // Convert monthly to weekly
|
||||
|
||||
const weeks = []
|
||||
let runningBalance = currentBalance
|
||||
|
||||
for (let week = 1; week <= 13; week++) {
|
||||
// Simple projection: subtract weekly burn
|
||||
runningBalance -= weeklyBurn
|
||||
|
||||
const breachesCushion = runningBalance < minCushion
|
||||
|
||||
weeks.push({
|
||||
week,
|
||||
balance: runningBalance,
|
||||
breachesCushion,
|
||||
cushionAmount: minCushion
|
||||
})
|
||||
}
|
||||
|
||||
const firstBreachWeek = weeks.find(w => w.breachesCushion)?.week
|
||||
const breachesWithin13Weeks = Boolean(firstBreachWeek)
|
||||
|
||||
return {
|
||||
weeks,
|
||||
firstBreachWeek,
|
||||
breachesWithin13Weeks,
|
||||
minCushion,
|
||||
weeksUntilBreach: firstBreachWeek || null
|
||||
}
|
||||
})
|
||||
|
||||
function getMonthlyBurn() {
|
||||
const operatingMode = policiesStore.operatingMode || 'minimum'
|
||||
const payrollCost = monthlyPayroll(membersStore.members, operatingMode)
|
||||
const oncostPct = policiesStore.payrollOncostPct || 0
|
||||
const totalPayroll = payrollCost * (1 + oncostPct / 100)
|
||||
const overheadCost = budgetStore.overheadCosts.reduce((sum, cost) => sum + (cost.amount || 0), 0)
|
||||
|
||||
return totalPayroll + overheadCost
|
||||
}
|
||||
|
||||
function getProgressStatus(current: number, target: number): 'green' | 'yellow' | 'red' {
|
||||
if (target === 0) return 'green'
|
||||
const pct = (current / target) * 100
|
||||
if (pct >= 80) return 'green'
|
||||
if (pct >= 50) return 'yellow'
|
||||
return 'red'
|
||||
}
|
||||
|
||||
// Alert conditions (matching CLAUDE.md)
|
||||
const alerts = computed(() => ({
|
||||
savingsBelowTarget: savingsProgress.value.current < savingsProgress.value.target,
|
||||
cushionBreach: cushionForecast.value.breachesWithin13Weeks,
|
||||
}))
|
||||
|
||||
return {
|
||||
savingsProgress,
|
||||
cushionForecast,
|
||||
alerts,
|
||||
getMonthlyBurn
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue