Epics table: barra de progreso (% HUs completadas) + removida columna Asignado
- epicProgress computed: agrupa HUs por _epicCode, calcula % completadas - getEpicProgress(epic): resuelve progreso para cada épica - Barra visual con colores: verde=100%, azul=>0%, gris=0%
This commit is contained in:
@@ -539,6 +539,32 @@ watch(
|
||||
{ immediate: true }
|
||||
)
|
||||
|
||||
// ─── Epic progress bar ───────────────────────────────
|
||||
const epicProgress = computed(() => {
|
||||
const map = new Map<string, { total: number; done: number }>()
|
||||
for (const hu of workItems.userStories) {
|
||||
const epicCode = hu._epicCode || ''
|
||||
if (!epicCode) continue
|
||||
if (!map.has(epicCode)) map.set(epicCode, { total: 0, done: 0 })
|
||||
const entry = map.get(epicCode)!
|
||||
entry.total++
|
||||
const s = String(hu.status ?? '').toLowerCase()
|
||||
if (['done', 'completed', 'closed', 'finalizado', '5', 'true'].includes(s)) {
|
||||
entry.done++
|
||||
}
|
||||
}
|
||||
const result: Record<string, number> = {}
|
||||
for (const [code, { total, done }] of map) {
|
||||
result[code] = total > 0 ? Math.round((done / total) * 100) : 0
|
||||
}
|
||||
return result
|
||||
})
|
||||
|
||||
function getEpicProgress(epic: any): number {
|
||||
const code = epic._epicCode
|
||||
return code ? epicProgress.value[code] ?? 0 : 0
|
||||
}
|
||||
|
||||
const statusVariant = (status: unknown) => {
|
||||
const s = String(status ?? '').toLowerCase()
|
||||
if (['done', 'completed', 'closed', 'finalizado'].includes(s)) return 'secondary'
|
||||
@@ -771,8 +797,7 @@ const statusLabel = (status: unknown) => {
|
||||
<TableHead class="w-[60px]">{{ t('users.role') }}</TableHead>
|
||||
<TableHead>{{ t('dashboard.title') }}</TableHead>
|
||||
<TableHead class="w-[60px] text-center">Desc</TableHead>
|
||||
<TableHead class="w-[90px] text-center">{{ t('dashboard.assignedTo') }}</TableHead>
|
||||
<TableHead class="w-[100px]">{{ t('dashboard.status') }}</TableHead>
|
||||
<TableHead class="w-[140px]">Progreso</TableHead>
|
||||
</TableRow>
|
||||
</TableHeader>
|
||||
<TableBody>
|
||||
@@ -792,9 +817,17 @@ const statusLabel = (status: unknown) => {
|
||||
</Dialog>
|
||||
<span v-else class="text-xs text-muted-foreground/40">—</span>
|
||||
</TableCell>
|
||||
<TableCell class="text-center text-xs text-muted-foreground">—</TableCell>
|
||||
<TableCell>
|
||||
<Badge :variant="statusVariant(epic.status || '')" class="text-xs">{{ statusLabel(epic.status || '') }}</Badge>
|
||||
<TableCell class="text-xs">
|
||||
<div class="flex items-center gap-2">
|
||||
<div class="flex-1 h-2 rounded-full bg-muted overflow-hidden">
|
||||
<div
|
||||
class="h-full rounded-full transition-all duration-300"
|
||||
:class="getEpicProgress(epic) >= 100 ? 'bg-green-500' : getEpicProgress(epic) > 0 ? 'bg-primary' : ''"
|
||||
:style="{ width: getEpicProgress(epic) + '%' }"
|
||||
/>
|
||||
</div>
|
||||
<span class="font-mono text-[10px] text-muted-foreground w-8 text-right">{{ getEpicProgress(epic) }}%</span>
|
||||
</div>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
</TableBody>
|
||||
|
||||
Reference in New Issue
Block a user