refactor: remove CashFlowChart and UnifiedCashFlowDashboard components, update routing paths in app.vue, and enhance budget page with cumulative balance calculations and payroll explanation modal for improved user experience
This commit is contained in:
parent
864a81065c
commit
f1889b3a70
17 changed files with 922 additions and 1004 deletions
84
pages/project-budget.vue
Normal file
84
pages/project-budget.vue
Normal file
|
|
@ -0,0 +1,84 @@
|
|||
<template>
|
||||
<div class="space-y-8">
|
||||
<div class="text-center">
|
||||
<h1 class="text-3xl font-bold mb-4">Project Budget Estimate</h1>
|
||||
<p class="text-gray-600 max-w-2xl mx-auto mb-4">
|
||||
Get a quick estimate of what it would cost to build your project with fair pay.
|
||||
This tool helps worker co-ops sketch project budgets and break-even scenarios.
|
||||
</p>
|
||||
<div class="bg-blue-50 border border-blue-200 rounded-lg p-4 max-w-2xl mx-auto">
|
||||
<div class="flex items-start gap-2">
|
||||
<UIcon name="i-heroicons-information-circle" class="h-5 w-5 text-blue-500 mt-0.5 flex-shrink-0" />
|
||||
<div class="text-sm text-blue-800">
|
||||
<p class="font-medium mb-1">About the calculations:</p>
|
||||
<p>These estimates are based on <strong>sustainable payroll</strong> — what you can actually afford to pay based on your revenue minus overhead costs. This may be different from theoretical maximum wages if revenue is limited.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-if="membersWithPay.length === 0" class="text-center py-8">
|
||||
<p class="text-gray-600 mb-4">No team members set up yet.</p>
|
||||
<NuxtLink
|
||||
to="/coop-builder"
|
||||
class="px-4 py-2 border-2 border-black bg-white font-bold hover:bg-gray-100"
|
||||
>
|
||||
Set up your team in Setup Wizard
|
||||
</NuxtLink>
|
||||
</div>
|
||||
|
||||
<ProjectBudgetEstimate
|
||||
v-else
|
||||
:members="membersWithPay"
|
||||
:oncost-rate="coopStore.payrollOncostPct / 100"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
const coopStore = useCoopBuilderStore()
|
||||
const budgetStore = useBudgetStore()
|
||||
|
||||
// Calculate member pay using the same allocation logic as the budget system
|
||||
const membersWithPay = computed(() => {
|
||||
// Get current month's payroll from budget store (matches budget page)
|
||||
const today = new Date()
|
||||
const currentMonthKey = `${today.getFullYear()}-${String(today.getMonth() + 1).padStart(2, "0")}`
|
||||
|
||||
const payrollExpense = budgetStore.budgetWorksheet.expenses.find(item =>
|
||||
item.id === "expense-payroll-base" || item.id === "expense-payroll"
|
||||
)
|
||||
const actualPayrollBudget = payrollExpense?.monthlyValues?.[currentMonthKey] || 0
|
||||
|
||||
// Use the member's desired hours (targetHours if available, otherwise hoursPerMonth)
|
||||
const getHoursForMember = (member: any) => {
|
||||
return member.capacity?.targetHours || member.hoursPerMonth || 0
|
||||
}
|
||||
|
||||
// Get theoretical allocation then scale to actual budget
|
||||
const { allocatePayroll } = useCoopBuilder()
|
||||
const theoreticalMembers = allocatePayroll()
|
||||
const theoreticalTotal = theoreticalMembers.reduce((sum, m) => sum + (m.monthlyPayPlanned || 0), 0)
|
||||
const scaleFactor = theoreticalTotal > 0 ? actualPayrollBudget / theoreticalTotal : 0
|
||||
|
||||
const allocatedMembers = theoreticalMembers.map(member => ({
|
||||
...member,
|
||||
monthlyPayPlanned: (member.monthlyPayPlanned || 0) * scaleFactor
|
||||
}))
|
||||
|
||||
return allocatedMembers.map(member => {
|
||||
const hours = getHoursForMember(member)
|
||||
|
||||
return {
|
||||
name: member.name || 'Unnamed',
|
||||
hoursPerMonth: hours,
|
||||
monthlyPay: member.monthlyPayPlanned || 0
|
||||
}
|
||||
}).filter(m => m.hoursPerMonth > 0) // Only include members with hours
|
||||
})
|
||||
|
||||
// Set page meta
|
||||
definePageMeta({
|
||||
title: 'Project Budget Estimate'
|
||||
})
|
||||
</script>
|
||||
Loading…
Add table
Add a link
Reference in a new issue