Paint each board row in its own notification type's colour
This commit is contained in:
@@ -45,13 +45,17 @@
|
|||||||
|
|
||||||
<!-- Carousel - one card at a time, rotating -->
|
<!-- Carousel - one card at a time, rotating -->
|
||||||
<section v-else-if="group.displaystyle === 'carousel'" class="recognition-section">
|
<section v-else-if="group.displaystyle === 'carousel'" class="recognition-section">
|
||||||
<div class="section-title recognition">{{ group.typename }}</div>
|
<div
|
||||||
|
class="section-title recognition"
|
||||||
|
:style="{ backgroundColor: getTypeColor(group.typecolor), color: textOn(group.typecolor) }"
|
||||||
|
>{{ group.typename }}</div>
|
||||||
<div class="recognition-carousel">
|
<div class="recognition-carousel">
|
||||||
<div
|
<div
|
||||||
v-for="(rec, idx) in group.items"
|
v-for="(rec, idx) in group.items"
|
||||||
:key="`${rec.notificationid}-${rec.employeesso}`"
|
:key="`${rec.notificationid}-${rec.employeesso}`"
|
||||||
class="recognition-card"
|
class="recognition-card"
|
||||||
:class="{ active: idx === carouselIndex(group) }"
|
:class="{ active: idx === carouselIndex(group) }"
|
||||||
|
:style="{ '--accent': getTypeColor(rec.typecolor) }"
|
||||||
>
|
>
|
||||||
<!-- A type that names no employee is a message, not a person:
|
<!-- A type that names no employee is a message, not a person:
|
||||||
no photo frame, no empty name line. -->
|
no photo frame, no empty name line. -->
|
||||||
@@ -82,7 +86,10 @@
|
|||||||
|
|
||||||
<!-- Grid - a row of tiles, cycling a page at a time -->
|
<!-- Grid - a row of tiles, cycling a page at a time -->
|
||||||
<section v-else class="recert-section">
|
<section v-else class="recert-section">
|
||||||
<div class="section-title recert-title">
|
<div
|
||||||
|
class="section-title recert-title"
|
||||||
|
:style="{ backgroundColor: getTypeColor(group.typecolor), color: textOn(group.typecolor) }"
|
||||||
|
>
|
||||||
<span>{{ group.typename }} ({{ group.items.length }})</span>
|
<span>{{ group.typename }} ({{ group.items.length }})</span>
|
||||||
<span v-if="gridRangeLabel(group)" class="recert-range">{{ gridRangeLabel(group) }}</span>
|
<span v-if="gridRangeLabel(group)" class="recert-range">{{ gridRangeLabel(group) }}</span>
|
||||||
</div>
|
</div>
|
||||||
@@ -99,6 +106,7 @@
|
|||||||
:key="`grid-${rec.notificationid}-${rec.employeesso}`"
|
:key="`grid-${rec.notificationid}-${rec.employeesso}`"
|
||||||
class="recert-tile"
|
class="recert-tile"
|
||||||
:class="{ 'message-tile': !hasEmployee(rec) }"
|
:class="{ 'message-tile': !hasEmployee(rec) }"
|
||||||
|
:style="{ '--accent': getTypeColor(rec.typecolor) }"
|
||||||
>
|
>
|
||||||
<template v-if="hasEmployee(rec)">
|
<template v-if="hasEmployee(rec)">
|
||||||
<img
|
<img
|
||||||
@@ -265,6 +273,10 @@ const styledGroups = computed(() => {
|
|||||||
key,
|
key,
|
||||||
typename: heading,
|
typename: heading,
|
||||||
displaystyle: n.displaystyle,
|
displaystyle: n.displaystyle,
|
||||||
|
// Heading colour comes from the first type in the row. A shared
|
||||||
|
// category is one heading, so it can only carry one colour; the
|
||||||
|
// individual cards below still wear their own type's colour.
|
||||||
|
typecolor: n.typecolor,
|
||||||
items: []
|
items: []
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -453,6 +465,19 @@ function getTypeColor(typecolor) {
|
|||||||
return aliases[typecolor] || typecolor || '#14abef'
|
return aliases[typecolor] || typecolor || '#14abef'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Text colour for a heading painted an arbitrary type colour. Gold needs dark
|
||||||
|
// text, navy needs white, and a site picks its own hexes - so this is computed
|
||||||
|
// rather than a per-colour rule.
|
||||||
|
function textOn(backgroundcolor) {
|
||||||
|
const hex = getTypeColor(backgroundcolor).replace('#', '')
|
||||||
|
if (hex.length < 6) return '#fff'
|
||||||
|
const r = parseInt(hex.slice(0, 2), 16)
|
||||||
|
const g = parseInt(hex.slice(2, 4), 16)
|
||||||
|
const b = parseInt(hex.slice(4, 6), 16)
|
||||||
|
// Rec. 709 luma, the usual quick contrast test.
|
||||||
|
return (0.2126 * r + 0.7152 * g + 0.0722 * b) > 150 ? '#231b00' : '#fff'
|
||||||
|
}
|
||||||
|
|
||||||
function getSectionClass(notifications) {
|
function getSectionClass(notifications) {
|
||||||
// Use danger color if any active incidents
|
// Use danger color if any active incidents
|
||||||
const hasIncident = notifications.some(n => n.typecolor === 'danger' && !n.resolved)
|
const hasIncident = notifications.some(n => n.typecolor === 'danger' && !n.resolved)
|
||||||
@@ -602,6 +627,7 @@ function handlePhotoError(e) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.section-title.recognition {
|
.section-title.recognition {
|
||||||
|
/* Fallback only - the real colour is the type's, set inline. */
|
||||||
background: #ffc107;
|
background: #ffc107;
|
||||||
color: #3a2e00;
|
color: #3a2e00;
|
||||||
}
|
}
|
||||||
@@ -612,6 +638,7 @@ function handlePhotoError(e) {
|
|||||||
margin-bottom: 25px;
|
margin-bottom: 25px;
|
||||||
}
|
}
|
||||||
.section-title.recert-title {
|
.section-title.recert-title {
|
||||||
|
/* Fallback only - the real colour is the type's, set inline. */
|
||||||
background: #0d6efd;
|
background: #0d6efd;
|
||||||
color: #fff;
|
color: #fff;
|
||||||
display: flex;
|
display: flex;
|
||||||
@@ -638,8 +665,8 @@ function handlePhotoError(e) {
|
|||||||
gap: 14px;
|
gap: 14px;
|
||||||
}
|
}
|
||||||
.recert-tile {
|
.recert-tile {
|
||||||
background: linear-gradient(135deg, #1e3a5f 0%, #0d2137 100%);
|
background: linear-gradient(135deg, #16233b 0%, #0d2137 100%);
|
||||||
border: 2px solid #0d6efd;
|
border: 2px solid var(--accent, #0d6efd);
|
||||||
border-radius: 10px;
|
border-radius: 10px;
|
||||||
padding: 14px 10px;
|
padding: 14px 10px;
|
||||||
display: flex;
|
display: flex;
|
||||||
@@ -653,7 +680,7 @@ function handlePhotoError(e) {
|
|||||||
height: 90px;
|
height: 90px;
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
object-fit: cover;
|
object-fit: cover;
|
||||||
border: 3px solid #0d6efd;
|
border: 3px solid var(--accent, #0d6efd);
|
||||||
background: #1a1a2e;
|
background: #1a1a2e;
|
||||||
}
|
}
|
||||||
.recert-photo.ge-logo-fallback {
|
.recert-photo.ge-logo-fallback {
|
||||||
@@ -713,8 +740,8 @@ function handlePhotoError(e) {
|
|||||||
top: 0;
|
top: 0;
|
||||||
left: 0;
|
left: 0;
|
||||||
right: 0;
|
right: 0;
|
||||||
background: linear-gradient(135deg, #4a3a0a 0%, #2a2200 100%);
|
background: linear-gradient(135deg, #2b2718 0%, #1d1a10 100%);
|
||||||
border: 3px solid #ffc107;
|
border: 3px solid var(--accent, #ffc107);
|
||||||
border-radius: 12px;
|
border-radius: 12px;
|
||||||
padding: 20px 25px;
|
padding: 20px 25px;
|
||||||
display: flex;
|
display: flex;
|
||||||
@@ -736,7 +763,7 @@ function handlePhotoError(e) {
|
|||||||
height: 140px;
|
height: 140px;
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
object-fit: cover;
|
object-fit: cover;
|
||||||
border: 4px solid #ffc107;
|
border: 4px solid var(--accent, #ffc107);
|
||||||
background: #1a1a2e;
|
background: #1a1a2e;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user