style(shopfloor): borders back, real drop indicator, logo demoted

Three concrete fixes based on user feedback:

1. Card borders restored — every card / panel / KPI tile / queue row /
   bake row / team card now has a thin 1px border (var(--bs-border-color))
   ON TOP of the soft shadow. That's the classic SaaS card treatment
   and solves the "jobs have no borders, they blend together" problem.
   Hover lifts the border to the accent colour (~45% mix) so cards
   feel responsive.

2. Plant Overview drop-zone indicator restored.
   - Column body gets inset outline + tinted background on dragover
     (.o_fp_drop_target class already added by onColDragOver in JS)
   - A 56px dashed placeholder bar appears at the bottom of the column
     via ::after on the drop target. That's the "here's where the card
     will land" visual the user remembered.
   - Dragged card gets scale(0.97) + slight rotation + opacity 0.4 for
     a clearer "I'm picking this up" feedback.

3. Customer logo removed from Plant Overview cards.
   The big company logo at the top of each kanban card was wasting
   space. Customer NAME still shows (in bold, full-width, with text-
   ellipsis), step badge pill stays on the right. No more wasted
   real estate on visuals nobody looks at twice.

Extra polish while in there:
   - Section headers (Tablet + Manager) now have a coloured icon badge
     — a rounded square 36×36 with tinted background + accent-coloured
     icon next to the H3 title. Adds visual weight without noise.
   - Panel head gets a 1px bottom divider.
   - Manager panels tint the icon badge per panel tone (amber for
     Unassigned, green for In Progress, blue for Team).
   - Header action buttons (Tablet scan/picker, Manager refresh/mode)
     get proper borders + hover state.
   - State dividers on bake/gate/hold rows preserved as inset shadows.

Verified: bundle rebuilt at /web/assets/278b43c/web.assets_backend.min.css
(1.45MB, id 1930). All key classes present: o_fp_drop_target,
o_fp_dragging, o_fp_po_parts_bar, o_fp_po_parts_fill, section-header
icon badges. Zero SCSS warnings.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
gsinghpal
2026-04-18 19:01:04 -04:00
parent 067d1f01c8
commit 83a999afad
4 changed files with 305 additions and 111 deletions

View File

@@ -87,22 +87,22 @@
min-width: 240px;
min-height: $fp-touch-min;
padding: $fp-space-2 $fp-space-4;
border: none;
border: 1px solid var(--bs-border-color);
border-radius: $fp-radius-md;
background-color: $fp-card;
color: $fp-ink;
font-size: $fp-text-base;
box-shadow: $fp-elev-1;
cursor: pointer;
transition: box-shadow $fp-dur $fp-ease;
transition: box-shadow $fp-dur $fp-ease, border-color $fp-dur $fp-ease;
&:focus { @include fp-focus-ring; }
&:focus { @include fp-focus-ring; border-color: $fp-accent; }
@media (max-width: 600px) { min-width: 0; width: 100%; }
}
.o_fp_scan_toggle {
min-height: $fp-touch-min;
padding: 0 $fp-space-5;
border: none;
border: 1px solid var(--bs-border-color);
border-radius: $fp-radius-md;
background-color: $fp-card;
color: $fp-ink;
@@ -110,9 +110,16 @@
font-size: $fp-text-base;
cursor: pointer;
box-shadow: $fp-elev-1;
transition: transform $fp-dur-fast $fp-ease, box-shadow $fp-dur $fp-ease;
transition: transform $fp-dur-fast $fp-ease,
box-shadow $fp-dur $fp-ease,
border-color $fp-dur $fp-ease;
@include fp-hover-only { &:hover { box-shadow: $fp-elev-2; } }
@include fp-hover-only {
&:hover {
box-shadow: $fp-elev-2;
border-color: color-mix(in srgb, #{$fp-accent} 45%, var(--bs-border-color));
}
}
&:active { transform: scale(0.97); }
}
@@ -199,13 +206,20 @@
.o_fp_kpi {
position: relative;
padding: $fp-space-5;
border: 1px solid var(--bs-border-color);
border-radius: $fp-radius-lg;
background-color: $fp-card;
box-shadow: $fp-elev-1;
display: flex; flex-direction: column; gap: $fp-space-2;
transition: transform $fp-dur $fp-ease, box-shadow $fp-dur $fp-ease;
@include fp-hover-only { &:hover { transform: translateY(-2px); box-shadow: $fp-elev-2; } }
@include fp-hover-only {
&:hover {
transform: translateY(-2px);
box-shadow: $fp-elev-2;
border-color: color-mix(in srgb, #{$fp-accent} 30%, var(--bs-border-color));
}
}
> .fa {
font-size: 1.1rem;
@@ -319,23 +333,41 @@
// Panel (section container)
// -------------------------------------------------------------------------
.o_fp_panel {
@include fp-card($fp-elev-1);
background-color: $fp-card;
border: 1px solid var(--bs-border-color);
border-radius: $fp-radius-lg;
box-shadow: $fp-elev-1;
padding: $fp-space-5;
@media (max-width: 600px) { padding: $fp-space-4; }
}
.o_fp_panel_head {
display: flex;
justify-content: space-between;
align-items: baseline;
align-items: center;
margin-bottom: $fp-space-4;
padding-bottom: $fp-space-3;
border-bottom: 1px solid var(--bs-border-color);
h3 {
font-size: $fp-text-lg;
font-weight: $fp-weight-bold;
letter-spacing: -0.01em;
margin: 0;
display: inline-flex; align-items: center; gap: $fp-space-2;
display: inline-flex; align-items: center; gap: $fp-space-3;
color: $fp-ink;
// Icon badge — rounded square with tinted background.
// Gives the panel head visual weight without being loud.
> .fa {
display: inline-flex;
align-items: center;
justify-content: center;
width: 36px; height: 36px;
border-radius: $fp-radius-sm;
background-color: color-mix(in srgb, #{$fp-accent} 12%, transparent);
color: $fp-accent;
font-size: 1rem;
}
}
}
.o_fp_panel_count {
@@ -379,15 +411,20 @@
align-items: center;
gap: $fp-space-3;
padding: $fp-space-3 $fp-space-4;
border: 1px solid var(--bs-border-color);
border-radius: $fp-radius-md;
background-color: $fp-page;
background-color: $fp-card;
min-height: 64px;
transition: background-color $fp-dur $fp-ease, transform $fp-dur-fast $fp-ease;
transition: background-color $fp-dur $fp-ease,
border-color $fp-dur $fp-ease,
box-shadow $fp-dur $fp-ease,
transform $fp-dur-fast $fp-ease;
@include fp-hover-only {
&:hover {
background-color: color-mix(in srgb, #{$fp-accent} 6%, $fp-page);
transform: translateX(2px);
background-color: color-mix(in srgb, #{$fp-accent} 4%, $fp-card);
border-color: color-mix(in srgb, #{$fp-accent} 45%, var(--bs-border-color));
box-shadow: $fp-elev-2;
}
}
@media (max-width: 600px) {
@@ -449,15 +486,21 @@
}
.o_fp_tile {
padding: $fp-space-4;
border: 1px solid var(--bs-border-color);
border-radius: $fp-radius-md;
background-color: $fp-page;
background-color: $fp-card;
cursor: pointer;
transition: transform $fp-dur-fast $fp-ease, background-color $fp-dur $fp-ease;
transition: transform $fp-dur-fast $fp-ease,
background-color $fp-dur $fp-ease,
border-color $fp-dur $fp-ease,
box-shadow $fp-dur $fp-ease;
@include fp-hover-only {
&:hover {
transform: translateY(-1px);
background-color: color-mix(in srgb, #{$fp-accent} 6%, $fp-page);
background-color: color-mix(in srgb, #{$fp-accent} 4%, $fp-card);
border-color: color-mix(in srgb, #{$fp-accent} 45%, var(--bs-border-color));
box-shadow: $fp-elev-2;
}
}
}
@@ -507,11 +550,15 @@
align-items: center;
gap: $fp-space-3;
padding: $fp-space-3 $fp-space-4;
border: 1px solid var(--bs-border-color);
border-radius: $fp-radius-md;
background-color: $fp-page;
background-color: $fp-card;
min-height: 64px;
transition: box-shadow $fp-dur $fp-ease, border-color $fp-dur $fp-ease;
// State-coloured left bar (6px wide, rounded)
@include fp-hover-only { &:hover { box-shadow: $fp-elev-2; } }
// State-coloured left bar (inset box-shadow so it lives inside the border)
box-shadow: inset 4px 0 0 0 $fp-ink-faint;
&[data-state="awaiting_bake"], &[data-state="pending"] {
box-shadow: inset 4px 0 0 0 $fp-warn;
@@ -522,6 +569,7 @@
&[data-state="missed_window"], &[data-state="fail"], &[data-state="on_hold"] {
box-shadow: inset 4px 0 0 0 $fp-bad;
background-color: fp-wash(--bs-danger, 5%);
border-color: color-mix(in srgb, #{$fp-bad} 35%, var(--bs-border-color));
}
&[data-state="baked"], &[data-state="pass"] {
box-shadow: inset 4px 0 0 0 $fp-ok;

View File

@@ -84,16 +84,24 @@
padding: 0 $fp-space-4;
border-radius: $fp-radius-md;
font-weight: $fp-weight-semibold;
border: none;
border: 1px solid var(--bs-border-color);
background-color: $fp-card;
color: $fp-ink;
box-shadow: $fp-elev-1;
transition: transform $fp-dur-fast $fp-ease, box-shadow $fp-dur $fp-ease;
@include fp-hover-only { &:hover { box-shadow: $fp-elev-2; } }
transition: transform $fp-dur-fast $fp-ease,
box-shadow $fp-dur $fp-ease,
border-color $fp-dur $fp-ease;
@include fp-hover-only {
&:hover {
box-shadow: $fp-elev-2;
border-color: color-mix(in srgb, #{$fp-accent} 45%, var(--bs-border-color));
}
}
&:active { transform: scale(0.97); }
&.btn-primary {
background-color: $fp-accent;
border-color: $fp-accent;
color: var(--o-we-text-on-action, #fff);
}
}
@@ -141,13 +149,20 @@
.o_fp_kpi {
position: relative;
padding: $fp-space-5;
border: 1px solid var(--bs-border-color);
border-radius: $fp-radius-lg;
background-color: $fp-card;
box-shadow: $fp-elev-1;
display: flex; flex-direction: column; gap: $fp-space-2;
transition: transform $fp-dur $fp-ease, box-shadow $fp-dur $fp-ease;
@include fp-hover-only { &:hover { transform: translateY(-2px); box-shadow: $fp-elev-2; } }
@include fp-hover-only {
&:hover {
transform: translateY(-2px);
box-shadow: $fp-elev-2;
border-color: color-mix(in srgb, #{$fp-accent} 30%, var(--bs-border-color));
}
}
> .fa { font-size: 1.1rem; color: $fp-ink-mute; }
.o_fp_kpi_value {
@@ -210,23 +225,37 @@
// Panels
// -------------------------------------------------------------------------
.o_fp_panel {
@include fp-card($fp-elev-1);
background-color: $fp-card;
border: 1px solid var(--bs-border-color);
border-radius: $fp-radius-lg;
box-shadow: $fp-elev-1;
padding: $fp-space-5;
@media (max-width: 600px) { padding: $fp-space-4; }
}
.o_fp_panel_head {
display: flex;
justify-content: space-between;
align-items: baseline;
align-items: center;
margin-bottom: $fp-space-4;
padding-bottom: $fp-space-3;
border-bottom: 1px solid var(--bs-border-color);
h3 {
font-size: $fp-text-lg;
font-weight: $fp-weight-bold;
letter-spacing: -0.01em;
margin: 0;
display: inline-flex; align-items: center; gap: $fp-space-2;
display: inline-flex; align-items: center; gap: $fp-space-3;
color: $fp-ink;
> .fa {
display: inline-flex; align-items: center; justify-content: center;
width: 36px; height: 36px;
border-radius: $fp-radius-sm;
font-size: 1rem;
background-color: color-mix(in srgb, #{$fp-accent} 12%, transparent);
color: $fp-accent;
}
}
}
.o_fp_panel_count {
@@ -238,18 +267,19 @@
border-radius: $fp-radius-pill;
}
// Panel accent by tone — a single coloured dot next to the title
.o_fp_panel_unassigned .o_fp_panel_head h3::before,
.o_fp_panel_active .o_fp_panel_head h3::before,
.o_fp_panel_team .o_fp_panel_head h3::before {
content: "";
width: 10px; height: 10px;
border-radius: 50%;
margin-right: $fp-space-1;
// Per-panel icon tints (amber / green / blue)
.o_fp_panel_unassigned .o_fp_panel_head h3 > .fa {
background-color: color-mix(in srgb, #{$fp-warn} 14%, transparent);
color: $fp-warn;
}
.o_fp_panel_active .o_fp_panel_head h3 > .fa {
background-color: color-mix(in srgb, #{$fp-ok} 14%, transparent);
color: $fp-ok;
}
.o_fp_panel_team .o_fp_panel_head h3 > .fa {
background-color: color-mix(in srgb, #{$fp-info} 14%, transparent);
color: $fp-info;
}
.o_fp_panel_unassigned .o_fp_panel_head h3::before { background-color: $fp-warn; }
.o_fp_panel_active .o_fp_panel_head h3::before { background-color: $fp-ok; }
.o_fp_panel_team .o_fp_panel_head h3::before { background-color: $fp-info; }
// -------------------------------------------------------------------------
@@ -278,16 +308,26 @@
}
.o_fp_mgr_card {
position: relative;
background-color: $fp-page;
background-color: $fp-card;
border: 1px solid var(--bs-border-color);
border-radius: $fp-radius-md;
overflow: hidden;
transition: transform $fp-dur-fast $fp-ease, box-shadow $fp-dur $fp-ease;
transition: transform $fp-dur-fast $fp-ease,
box-shadow $fp-dur $fp-ease,
border-color $fp-dur $fp-ease;
@include fp-hover-only { &:hover { box-shadow: $fp-elev-1; transform: translateX(2px); } }
@include fp-hover-only {
&:hover {
border-color: color-mix(in srgb, #{$fp-accent} 45%, var(--bs-border-color));
box-shadow: $fp-elev-2;
transform: translateY(-1px);
}
}
// Priority stripe (4px) on the left — only when priority is set
&[data-priority="2"] {
background-color: color-mix(in srgb, #{$fp-bad} 4%, $fp-page);
background-color: color-mix(in srgb, #{$fp-bad} 4%, $fp-card);
border-color: color-mix(in srgb, #{$fp-bad} 35%, var(--bs-border-color));
&::before {
content: "";
position: absolute; left: 0; top: 0; bottom: 0;
@@ -336,6 +376,7 @@
align-items: center;
padding: $fp-space-2 $fp-space-3;
background-color: $fp-card;
border: 1px solid var(--bs-border-color);
border-radius: $fp-radius-sm;
font-size: $fp-text-sm;
@@ -360,12 +401,12 @@
min-width: 140px; max-width: 220px;
min-height: 40px;
padding: 0 $fp-space-3;
border: none;
border: 1px solid var(--bs-border-color);
border-radius: $fp-radius-sm;
background-color: $fp-card-soft;
background-color: $fp-card;
color: $fp-ink;
font-size: $fp-text-sm;
&:focus { @include fp-focus-ring; }
&:focus { @include fp-focus-ring; border-color: $fp-accent; }
}
.o_fp_mgr_wo_row .btn {
min-height: 40px;
@@ -413,16 +454,21 @@
align-items: center;
gap: $fp-space-3;
padding: $fp-space-3 $fp-space-4;
border: 1px solid var(--bs-border-color);
border-radius: $fp-radius-md;
background-color: $fp-page;
background-color: $fp-card;
cursor: pointer;
min-height: 72px;
transition: transform $fp-dur-fast $fp-ease, background-color $fp-dur $fp-ease;
transition: transform $fp-dur-fast $fp-ease,
background-color $fp-dur $fp-ease,
border-color $fp-dur $fp-ease,
box-shadow $fp-dur $fp-ease;
@include fp-hover-only {
&:hover {
background-color: color-mix(in srgb, #{$fp-accent} 6%, $fp-page);
transform: translateX(2px);
background-color: color-mix(in srgb, #{$fp-accent} 4%, $fp-card);
border-color: color-mix(in srgb, #{$fp-accent} 45%, var(--bs-border-color));
box-shadow: $fp-elev-2;
}
}
}

View File

@@ -2,8 +2,9 @@
// Fusion Plating — Plant Overview (Kanban)
// Copyright 2026 Nexa Systems Inc. · License OPL-1
//
// Kanban of work orders grouped by work centre. Clean, shadow-based,
// no heavy chrome. Shared tokens from _fp_shopfloor_tokens.scss.
// Kanban of work orders grouped by work centre. Cards have BOTH a
// subtle border and a soft shadow so they feel substantial, drop zones
// show a clear dashed placeholder when a card is dragged over them.
// =============================================================================
@@ -36,7 +37,6 @@
background-color: $fp-page;
.o_fp_po_header_left { display: flex; align-items: center; }
.o_fp_po_title {
font-size: $fp-text-xl;
font-weight: $fp-weight-bold;
@@ -44,14 +44,8 @@
margin: 0;
color: $fp-ink;
}
.o_fp_po_refresh_ts {
font-size: $fp-text-xs; color: $fp-ink-mute;
}
.o_fp_po_header_right {
display: flex; align-items: center; gap: $fp-space-2;
}
.o_fp_po_refresh_ts { font-size: $fp-text-xs; color: $fp-ink-mute; }
.o_fp_po_header_right { display: flex; align-items: center; gap: $fp-space-2; }
@media (max-width: 600px) {
padding: $fp-space-4;
@@ -69,22 +63,24 @@
.o_fp_po_search_icon {
position: absolute; left: 14px;
color: $fp-ink-mute;
pointer-events: none;
color: $fp-ink-mute; pointer-events: none;
}
.o_fp_po_search_input {
padding: 0 $fp-space-4 0 $fp-space-7;
min-height: $fp-touch-min;
border: none;
border: 1px solid var(--bs-border-color);
border-radius: $fp-radius-md;
background-color: $fp-card;
color: $fp-ink;
box-shadow: $fp-elev-1;
width: 260px;
font-size: $fp-text-base;
transition: box-shadow $fp-dur $fp-ease;
transition: box-shadow $fp-dur $fp-ease, border-color $fp-dur $fp-ease;
&:focus { @include fp-focus-ring; }
&:focus {
@include fp-focus-ring;
border-color: $fp-accent;
}
@media (max-width: 600px) { width: 100%; }
}
.o_fp_po_search_clear {
@@ -99,7 +95,7 @@
.o_fp_po_refresh_btn {
width: $fp-touch-min; height: $fp-touch-min;
display: flex; align-items: center; justify-content: center;
border: none;
border: 1px solid var(--bs-border-color);
border-radius: $fp-radius-md;
background-color: $fp-card;
color: $fp-ink;
@@ -120,9 +116,7 @@
min-height: 0;
align-items: flex-start;
@media (max-width: 900px) {
padding: 0 $fp-space-4 $fp-space-4;
}
@media (max-width: 900px) { padding: 0 $fp-space-4 $fp-space-4; }
@media (max-width: 600px) {
flex-direction: column;
padding: 0 $fp-space-3 $fp-space-3;
@@ -137,7 +131,8 @@
max-width: 340px;
display: flex;
flex-direction: column;
background-color: $fp-card;
background-color: $fp-card-soft;
border: 1px solid var(--bs-border-color);
border-radius: $fp-radius-lg;
box-shadow: $fp-elev-1;
max-height: calc(100vh - 180px);
@@ -152,7 +147,9 @@
.o_fp_po_col_header {
display: flex; align-items: center; justify-content: space-between;
padding: $fp-space-4 $fp-space-4 $fp-space-3;
padding: $fp-space-4;
border-bottom: 1px solid var(--bs-border-color);
background-color: $fp-card;
.o_fp_po_col_name {
font-weight: $fp-weight-bold;
@@ -163,80 +160,179 @@
}
.o_fp_po_col_count {
font-weight: $fp-weight-semibold;
font-size: 0.75rem;
font-size: 0.72rem;
padding: 2px 10px;
border-radius: $fp-radius-pill;
background-color: $fp-card-soft;
color: $fp-ink-mute;
background-color: color-mix(in srgb, #{$fp-accent} 14%, transparent);
color: $fp-accent;
min-width: 24px; text-align: center;
}
}
.o_fp_po_col_body {
overflow-y: auto;
padding: $fp-space-2 $fp-space-3 $fp-space-3;
padding: $fp-space-3;
flex: 1;
transition: background-color $fp-dur $fp-ease;
border-radius: 0 0 $fp-radius-lg $fp-radius-lg;
// Drop zone highlight — solid tinted background + dashed outline
// so the manager sees EXACTLY where the card will land.
&.o_fp_drop_target {
background-color: color-mix(in srgb, #{$fp-accent} 8%, transparent);
box-shadow: inset 0 0 0 2px color-mix(in srgb, #{$fp-accent} 45%, transparent);
// Placeholder bar at the bottom of the list — that's where
// the card will drop when released.
&::after {
content: "";
display: block;
height: 56px;
margin-top: $fp-space-2;
border: 2px dashed color-mix(in srgb, #{$fp-accent} 55%, transparent);
border-radius: $fp-radius-md;
background-color: color-mix(in srgb, #{$fp-accent} 6%, transparent);
}
}
}
.o_fp_po_no_cards {
padding: $fp-space-5 $fp-space-3;
text-align: center;
color: $fp-ink-mute;
font-size: $fp-text-sm;
}
// ---------- Card ------------------------------------------------------------
.o_fp_po_card {
background-color: $fp-page;
position: relative;
background-color: $fp-card;
border: 1px solid var(--bs-border-color);
border-radius: $fp-radius-md;
padding: $fp-space-3 $fp-space-4;
margin-bottom: $fp-space-2;
cursor: grab;
box-shadow: $fp-elev-1;
transition: transform $fp-dur-fast $fp-ease,
box-shadow $fp-dur $fp-ease,
opacity $fp-dur $fp-ease,
background-color $fp-dur $fp-ease;
border-color $fp-dur $fp-ease;
@include fp-hover-only {
&:hover {
background-color: $fp-card;
border-color: color-mix(in srgb, #{$fp-accent} 45%, var(--bs-border-color));
box-shadow: $fp-elev-2;
transform: translateY(-2px);
transform: translateY(-1px);
}
}
&:active, &.o_fp_po_dragging {
&:active, &.o_fp_dragging {
cursor: grabbing;
opacity: 0.6;
opacity: 0.4;
transform: scale(0.97) rotate(-1deg);
box-shadow: $fp-elev-3;
}
// Priority left bar — only visible when a priority is set
position: relative; overflow: hidden;
&[data-priority="2"] {
background-color: color-mix(in srgb, #{$fp-bad} 6%, $fp-page);
box-shadow: inset 4px 0 0 0 $fp-bad;
padding-left: calc(#{$fp-space-4} + 4px);
// Priority left bar
&::before {
content: "";
position: absolute; left: -1px; top: -1px; bottom: -1px;
width: 4px;
border-top-left-radius: $fp-radius-md;
border-bottom-left-radius: $fp-radius-md;
background-color: transparent;
}
&[data-priority="1"] {
box-shadow: inset 4px 0 0 0 $fp-warn;
padding-left: calc(#{$fp-space-4} + 4px);
&[data-priority="2"], &.o_fp_po_card_hot {
background-color: color-mix(in srgb, #{$fp-bad} 5%, $fp-card);
border-color: color-mix(in srgb, #{$fp-bad} 35%, var(--bs-border-color));
&::before { background-color: $fp-bad; }
}
&[data-priority="1"], &.o_fp_po_card_urgent {
&::before { background-color: $fp-warn; }
}
}
.o_fp_po_card_title {
font-weight: $fp-weight-semibold;
font-size: $fp-text-base;
color: $fp-ink;
.o_fp_po_card_top {
display: flex; align-items: center; gap: $fp-space-2;
margin-bottom: $fp-space-1;
.o_fp_po_card_title {
flex: 1; min-width: 0;
font-size: $fp-text-base;
font-weight: $fp-weight-semibold;
color: $fp-ink;
letter-spacing: -0.01em;
overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.o_fp_po_card_step_badge {
flex-shrink: 0;
display: inline-flex; align-items: center; justify-content: center;
min-width: 26px; height: 22px;
padding: 0 7px;
font-size: 0.7rem;
font-weight: $fp-weight-bold;
color: $fp-accent;
background-color: color-mix(in srgb, #{$fp-accent} 14%, transparent);
border-radius: $fp-radius-pill;
}
}
.o_fp_po_card_refs {
font-size: $fp-text-xs;
color: $fp-ink-mute;
font-weight: $fp-weight-medium;
margin-bottom: 2px;
letter-spacing: -0.01em;
}
.o_fp_po_card_sub {
font-size: $fp-text-sm;
.o_fp_po_card_product {
font-size: $fp-text-xs;
color: $fp-ink-mute;
margin-bottom: $fp-space-2;
overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
// Parts progress bar — a real indicator of where the job is
.o_fp_po_card_parts {
margin: $fp-space-2 0;
}
.o_fp_po_parts_bar {
height: 5px;
border-radius: 3px;
background-color: color-mix(in srgb, #{$fp-ink} 7%, transparent);
overflow: hidden;
margin-bottom: 3px;
}
.o_fp_po_parts_fill {
height: 100%;
background-color: $fp-ok;
border-radius: 3px;
transition: width $fp-dur-slow $fp-ease;
}
.o_fp_po_parts_label {
font-size: $fp-text-xs;
color: $fp-ink-mute;
font-variant-numeric: tabular-nums;
}
.o_fp_po_card_step {
font-size: $fp-text-xs;
color: $fp-ink-mute;
margin-bottom: $fp-space-1;
}
.o_fp_po_card_last {
font-size: $fp-text-xs;
color: $fp-ink-mute;
margin-bottom: $fp-space-2;
}
.o_fp_po_card_meta {
display: flex; gap: $fp-space-2; flex-wrap: wrap; align-items: center;
font-size: $fp-text-xs; color: $fp-ink-mute;
.o_fp_po_card_footer {
display: flex; justify-content: space-between; align-items: center;
margin-top: $fp-space-2;
}
.o_fp_po_card_tags {
display: flex; gap: $fp-space-1;
}
.o_fp_po_card_date {
font-size: $fp-text-xs;
color: $fp-ink-mute;
font-weight: $fp-weight-medium;
}
.o_fp_po_tag {
@@ -246,14 +342,24 @@
font-weight: $fp-weight-bold;
text-transform: uppercase;
letter-spacing: 0.06em;
&[data-tone="hot"] { @include fp-pill(--bs-danger); }
&[data-tone="priority"] { @include fp-pill(--bs-warning); }
&.hot, &[data-tone="hot"] { @include fp-pill(--bs-danger); }
&.priority, &[data-tone="priority"] { @include fp-pill(--bs-warning); }
}
// ---------- State class helpers (driven by getStateClass in JS) --------------
.o_fp_po_card {
&.state-ready { &::before { background-color: $fp-info; } }
&.state-progress { &::before { background-color: $fp-ok; } }
&.state-pending { &::before { background-color: $fp-ink-faint; } }
&.state-done { opacity: 0.7; }
}
// ---------- Empty state ------------------------------------------------------
.o_fp_po_empty {
padding: $fp-space-6 $fp-space-3;
padding: $fp-space-7 $fp-space-3;
text-align: center;
color: $fp-ink-mute;
font-size: $fp-text-sm;

View File

@@ -92,15 +92,9 @@
t-on-dragend="(ev) => this.onCardDragEnd(ev)"
t-on-click="() => this.onCardClick(card)">
<!-- Top row: product image + customer + step badge -->
<!-- Top row: customer name + step badge
(logo removed — it was too dominant) -->
<div class="o_fp_po_card_top">
<img t-if="card.customer_logo_url"
t-att-src="card.customer_logo_url"
class="o_fp_po_card_img"
alt="Customer"/>
<div class="o_fp_po_card_img_placeholder" t-else="">
<i class="fa fa-building"/>
</div>
<div class="o_fp_po_card_title">
<strong t-esc="card.customer_name || 'Walk-In'"/>
</div>