fix(app): equal-height KPI cards on dashboard and form failures
- Stretch row + flex column cards so tiles share height - Form failures: uniform outlined cards; primary border for selection (replacing elevated vs outlined mismatch) - Full-width state toggle with flex-grow buttons and wrap to fix overlap - Responsive KPI columns sm6/lg3 for Form failures Made-with: Cursor
This commit is contained in:
@@ -130,22 +130,28 @@ function setStateFilter(s: FormFailureState | 'all') {
|
|||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<!-- KPI tiles — server-side aggregate (sessie 3c). -->
|
<!-- KPI tiles — server-side aggregate (sessie 3c). -->
|
||||||
<VRow class="mb-4">
|
<VRow
|
||||||
|
class="mb-4"
|
||||||
|
align="stretch"
|
||||||
|
>
|
||||||
<VCol
|
<VCol
|
||||||
cols="12"
|
cols="12"
|
||||||
md="3"
|
sm="6"
|
||||||
|
lg="3"
|
||||||
|
class="d-flex"
|
||||||
>
|
>
|
||||||
<VCard
|
<VCard
|
||||||
density="compact"
|
density="compact"
|
||||||
class="cursor-pointer"
|
variant="outlined"
|
||||||
:variant="stateFilter === 'open' ? 'elevated' : 'outlined'"
|
class="flex-grow-1 w-100 cursor-pointer d-flex flex-column"
|
||||||
|
:class="stateFilter === 'open' ? 'border-opacity-100 border-primary' : ''"
|
||||||
@click="setStateFilter('open')"
|
@click="setStateFilter('open')"
|
||||||
>
|
>
|
||||||
<VCardText>
|
<VCardText class="flex-grow-1 d-flex flex-column justify-center">
|
||||||
<p class="text-caption text-disabled mb-1">
|
<p class="text-caption text-disabled mb-1 text-no-wrap">
|
||||||
Open failures
|
Open failures
|
||||||
</p>
|
</p>
|
||||||
<h5 class="text-h5">
|
<h5 class="text-h5 mb-0 d-flex align-center">
|
||||||
<VIcon
|
<VIcon
|
||||||
icon="tabler-alert-triangle"
|
icon="tabler-alert-triangle"
|
||||||
color="error"
|
color="error"
|
||||||
@@ -159,19 +165,22 @@ function setStateFilter(s: FormFailureState | 'all') {
|
|||||||
</VCol>
|
</VCol>
|
||||||
<VCol
|
<VCol
|
||||||
cols="12"
|
cols="12"
|
||||||
md="3"
|
sm="6"
|
||||||
|
lg="3"
|
||||||
|
class="d-flex"
|
||||||
>
|
>
|
||||||
<VCard
|
<VCard
|
||||||
density="compact"
|
density="compact"
|
||||||
class="cursor-pointer"
|
variant="outlined"
|
||||||
:variant="stateFilter === 'resolved' ? 'elevated' : 'outlined'"
|
class="flex-grow-1 w-100 cursor-pointer d-flex flex-column"
|
||||||
|
:class="stateFilter === 'resolved' ? 'border-opacity-100 border-primary' : ''"
|
||||||
@click="setStateFilter('resolved')"
|
@click="setStateFilter('resolved')"
|
||||||
>
|
>
|
||||||
<VCardText>
|
<VCardText class="flex-grow-1 d-flex flex-column justify-center">
|
||||||
<p class="text-caption text-disabled mb-1">
|
<p class="text-caption text-disabled mb-1 text-no-wrap">
|
||||||
Opgelost (30d)
|
Opgelost (30d)
|
||||||
</p>
|
</p>
|
||||||
<h5 class="text-h5">
|
<h5 class="text-h5 mb-0 d-flex align-center">
|
||||||
<VIcon
|
<VIcon
|
||||||
icon="tabler-check"
|
icon="tabler-check"
|
||||||
color="success"
|
color="success"
|
||||||
@@ -185,19 +194,22 @@ function setStateFilter(s: FormFailureState | 'all') {
|
|||||||
</VCol>
|
</VCol>
|
||||||
<VCol
|
<VCol
|
||||||
cols="12"
|
cols="12"
|
||||||
md="3"
|
sm="6"
|
||||||
|
lg="3"
|
||||||
|
class="d-flex"
|
||||||
>
|
>
|
||||||
<VCard
|
<VCard
|
||||||
density="compact"
|
density="compact"
|
||||||
class="cursor-pointer"
|
variant="outlined"
|
||||||
:variant="stateFilter === 'dismissed' ? 'elevated' : 'outlined'"
|
class="flex-grow-1 w-100 cursor-pointer d-flex flex-column"
|
||||||
|
:class="stateFilter === 'dismissed' ? 'border-opacity-100 border-primary' : ''"
|
||||||
@click="setStateFilter('dismissed')"
|
@click="setStateFilter('dismissed')"
|
||||||
>
|
>
|
||||||
<VCardText>
|
<VCardText class="flex-grow-1 d-flex flex-column justify-center">
|
||||||
<p class="text-caption text-disabled mb-1">
|
<p class="text-caption text-disabled mb-1 text-no-wrap">
|
||||||
Dismissed (30d)
|
Dismissed (30d)
|
||||||
</p>
|
</p>
|
||||||
<h5 class="text-h5">
|
<h5 class="text-h5 mb-0 d-flex align-center">
|
||||||
<VIcon
|
<VIcon
|
||||||
icon="tabler-x"
|
icon="tabler-x"
|
||||||
color="warning"
|
color="warning"
|
||||||
@@ -211,17 +223,20 @@ function setStateFilter(s: FormFailureState | 'all') {
|
|||||||
</VCol>
|
</VCol>
|
||||||
<VCol
|
<VCol
|
||||||
cols="12"
|
cols="12"
|
||||||
md="3"
|
sm="6"
|
||||||
|
lg="3"
|
||||||
|
class="d-flex"
|
||||||
>
|
>
|
||||||
<VCard
|
<VCard
|
||||||
density="compact"
|
density="compact"
|
||||||
variant="outlined"
|
variant="outlined"
|
||||||
|
class="flex-grow-1 w-100 d-flex flex-column"
|
||||||
>
|
>
|
||||||
<VCardText>
|
<VCardText class="flex-grow-1 d-flex flex-column justify-center">
|
||||||
<p class="text-caption text-disabled mb-1">
|
<p class="text-caption text-disabled mb-1 text-no-wrap">
|
||||||
Submissions
|
Submissions
|
||||||
</p>
|
</p>
|
||||||
<h5 class="text-h5">
|
<h5 class="text-h5 mb-0 d-flex align-center">
|
||||||
<VIcon
|
<VIcon
|
||||||
icon="tabler-chart-bar"
|
icon="tabler-chart-bar"
|
||||||
color="info"
|
color="info"
|
||||||
@@ -254,12 +269,10 @@ function setStateFilter(s: FormFailureState | 'all') {
|
|||||||
<VCard>
|
<VCard>
|
||||||
<VCardText>
|
<VCardText>
|
||||||
<VRow>
|
<VRow>
|
||||||
<VCol
|
<VCol cols="12">
|
||||||
cols="12"
|
|
||||||
md="6"
|
|
||||||
>
|
|
||||||
<VBtnToggle
|
<VBtnToggle
|
||||||
:model-value="stateFilter"
|
:model-value="stateFilter"
|
||||||
|
class="w-100 flex-wrap"
|
||||||
divided
|
divided
|
||||||
density="comfortable"
|
density="comfortable"
|
||||||
mandatory
|
mandatory
|
||||||
@@ -269,14 +282,16 @@ function setStateFilter(s: FormFailureState | 'all') {
|
|||||||
v-for="opt in stateOptions"
|
v-for="opt in stateOptions"
|
||||||
:key="opt.value"
|
:key="opt.value"
|
||||||
:value="opt.value"
|
:value="opt.value"
|
||||||
|
class="flex-grow-1"
|
||||||
|
style="min-inline-size: 0"
|
||||||
>
|
>
|
||||||
{{ opt.title }}
|
<span class="text-truncate">{{ opt.title }}</span>
|
||||||
</VBtn>
|
</VBtn>
|
||||||
</VBtnToggle>
|
</VBtnToggle>
|
||||||
</VCol>
|
</VCol>
|
||||||
<VCol
|
<VCol
|
||||||
cols="12"
|
cols="12"
|
||||||
md="6"
|
md="12"
|
||||||
>
|
>
|
||||||
<AppTextField
|
<AppTextField
|
||||||
v-model="search"
|
v-model="search"
|
||||||
|
|||||||
@@ -24,16 +24,17 @@ const stats = [
|
|||||||
</VCardText>
|
</VCardText>
|
||||||
</VCard>
|
</VCard>
|
||||||
|
|
||||||
<VRow>
|
<VRow align="stretch">
|
||||||
<VCol
|
<VCol
|
||||||
v-for="stat in stats"
|
v-for="stat in stats"
|
||||||
:key="stat.title"
|
:key="stat.title"
|
||||||
cols="12"
|
cols="12"
|
||||||
sm="6"
|
sm="6"
|
||||||
md="3"
|
md="3"
|
||||||
|
class="d-flex"
|
||||||
>
|
>
|
||||||
<VCard>
|
<VCard class="flex-grow-1 w-100 d-flex flex-column">
|
||||||
<VCardText class="d-flex align-center gap-x-4">
|
<VCardText class="d-flex align-center gap-x-4 flex-grow-1">
|
||||||
<VAvatar
|
<VAvatar
|
||||||
:color="stat.color"
|
:color="stat.color"
|
||||||
variant="tonal"
|
variant="tonal"
|
||||||
|
|||||||
Reference in New Issue
Block a user