app/pages/session.vue

173 lines
5.6 KiB
Vue

<template>
<section class="py-8 space-y-6">
<div class="flex items-center justify-between">
<h2 class="text-2xl font-semibold">Value Accounting Session</h2>
<UBadge color="primary" variant="subtle">January 2024</UBadge>
</div>
<div class="grid grid-cols-1 lg:grid-cols-3 gap-6">
<UCard>
<template #header>
<h3 class="text-lg font-medium">Checklist</h3>
</template>
<div class="space-y-3">
<div class="flex items-center gap-3">
<UCheckbox v-model="checklist.monthClosed" />
<span class="text-sm">Month closed & reviewed</span>
</div>
<div class="flex items-center gap-3">
<UCheckbox v-model="checklist.contributionsLogged" />
<span class="text-sm">Contributions logged</span>
</div>
<div class="flex items-center gap-3">
<UCheckbox v-model="checklist.surplusCalculated" />
<span class="text-sm">Surplus calculated</span>
</div>
<div class="flex items-center gap-3">
<UCheckbox v-model="checklist.needsReviewed" />
<span class="text-sm">Member needs reviewed</span>
</div>
</div>
</UCard>
<UCard>
<template #header>
<h3 class="text-lg font-medium">Available</h3>
</template>
<div class="space-y-3">
<div class="flex justify-between text-sm">
<span class="text-neutral-600">Surplus</span>
<span class="font-medium text-green-600"
>{{ availableAmounts.surplus.toLocaleString() }}</span
>
</div>
<div class="flex justify-between text-sm">
<span class="text-neutral-600">Deferred owed</span>
<span class="font-medium text-orange-600"
>{{ availableAmounts.deferredOwed.toLocaleString() }}</span
>
</div>
<div class="flex justify-between text-sm">
<span class="text-neutral-600">Savings gap</span>
<span class="font-medium text-blue-600"
>{{ availableAmounts.savingsNeeded.toLocaleString() }}</span
>
</div>
</div>
</UCard>
<UCard>
<template #header>
<h3 class="text-lg font-medium">Distribution</h3>
</template>
<div class="space-y-4">
<div>
<label class="block text-xs font-medium mb-1">Deferred Repay</label>
<UInput
v-model.number="draftAllocations.deferredRepay"
type="number"
size="sm" />
</div>
<div>
<label class="block text-xs font-medium mb-1">Savings</label>
<UInput
v-model.number="draftAllocations.savings"
type="number"
size="sm" />
</div>
<div>
<label class="block text-xs font-medium mb-1">Training</label>
<UInput
v-model.number="draftAllocations.training"
type="number"
size="sm" />
</div>
<div>
<label class="block text-xs font-medium mb-1">Retained</label>
<UInput
v-model.number="draftAllocations.retained"
type="number"
size="sm"
readonly />
</div>
</div>
</UCard>
</div>
<UCard>
<template #header>
<h3 class="text-lg font-medium">Decision Record</h3>
</template>
<div class="space-y-4">
<UTextarea
v-model="rationale"
placeholder="Brief rationale for this month's distribution decisions..."
rows="3" />
<div class="flex justify-end gap-3">
<UButton variant="ghost"> Save Draft </UButton>
<UButton color="primary" :disabled="!allChecklistComplete">
Complete Session
</UButton>
</div>
</div>
</UCard>
</section>
</template>
<script setup lang="ts">
// Use stores
const sessionStore = useSessionStore();
const membersStore = useMembersStore();
const policiesStore = usePoliciesStore();
const budgetStore = useBudgetStore();
const streamsStore = useStreamsStore();
// Use store refs
const { checklist, draftAllocations, rationale, availableAmounts } =
storeToRefs(sessionStore);
const allChecklistComplete = computed(() => {
return Object.values(checklist.value).every(Boolean);
});
// Calculate available amounts from real data
const calculatedAvailableAmounts = computed(() => {
// Calculate surplus from budget metrics
const totalRevenue = streamsStore.totalMonthlyAmount || 0;
const totalHours = membersStore.capacityTotals.targetHours || 0;
const hourlyWage = policiesStore.equalHourlyWage || 0;
const oncostPct = policiesStore.payrollOncostPct || 0;
const totalPayroll = totalHours * hourlyWage * (1 + oncostPct / 100);
const totalOverhead = budgetStore.overheadCosts.reduce(
(sum, cost) => sum + (cost.amount || 0),
0
);
const surplus = Math.max(0, totalRevenue - totalPayroll - totalOverhead);
// Calculate deferred owed
const deferredOwed = membersStore.members.reduce((sum, member) => {
return sum + (member.deferredHours || 0) * hourlyWage;
}, 0);
// Calculate savings gap
const savingsTarget =
(policiesStore.savingsTargetMonths || 0) * (totalPayroll + totalOverhead);
const savingsNeeded = Math.max(0, savingsTarget);
return {
surplus,
deferredOwed,
savingsNeeded,
};
});
// Update store available amounts when calculated values change
watch(
calculatedAvailableAmounts,
(newAmounts) => {
sessionStore.updateAvailableAmounts(newAmounts);
},
{ immediate: true }
);
</script>