56 lines
No EOL
1.8 KiB
Vue
56 lines
No EOL
1.8 KiB
Vue
<template>
|
|
<div class="hidden" data-ui="member_coverage_panel_v1" />
|
|
<UCard class="shadow-sm rounded-xl">
|
|
<template #header>
|
|
<h3 class="font-semibold">Member needs coverage</h3>
|
|
</template>
|
|
|
|
<div class="space-y-6">
|
|
<div
|
|
v-for="member in allocatedMembers"
|
|
:key="member.id"
|
|
class="flex items-center gap-4"
|
|
>
|
|
<div class="w-20 text-sm font-medium text-gray-700 truncate">
|
|
{{ member.name }}
|
|
</div>
|
|
<div class="flex-1">
|
|
<div class="w-full bg-gray-200 rounded-full h-2">
|
|
<div
|
|
class="h-2 rounded-full transition-all"
|
|
:class="getBarColor(coverage(member).minPct)"
|
|
:style="{ width: `${Math.min(100, (coverage(member).minPct / 200) * 100)}%` }"
|
|
/>
|
|
</div>
|
|
</div>
|
|
<div class="w-12 text-sm font-medium text-right">
|
|
{{ Math.round(coverage(member).minPct) }}%
|
|
</div>
|
|
</div>
|
|
|
|
<div v-if="allocatedMembers.length === 0" class="text-sm text-gray-600 text-center py-8">
|
|
Add members in Setup → Members to see coverage.
|
|
</div>
|
|
</div>
|
|
|
|
<template #footer v-if="allocatedMembers.length > 0">
|
|
<div class="text-sm text-gray-600 text-center">
|
|
Team median {{ Math.round(stats.median) }}% • {{ stats.under100 }} under 100%{{ allCovered ? ' • All covered ✓' : '' }}
|
|
</div>
|
|
</template>
|
|
</UCard>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
const { allocatePayroll, coverage, teamCoverageStats } = useCoopBuilder()
|
|
|
|
const allocatedMembers = computed(() => allocatePayroll())
|
|
const stats = computed(() => teamCoverageStats())
|
|
const allCovered = computed(() => stats.value.under100 === 0)
|
|
|
|
function getBarColor(pct: number): string {
|
|
if (pct >= 100) return 'bg-green-500'
|
|
if (pct >= 80) return 'bg-amber-500'
|
|
return 'bg-red-500'
|
|
}
|
|
</script> |