app/components/dashboard/RevenueMixCard.vue

53 lines
1.7 KiB
Vue

<template>
<div class="hidden" data-ui="revenue_mix_card_v1" />
<UCard class="min-h-[140px] shadow-sm rounded-xl">
<template #header>
<div class="flex items-center gap-2">
<UIcon name="i-heroicons-chart-pie" class="h-5 w-5" />
<h3 class="font-semibold">Revenue Mix</h3>
</div>
</template>
<div class="space-y-6">
<div
v-if="mix.length === 0"
class="text-sm text-neutral-600 text-center py-8">
Add revenue streams to see mix.
</div>
<div v-else>
<!-- Revenue bars -->
<div v-for="s in mix.slice(0, 3)" :key="s.label" class="mb-2">
<div class="flex justify-between text-xs">
<span class="truncate">{{ s.label }}</span>
<span>{{ Math.round(s.pct * 100) }}%</span>
</div>
<div class="h-2 bg-neutral-200 rounded">
<div
class="h-2 rounded"
:class="getBarColor(mix.indexOf(s))"
:style="{ width: s.pct * 100 + '%' }" />
</div>
</div>
<!-- Subtext with concentration warning -->
<div class="text-sm text-neutral-600 text-center">
Top stream {{ Math.round(topPct * 100) }}%
<span v-if="topPct > 0.5" class="text-amber-600"></span>
</div>
</div>
</div>
</UCard>
</template>
<script setup lang="ts">
const { revenueMix, concentrationPct } = useCoopBuilder();
const mix = computed(() => revenueMix());
const topPct = computed(() => concentrationPct());
function getBarColor(index: number): string {
const colors = ["bg-blue-500", "bg-green-500", "bg-amber-500"];
return colors[index % colors.length];
}
</script>