Show every status the asset total contains, and what it excludes
All checks were successful
CI / naming (push) Successful in 4s
CI / frontend (push) Successful in 12s
CI / migrations-mysql (push) Successful in 41s
CI / backend (push) Successful in 4m5s

Asked twice what "All assets" covered, which is the signal a label is
underspecified rather than a reader being slow.

The endpoint already counted every status to build its rollup and then returned
two of them, so a reader could see In Use and had no way to learn where the rest
of the total went. It now returns them all, and the panel lists them under the
total - indented and quieter, because they break the total down rather than
adding to it.

Three things this makes visible that were not guessable:

Retired assets are IN the total. Retired is a status on an active record, not
the same as deactivated, and seven of them sit inside this site's 610.

There is an "Inventory" status. I would have hardcoded In Use, In Repair and
Retired and silently dropped it. The rows are built from whatever the API
returns, sorted by count, so a status a site adds appears rather than
disappearing - which matters for sites adopting with their own seed data.

Rows held back by isactive are in NO status bucket, so they cannot be found by
adding the buckets up. That gap is exactly what makes a dashboard total
disagree with a list page, so the count is reported and captioned.

The caption states the counting policy - active records only, dual-bay pairs
counted once - and the dual-path clause renders only when that site toggle is
on, since asserting it unconditionally would be false at a site that has it off.

Full suite 2182, frontend 314.
This commit is contained in:
cproudlock
2026-08-30 15:18:13 -04:00
parent 4c8291628f
commit 511c3ffcee
2 changed files with 74 additions and 13 deletions

View File

@@ -69,14 +69,24 @@
<span class="assets-v">{{ stats.totalassets || 0 }}</span>
</div>
<!-- Status, on one line, and explicitly labelled as status. In
repair is muted at zero rather than given a card of its own to
announce that nothing is wrong. -->
<p class="assets-status">
<span class="assets-inuse">{{ stats.activeassets || 0 }}</span> in use
<span aria-hidden="true"> / </span>
<span :class="{ 'assets-zero': !stats.inrepair }">
{{ stats.inrepair || 0 }} in repair
<!-- Every status the total contains, not just In Use. These were
counted server-side for the rollup and then thrown away, so a
reader could see one number and had no way to learn where the
rest of the total went. Retired assets in particular ARE in
the total, which is not guessable. -->
<div v-for="row in statusrows" :key="row.name" class="assets-row assets-sub">
<span class="assets-k assets-subk">{{ row.name }}</span>
<span class="assets-v assets-subv">{{ row.count }}</span>
</div>
<!-- What the total covers. Asked twice what the number meant, which
is the signal a label is underspecified. -->
<p class="assets-caption">
Active records only<span v-if="stats.dualpathcollapsed">, dual-bay
pairs counted once</span>.
<span v-if="stats.inactiveexcluded">
{{ stats.inactiveexcluded }} deactivated record{{ stats.inactiveexcluded === 1 ? '' : 's' }}
excluded.
</span>
</p>
</section>
@@ -133,6 +143,17 @@ const summaryloaded = ref(false)
// hold - and to what the guest role reaches, when nobody is signed in.
const navitems = ref([])
// Every status in the total, biggest first. Sorted rather than fixed-order
// because the statuses are seed data a site can change - hardcoding "In Use,
// In Repair, Retired" would silently omit a status somebody added.
const statusrows = computed(() => {
const statuses = stats.value.statuses || {}
return Object.keys(statuses)
.map((name) => ({ name, count: statuses[name] }))
.filter((row) => row.count > 0)
.sort((a, b) => b.count - a.count)
})
const openable = computed(
// The dashboard itself is not somewhere to go from the dashboard.
() => navitems.value.filter((item) => item.route && item.route !== '/'))
@@ -224,11 +245,18 @@ span.assets-k { color: var(--text); font-weight: 600; }
border-bottom: none;
}
.assets-status {
margin: 0.5rem 0 0;
font-size: 0.85rem;
/* Status rows sit UNDER the total, indented and quieter, because they break
the total down rather than adding to it. Same weight as the type rows would
read as more things to add up. */
.assets-sub { border-bottom: none; padding: 0.15rem 0 0.15rem 0.75rem; }
.assets-subk { color: var(--text-light); font-size: 0.85rem; }
a.assets-subk:hover { text-decoration: none; }
.assets-subv { font-weight: 500; font-size: 0.85rem; color: var(--text-light); }
.assets-caption {
margin: 0.6rem 0 0;
font-size: 0.78rem;
line-height: 1.45;
color: var(--text-light);
}
.assets-inuse { color: var(--success); font-weight: 600; font-variant-numeric: tabular-nums; }
.assets-zero { color: var(--text-light); }
</style>