app/pages/budget.vue

264 lines
9 KiB
Vue

<template>
<section class="py-8 space-y-6">
<div class="flex items-center justify-between">
<h2 class="text-2xl font-semibold">Operating Plan</h2>
<USelect
v-model="selectedMonth"
:options="months"
placeholder="Select month" />
</div>
<!-- Cash Waterfall Summary -->
<UCard>
<template #header>
<h3 class="text-lg font-medium">
Cash Waterfall - {{ selectedMonth }}
</h3>
</template>
<div
class="flex items-center justify-between py-4 border-b border-gray-200">
<div class="flex items-center gap-8">
<div class="text-center">
<div class="text-2xl font-bold text-blue-600">€12,000</div>
<div class="text-xs text-gray-600">Gross Revenue</div>
</div>
<UIcon name="i-heroicons-arrow-right" class="text-gray-400" />
<div class="text-center">
<div class="text-2xl font-bold text-red-600">-€450</div>
<div class="text-xs text-gray-600">Fees</div>
</div>
<UIcon name="i-heroicons-arrow-right" class="text-gray-400" />
<div class="text-center">
<div class="text-2xl font-bold text-green-600">€11,550</div>
<div class="text-xs text-gray-600">Net Revenue</div>
</div>
<UIcon name="i-heroicons-arrow-right" class="text-gray-400" />
<div class="text-center">
<div class="text-2xl font-bold text-blue-600">€300</div>
<div class="text-xs text-gray-600">To Savings</div>
</div>
<UIcon name="i-heroicons-arrow-right" class="text-gray-400" />
<div class="text-center">
<div class="text-2xl font-bold text-purple-600">€6,400</div>
<div class="text-xs text-gray-600">Payroll</div>
</div>
<UIcon name="i-heroicons-arrow-right" class="text-gray-400" />
<div class="text-center">
<div class="text-2xl font-bold text-orange-600">€2,300</div>
<div class="text-xs text-gray-600">Overhead</div>
</div>
</div>
</div>
<div class="pt-4">
<div class="flex items-center justify-between">
<span class="text-lg font-medium">Available for Operations</span>
<span class="text-2xl font-bold text-green-600">€2,550</span>
</div>
</div>
</UCard>
<!-- Monthly Revenue Table -->
<UCard>
<template #header>
<h3 class="text-lg font-medium">Revenue by Stream</h3>
</template>
<UTable :rows="revenueStreams" :columns="revenueColumns">
<template #name-data="{ row }">
<div class="flex items-center gap-2">
<span class="font-medium">{{ row.name }}</span>
<RestrictionChip :restriction="row.restrictions" size="xs" />
</div>
</template>
<template #target-data="{ row }">
<span class="font-medium">{{ row.target.toLocaleString() }}</span>
</template>
<template #committed-data="{ row }">
<span class="font-medium text-green-600"
>{{ row.committed.toLocaleString() }}</span
>
</template>
<template #actual-data="{ row }">
<span
class="font-medium"
:class="
row.actual >= row.committed ? 'text-green-600' : 'text-orange-600'
">
{{ row.actual.toLocaleString() }}
</span>
</template>
<template #variance-data="{ row }">
<span :class="row.variance >= 0 ? 'text-green-600' : 'text-red-600'">
{{ row.variance >= 0 ? "+" : "" }}{{
row.variance.toLocaleString()
}}
</span>
</template>
</UTable>
</UCard>
<!-- Costs Breakdown -->
<div class="grid grid-cols-1 lg:grid-cols-2 gap-6">
<UCard>
<template #header>
<h3 class="text-lg font-medium">Costs</h3>
</template>
<div class="space-y-4">
<div>
<h4 class="font-medium text-sm mb-2">Payroll</h4>
<div class="space-y-2">
<div class="flex justify-between text-sm">
<span class="text-gray-600">Wages (320h @ 20)</span>
<span class="font-medium">6,400</span>
</div>
<div class="flex justify-between text-sm">
<span class="text-gray-600">On-costs (25%)</span>
<span class="font-medium">1,600</span>
</div>
<div
class="flex justify-between text-sm font-medium border-t pt-2">
<span>Total Payroll</span>
<span>8,000</span>
</div>
</div>
</div>
<div>
<h4 class="font-medium text-sm mb-2">Overhead</h4>
<div class="space-y-2">
<div class="flex justify-between text-sm">
<span class="text-gray-600">Coworking space</span>
<span class="font-medium">800</span>
</div>
<div class="flex justify-between text-sm">
<span class="text-gray-600">Tools & software</span>
<span class="font-medium">400</span>
</div>
<div class="flex justify-between text-sm">
<span class="text-gray-600">Insurance</span>
<span class="font-medium">200</span>
</div>
<div
class="flex justify-between text-sm font-medium border-t pt-2">
<span>Total Overhead</span>
<span>1,400</span>
</div>
</div>
</div>
<div>
<h4 class="font-medium text-sm mb-2">Production</h4>
<div class="space-y-2">
<div class="flex justify-between text-sm">
<span class="text-gray-600">Dev kits</span>
<span class="font-medium">500</span>
</div>
<div
class="flex justify-between text-sm font-medium border-t pt-2">
<span>Total Production</span>
<span>500</span>
</div>
</div>
</div>
</div>
</UCard>
<UCard>
<template #header>
<h3 class="text-lg font-medium">Net Impact on Savings</h3>
</template>
<div class="space-y-4">
<div class="space-y-3">
<div class="flex justify-between text-sm">
<span class="text-gray-600">Net Revenue</span>
<span class="font-medium text-green-600">11,550</span>
</div>
<div class="flex justify-between text-sm">
<span class="text-gray-600">Total Costs</span>
<span class="font-medium text-red-600">-9,900</span>
</div>
<div class="flex justify-between text-lg font-bold border-t pt-3">
<span>Net</span>
<span class="text-green-600">+1,650</span>
</div>
</div>
<div class="bg-gray-50 rounded-lg p-4">
<h4 class="font-medium text-sm mb-3">Allocation</h4>
<div class="space-y-2">
<div class="flex justify-between text-sm">
<span class="text-gray-600">To Savings</span>
<span class="font-medium">1,200</span>
</div>
<div class="flex justify-between text-sm">
<span class="text-gray-600">Available</span>
<span class="font-medium">450</span>
</div>
</div>
</div>
<div class="text-xs text-gray-600 space-y-1">
<p>
<RestrictionChip restriction="Restricted" size="xs" /> funds can
only be used for approved purposes.
</p>
<p>
<RestrictionChip restriction="General" size="xs" /> funds have no
restrictions.
</p>
</div>
</div>
</UCard>
</div>
</section>
</template>
<script setup lang="ts">
const selectedMonth = ref("2024-01");
const months = ref([
{ label: "January 2024", value: "2024-01" },
{ label: "February 2024", value: "2024-02" },
{ label: "March 2024", value: "2024-03" },
]);
const revenueStreams = ref([
{
id: 1,
name: "Client Services",
target: 7800,
committed: 6500,
actual: 7200,
variance: 700,
restrictions: "General",
},
{
id: 2,
name: "Platform Sales",
target: 3000,
committed: 2000,
actual: 2400,
variance: 400,
restrictions: "General",
},
{
id: 3,
name: "Grant Funding",
target: 1200,
committed: 0,
actual: 1400,
variance: 1400,
restrictions: "Restricted",
},
]);
const revenueColumns = [
{ id: "name", key: "name", label: "Stream" },
{ id: "target", key: "target", label: "Target" },
{ id: "committed", key: "committed", label: "Committed" },
{ id: "actual", key: "actual", label: "Actual" },
{ id: "variance", key: "variance", label: "Variance" },
];
</script>