fix(app): align Form failures KPI row with AppKpiCard
Reuse AppKpiCard for the four tiles; selection uses borderAccent primary (bottom stripe) instead of full border-primary outline. Update tests to register AppKpiCard and stub VAvatar. Made-with: Cursor
This commit is contained in:
@@ -140,28 +140,15 @@ function setStateFilter(s: FormFailureState | 'all') {
|
|||||||
lg="3"
|
lg="3"
|
||||||
class="d-flex"
|
class="d-flex"
|
||||||
>
|
>
|
||||||
<VCard
|
<AppKpiCard
|
||||||
density="compact"
|
icon="tabler-alert-triangle"
|
||||||
variant="outlined"
|
icon-color="error"
|
||||||
class="flex-grow-1 w-100 cursor-pointer d-flex flex-column"
|
:value="kpis?.open ?? 0"
|
||||||
:class="stateFilter === 'open' ? 'border-opacity-100 border-primary' : ''"
|
title="Open failures"
|
||||||
|
clickable
|
||||||
|
:border-accent="stateFilter === 'open' ? 'primary' : undefined"
|
||||||
@click="setStateFilter('open')"
|
@click="setStateFilter('open')"
|
||||||
>
|
/>
|
||||||
<VCardText class="flex-grow-1 d-flex flex-column justify-center">
|
|
||||||
<p class="text-caption text-disabled mb-1 text-no-wrap">
|
|
||||||
Open failures
|
|
||||||
</p>
|
|
||||||
<h5 class="text-h5 mb-0 d-flex align-center">
|
|
||||||
<VIcon
|
|
||||||
icon="tabler-alert-triangle"
|
|
||||||
color="error"
|
|
||||||
size="20"
|
|
||||||
class="me-1"
|
|
||||||
/>
|
|
||||||
{{ kpis?.open ?? 0 }}
|
|
||||||
</h5>
|
|
||||||
</VCardText>
|
|
||||||
</VCard>
|
|
||||||
</VCol>
|
</VCol>
|
||||||
<VCol
|
<VCol
|
||||||
cols="12"
|
cols="12"
|
||||||
@@ -169,28 +156,15 @@ function setStateFilter(s: FormFailureState | 'all') {
|
|||||||
lg="3"
|
lg="3"
|
||||||
class="d-flex"
|
class="d-flex"
|
||||||
>
|
>
|
||||||
<VCard
|
<AppKpiCard
|
||||||
density="compact"
|
icon="tabler-check"
|
||||||
variant="outlined"
|
icon-color="success"
|
||||||
class="flex-grow-1 w-100 cursor-pointer d-flex flex-column"
|
:value="kpis?.resolved_30d ?? 0"
|
||||||
:class="stateFilter === 'resolved' ? 'border-opacity-100 border-primary' : ''"
|
title="Opgelost (30d)"
|
||||||
|
clickable
|
||||||
|
:border-accent="stateFilter === 'resolved' ? 'primary' : undefined"
|
||||||
@click="setStateFilter('resolved')"
|
@click="setStateFilter('resolved')"
|
||||||
>
|
/>
|
||||||
<VCardText class="flex-grow-1 d-flex flex-column justify-center">
|
|
||||||
<p class="text-caption text-disabled mb-1 text-no-wrap">
|
|
||||||
Opgelost (30d)
|
|
||||||
</p>
|
|
||||||
<h5 class="text-h5 mb-0 d-flex align-center">
|
|
||||||
<VIcon
|
|
||||||
icon="tabler-check"
|
|
||||||
color="success"
|
|
||||||
size="20"
|
|
||||||
class="me-1"
|
|
||||||
/>
|
|
||||||
{{ kpis?.resolved_30d ?? 0 }}
|
|
||||||
</h5>
|
|
||||||
</VCardText>
|
|
||||||
</VCard>
|
|
||||||
</VCol>
|
</VCol>
|
||||||
<VCol
|
<VCol
|
||||||
cols="12"
|
cols="12"
|
||||||
@@ -198,28 +172,15 @@ function setStateFilter(s: FormFailureState | 'all') {
|
|||||||
lg="3"
|
lg="3"
|
||||||
class="d-flex"
|
class="d-flex"
|
||||||
>
|
>
|
||||||
<VCard
|
<AppKpiCard
|
||||||
density="compact"
|
icon="tabler-x"
|
||||||
variant="outlined"
|
icon-color="warning"
|
||||||
class="flex-grow-1 w-100 cursor-pointer d-flex flex-column"
|
:value="kpis?.dismissed_30d ?? 0"
|
||||||
:class="stateFilter === 'dismissed' ? 'border-opacity-100 border-primary' : ''"
|
title="Dismissed (30d)"
|
||||||
|
clickable
|
||||||
|
:border-accent="stateFilter === 'dismissed' ? 'primary' : undefined"
|
||||||
@click="setStateFilter('dismissed')"
|
@click="setStateFilter('dismissed')"
|
||||||
>
|
/>
|
||||||
<VCardText class="flex-grow-1 d-flex flex-column justify-center">
|
|
||||||
<p class="text-caption text-disabled mb-1 text-no-wrap">
|
|
||||||
Dismissed (30d)
|
|
||||||
</p>
|
|
||||||
<h5 class="text-h5 mb-0 d-flex align-center">
|
|
||||||
<VIcon
|
|
||||||
icon="tabler-x"
|
|
||||||
color="warning"
|
|
||||||
size="20"
|
|
||||||
class="me-1"
|
|
||||||
/>
|
|
||||||
{{ kpis?.dismissed_30d ?? 0 }}
|
|
||||||
</h5>
|
|
||||||
</VCardText>
|
|
||||||
</VCard>
|
|
||||||
</VCol>
|
</VCol>
|
||||||
<VCol
|
<VCol
|
||||||
cols="12"
|
cols="12"
|
||||||
@@ -227,26 +188,12 @@ function setStateFilter(s: FormFailureState | 'all') {
|
|||||||
lg="3"
|
lg="3"
|
||||||
class="d-flex"
|
class="d-flex"
|
||||||
>
|
>
|
||||||
<VCard
|
<AppKpiCard
|
||||||
density="compact"
|
icon="tabler-chart-bar"
|
||||||
variant="outlined"
|
icon-color="info"
|
||||||
class="flex-grow-1 w-100 d-flex flex-column"
|
:value="kpis?.total_submissions ?? 0"
|
||||||
>
|
title="Submissions"
|
||||||
<VCardText class="flex-grow-1 d-flex flex-column justify-center">
|
/>
|
||||||
<p class="text-caption text-disabled mb-1 text-no-wrap">
|
|
||||||
Submissions
|
|
||||||
</p>
|
|
||||||
<h5 class="text-h5 mb-0 d-flex align-center">
|
|
||||||
<VIcon
|
|
||||||
icon="tabler-chart-bar"
|
|
||||||
color="info"
|
|
||||||
size="20"
|
|
||||||
class="me-1"
|
|
||||||
/>
|
|
||||||
{{ kpis?.total_submissions ?? 0 }}
|
|
||||||
</h5>
|
|
||||||
</VCardText>
|
|
||||||
</VCard>
|
|
||||||
</VCol>
|
</VCol>
|
||||||
</VRow>
|
</VRow>
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import { flushPromises, mount } from '@vue/test-utils'
|
|||||||
import { beforeEach, describe, expect, it, vi } from 'vitest'
|
import { beforeEach, describe, expect, it, vi } from 'vitest'
|
||||||
|
|
||||||
import FormFailuresTable from '../FormFailuresTable.vue'
|
import FormFailuresTable from '../FormFailuresTable.vue'
|
||||||
|
import AppKpiCard from '@/components/AppKpiCard.vue'
|
||||||
import type { FormFailure, FormFailuresKpis } from '@/types/form-failures'
|
import type { FormFailure, FormFailuresKpis } from '@/types/form-failures'
|
||||||
|
|
||||||
const mockGet = vi.fn()
|
const mockGet = vi.fn()
|
||||||
@@ -66,6 +67,7 @@ const stubs = {
|
|||||||
props: ['modelValue'],
|
props: ['modelValue'],
|
||||||
},
|
},
|
||||||
VIcon: { template: '<i :class="icon"></i>', props: ['icon', 'size', 'color'] },
|
VIcon: { template: '<i :class="icon"></i>', props: ['icon', 'size', 'color'] },
|
||||||
|
VAvatar: { template: '<span class="v-avatar-stub"><slot /></span>', props: ['color', 'size', 'rounded', 'variant'] },
|
||||||
VChip: { template: '<span class="v-chip-stub" :data-color="color"><slot/></span>', props: ['color', 'size', 'variant'] },
|
VChip: { template: '<span class="v-chip-stub" :data-color="color"><slot/></span>', props: ['color', 'size', 'variant'] },
|
||||||
AppTextField: {
|
AppTextField: {
|
||||||
template: '<input :value="modelValue" :placeholder="placeholder" :data-label="label" :type="type" @input="$emit(\'update:modelValue\', $event.target.value)"/>',
|
template: '<input :value="modelValue" :placeholder="placeholder" :data-label="label" :type="type" @input="$emit(\'update:modelValue\', $event.target.value)"/>',
|
||||||
@@ -116,6 +118,7 @@ function mountTable(items: FormFailure[], kpis: FormFailuresKpis = { open: 0, re
|
|||||||
return mount(FormFailuresTable, {
|
return mount(FormFailuresTable, {
|
||||||
props: { scope: 'platform' },
|
props: { scope: 'platform' },
|
||||||
global: {
|
global: {
|
||||||
|
components: { AppKpiCard },
|
||||||
stubs,
|
stubs,
|
||||||
plugins: [[VueQueryPlugin, { queryClient: client }]],
|
plugins: [[VueQueryPlugin, { queryClient: client }]],
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in New Issue
Block a user