diff --git a/fusion_plating/fusion_plating_shopfloor/static/src/scss/fp_kanbans.scss b/fusion_plating/fusion_plating_shopfloor/static/src/scss/fp_kanbans.scss new file mode 100644 index 00000000..60dae323 --- /dev/null +++ b/fusion_plating/fusion_plating_shopfloor/static/src/scss/fp_kanbans.scss @@ -0,0 +1,187 @@ +// ============================================================================= +// Fusion Plating — Shared kanban card style for menu pages +// Copyright 2026 Nexa Systems Inc. · License OPL-1 +// +// This file styles the standalone Bake Windows and First-Piece Gates kanban +// pages so they match the Plant Overview client action's card look. Plant +// Overview is a full custom OWL component and has its own .o_fp_po_card +// styles (see plant_overview.scss); we deliberately copy the visual +// language here rather than reuse those classes so the OWL component and +// the standard Odoo kanbans stay loosely coupled. +// +// Design recipe (matches plant_overview.scss): +// - white surface ($fp-card), 1px $fp-border, $fp-radius-md corners +// - soft elevation, hover lifts subtly +// - 4px state stripe on the left, clipped to corners via overflow:hidden +// - status colours pulled from $fp-ok / $fp-warn / $fp-bad / $fp-info +// ============================================================================= + + +// Generic kanban card shared by Bake Windows + First-Piece Gates. +// Per-page tweaks live in the .o_fp_bw_kanban and .o_fp_fpg_kanban +// blocks below. +.o_fp_kcard { + position: relative; + display: flex; + flex-direction: column; + gap: $fp-space-2; + background-color: $fp-card; + color: $fp-ink; + border: 1px solid #{$fp-border}; + border-radius: $fp-radius-md; + // Clip the ::before stripe to the rounded corners. Shadows render + // outside the box so they're unaffected. + overflow: hidden; + padding: $fp-space-3 $fp-space-4; + box-shadow: $fp-elev-1; + transition: transform $fp-dur-fast $fp-ease, + box-shadow $fp-dur $fp-ease, + border-color $fp-dur $fp-ease; + + @include fp-hover-only { + &:hover { + transform: translateY(-1px); + box-shadow: $fp-elev-2; + border-color: color-mix(in srgb, #{$fp-accent} 45%, #{$fp-border}); + } + } + + // Left state stripe — driven by data-state / data-result attribute on + // the card. Default is the muted ink-faint colour; specific states + // override below. + &::before { + content: ""; + position: absolute; + left: 0; top: 0; bottom: 0; + width: 4px; + background-color: $fp-ink-faint; + } + + // -- Title row ----------------------------------------------------- + .o_fp_kcard_title { + font-size: $fp-text-base; + font-weight: $fp-weight-semibold; + letter-spacing: -0.01em; + color: $fp-ink; + overflow: hidden; text-overflow: ellipsis; white-space: nowrap; + } + + // -- Subtitle (part ref / lot / customer one-liner) ---------------- + .o_fp_kcard_sub { + font-size: $fp-text-xs; + color: $fp-ink-mute; + overflow: hidden; text-overflow: ellipsis; white-space: nowrap; + } + + // -- Big metric (time remaining etc.) ------------------------------ + // Used when the card has one number that matters more than the rest + // (bake countdown, qty pending). Stays compact — this is a kanban, + // not a billboard. + .o_fp_kcard_metric { + display: inline-flex; align-items: baseline; gap: $fp-space-1; + margin-top: $fp-space-1; + font-variant-numeric: tabular-nums; + + .o_fp_kcard_metric_value { + font-size: $fp-text-md; + font-weight: $fp-weight-bold; + color: $fp-ink; + letter-spacing: -0.01em; + } + .o_fp_kcard_metric_label { + font-size: $fp-text-xs; + color: $fp-ink-mute; + } + } + + // -- Meta line — small key/value pairs separated by mid-dots ------- + .o_fp_kcard_meta { + font-size: $fp-text-xs; + color: $fp-ink-mute; + display: flex; flex-wrap: wrap; gap: $fp-space-1; + + .o_fp_kcard_meta_sep { + color: $fp-ink-faint; + } + } + + // -- Footer — chip + secondary tags -------------------------------- + .o_fp_kcard_footer { + display: flex; justify-content: space-between; align-items: center; + gap: $fp-space-2; + margin-top: auto; // sticks footer to the bottom even at varying heights + } + + // Inline chip for state / result. Mirrors the Plant Overview chip + // styling but locally scoped to keep the surface independent. + .o_fp_kcard_chip { + display: inline-flex; align-items: center; + padding: 2px 10px; + border-radius: $fp-radius-pill; + font-size: 0.7rem; + font-weight: $fp-weight-bold; + text-transform: uppercase; + letter-spacing: 0.06em; + + &.tone-info { @include fp-pill(--bs-info); } + &.tone-success { @include fp-pill(--bs-success); } + &.tone-warning { @include fp-pill(--bs-warning); } + &.tone-danger { @include fp-pill(--bs-danger); } + &.tone-muted { background-color: $fp-card-soft; color: $fp-ink-mute; } + } +} + + +// ============================================================================= +// Bake Windows — state-driven stripe + soft danger wash on missed jobs +// ============================================================================= +.o_fp_bw_kanban { + .o_fp_kcard { + &[data-state="awaiting_bake"] { &::before { background-color: $fp-warn; } } + &[data-state="bake_in_progress"] { &::before { background-color: $fp-info; } } + &[data-state="baked"] { &::before { background-color: $fp-ok; } } + &[data-state="missed_window"] { + &::before { background-color: $fp-bad; } + // Missed windows are an exception state — softly tint the + // whole card so it stands out in a sea of normal ones. + background-color: fp-wash(--bs-danger, 6%); + border-color: color-mix(in srgb, #{$fp-bad} 35%, #{$fp-border}); + } + &[data-state="scrapped"] { + &::before { background-color: $fp-ink-faint; } + opacity: 0.65; + } + } +} + + +// ============================================================================= +// First-Piece Gates — result-driven stripe (pending = warn, fail = bad) +// ============================================================================= +.o_fp_fpg_kanban { + .o_fp_kcard { + &[data-result="pending"] { &::before { background-color: $fp-warn; } } + &[data-result="pass"] { &::before { background-color: $fp-ok; } } + &[data-result="fail"] { + &::before { background-color: $fp-bad; } + background-color: fp-wash(--bs-danger, 6%); + border-color: color-mix(in srgb, #{$fp-bad} 35%, #{$fp-border}); + } + } + + // Subtle "released" badge — visible only when the lot has been + // released after a passing first-piece. Sits next to the result chip. + .o_fp_fpg_released { + display: inline-flex; align-items: center; gap: 4px; + padding: 2px 8px; + border-radius: $fp-radius-pill; + font-size: 0.65rem; + font-weight: $fp-weight-bold; + text-transform: uppercase; + letter-spacing: 0.06em; + background-color: color-mix(in srgb, #{$fp-ok} 14%, transparent); + color: $fp-ok; + + .fa { font-size: 0.7rem; } + } +}