Per-type expiry tail on the shopfloor board, and a 2x2 recertification block

This commit is contained in:
2026-08-07 09:28:10 -04:00
parent dd6ccd7a55
commit 2f15610cfd
7 changed files with 277 additions and 25 deletions

View File

@@ -87,6 +87,18 @@
</select>
</label>
<label class="field">
<span>Keep showing after end (minutes)</span>
<input v-model.number="form.gracewindowminutes" type="number"
min="0" max="1440" step="5" />
<small class="muted">
0 means a card leaves the shopfloor board the moment its end time
passes. A higher number keeps it up that long afterwards, marked
RESOLVED - useful for an incident worth acknowledging once it
clears.
</small>
</label>
<label class="field checkbox">
<input v-model="form.splitperemployee" type="checkbox" />
<span>Split one card per employee</span>
@@ -170,9 +182,12 @@ function swatchColor(c) {
}
function expiryLabel(t) {
if (t.expirymode === 'duration' && t.expirydays) return `${t.expirydays} day(s)`
if (t.expirymode === 'dailytime') return `daily @ ${String(t.expiryhour ?? 8).padStart(2, '0')}:00 ET`
return 'none'
const grace = t.gracewindowminutes ?? 0
// The tail only means something next to the rule that ends the card.
const tail = grace > 0 ? ` (+${grace}m resolved)` : ''
if (t.expirymode === 'duration' && t.expirydays) return `${t.expirydays} day(s)${tail}`
if (t.expirymode === 'dailytime') return `daily @ ${String(t.expiryhour ?? 8).padStart(2, '0')}:00 ET${tail}`
return grace > 0 ? `none${tail}` : 'none'
}
async function load() {
@@ -199,6 +214,7 @@ function openNew() {
expirymode: 'none',
expirydays: null,
expiryhour: null,
gracewindowminutes: 0,
isactive: true
}
editing.value = true
@@ -217,6 +233,7 @@ function openEdit(t) {
expirymode: t.expirymode || 'none',
expirydays: t.expirydays ?? null,
expiryhour: t.expiryhour ?? null,
gracewindowminutes: t.gracewindowminutes ?? 0,
isactive: t.isactive !== false
}
editing.value = true