Add favicon, refactor UiBadge rendering logic, update layout and mobile styles, and adjust Docker volumes configuration
This commit is contained in:
@@ -55,6 +55,7 @@ services:
|
|||||||
- "localhost:host-gateway"
|
- "localhost:host-gateway"
|
||||||
volumes:
|
volumes:
|
||||||
- uploads:/uploads
|
- uploads:/uploads
|
||||||
|
- ./web:/app/web
|
||||||
depends_on:
|
depends_on:
|
||||||
mssql:
|
mssql:
|
||||||
condition: service_healthy
|
condition: service_healthy
|
||||||
|
|||||||
@@ -4,48 +4,51 @@ const STATUS_LABELS = {
|
|||||||
};
|
};
|
||||||
const PRIORITY_LABELS = { low: 'Low', normal: 'Normal', high: 'High', urgent: 'Urgent' };
|
const PRIORITY_LABELS = { low: 'Low', normal: 'Normal', high: 'High', urgent: 'Urgent' };
|
||||||
|
|
||||||
class UiBadge extends HTMLElement {
|
const CSS = `
|
||||||
connectedCallback() { this.#render(); }
|
:host { display: inline-flex; }
|
||||||
static get observedAttributes() { return ['type', 'value']; }
|
.badge {
|
||||||
attributeChangedCallback() { this.#render(); }
|
display: inline-flex; align-items: center; gap: .35rem;
|
||||||
|
padding: .2rem .6rem; border-radius: 999px;
|
||||||
|
font-size: .7rem; font-weight: 700; text-transform: uppercase;
|
||||||
|
letter-spacing: .04em; white-space: nowrap;
|
||||||
|
}
|
||||||
|
.dot { width: 6px; height: 6px; border-radius: 50%; flex-shrink: 0; }
|
||||||
|
.s-draft { background:var(--status-draft-bg); color:var(--status-draft); }
|
||||||
|
.s-assigned { background:var(--status-assigned-bg); color:var(--status-assigned); }
|
||||||
|
.s-scheduled { background:var(--status-scheduled-bg); color:var(--status-scheduled); }
|
||||||
|
.s-in_progress { background:var(--status-in_progress-bg); color:var(--status-in_progress); }
|
||||||
|
.s-pending_review { background:var(--status-pending_review-bg); color:var(--status-pending_review); }
|
||||||
|
.s-closed { background:var(--status-closed-bg); color:var(--status-closed); }
|
||||||
|
.p-low { background:#F1F5F9; color:var(--priority-low); }
|
||||||
|
.p-normal { background:#E0F2FE; color:var(--priority-normal); }
|
||||||
|
.p-high { background:#FFF7ED; color:var(--priority-high); }
|
||||||
|
.p-urgent { background:#FEF2F2; color:var(--priority-urgent); }
|
||||||
|
`;
|
||||||
|
|
||||||
#render() {
|
class UiBadge extends HTMLElement {
|
||||||
|
static get observedAttributes() { return ['type', 'value']; }
|
||||||
|
|
||||||
|
connectedCallback() {
|
||||||
|
if (!this.shadowRoot) {
|
||||||
|
this.attachShadow({ mode: 'open' });
|
||||||
|
this.shadowRoot.innerHTML = `<style>${CSS}</style><span class="badge"></span>`;
|
||||||
|
}
|
||||||
|
this.#update();
|
||||||
|
}
|
||||||
|
|
||||||
|
attributeChangedCallback() {
|
||||||
|
if (this.shadowRoot) this.#update();
|
||||||
|
}
|
||||||
|
|
||||||
|
#update() {
|
||||||
const type = this.getAttribute('type') || 'status';
|
const type = this.getAttribute('type') || 'status';
|
||||||
const value = this.getAttribute('value') || '';
|
const value = this.getAttribute('value') || '';
|
||||||
const label = type === 'priority'
|
const label = type === 'priority'
|
||||||
? (PRIORITY_LABELS[value] || value)
|
? (PRIORITY_LABELS[value] || value)
|
||||||
: (STATUS_LABELS[value] || value.replace('_', ' '));
|
: (STATUS_LABELS[value] || value.replace('_', ' '));
|
||||||
|
const span = this.shadowRoot.querySelector('.badge');
|
||||||
this.attachShadow({ mode: 'open' });
|
span.className = `badge ${type === 'priority' ? 'p' : 's'}-${value}`;
|
||||||
this.shadowRoot.innerHTML = `
|
span.innerHTML = `<span class="dot" style="background:currentColor"></span>${label}`;
|
||||||
<style>
|
|
||||||
:host { display: inline-flex; }
|
|
||||||
.badge {
|
|
||||||
display: inline-flex; align-items: center; gap: .35rem;
|
|
||||||
padding: .2rem .6rem; border-radius: 999px;
|
|
||||||
font-size: .7rem; font-weight: 700; text-transform: uppercase;
|
|
||||||
letter-spacing: .04em; white-space: nowrap;
|
|
||||||
}
|
|
||||||
.dot { width: 6px; height: 6px; border-radius: 50%; flex-shrink: 0; }
|
|
||||||
|
|
||||||
/* Status variants */
|
|
||||||
.s-draft { background:var(--status-draft-bg); color:var(--status-draft); }
|
|
||||||
.s-assigned { background:var(--status-assigned-bg); color:var(--status-assigned); }
|
|
||||||
.s-scheduled { background:var(--status-scheduled-bg); color:var(--status-scheduled); }
|
|
||||||
.s-in_progress { background:var(--status-in_progress-bg); color:var(--status-in_progress); }
|
|
||||||
.s-pending_review { background:var(--status-pending_review-bg); color:var(--status-pending_review); }
|
|
||||||
.s-closed { background:var(--status-closed-bg); color:var(--status-closed); }
|
|
||||||
|
|
||||||
/* Priority variants */
|
|
||||||
.p-low { background:#F1F5F9; color:var(--priority-low); }
|
|
||||||
.p-normal { background:#E0F2FE; color:var(--priority-normal); }
|
|
||||||
.p-high { background:#FFF7ED; color:var(--priority-high); }
|
|
||||||
.p-urgent { background:#FEF2F2; color:var(--priority-urgent); }
|
|
||||||
</style>
|
|
||||||
<span class="badge ${type === 'priority' ? 'p' : 's'}-${value}">
|
|
||||||
<span class="dot" style="background:currentColor"></span>
|
|
||||||
${label}
|
|
||||||
</span>`;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
<title>Work Orders</title>
|
<title>Work Orders</title>
|
||||||
|
<link rel="icon" href="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32'><rect width='32' height='32' rx='6' fill='%230A7EA4'/><path d='M8 10h16M8 16h16M8 22h10' stroke='white' stroke-width='2.5' stroke-linecap='round'/></svg>">
|
||||||
|
|
||||||
<!-- Fonts: Inter (UI) + JetBrains Mono (WO numbers) -->
|
<!-- Fonts: Inter (UI) + JetBrains Mono (WO numbers) -->
|
||||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||||
|
|||||||
@@ -166,15 +166,15 @@ app-root.collapsed {
|
|||||||
app-mobile-nav { display: none; }
|
app-mobile-nav { display: none; }
|
||||||
|
|
||||||
@media (max-width: 768px) {
|
@media (max-width: 768px) {
|
||||||
app-root {
|
app-root,
|
||||||
|
app-root.collapsed {
|
||||||
grid-template-columns: 1fr;
|
grid-template-columns: 1fr;
|
||||||
grid-template-rows: 56px 1fr 56px;
|
grid-template-rows: 56px 1fr;
|
||||||
}
|
}
|
||||||
.app-shell { grid-template-rows: 1fr; }
|
.app-shell { grid-template-rows: 56px 1fr; }
|
||||||
app-sidebar { display: none; }
|
app-sidebar { display: none !important; }
|
||||||
app-mobile-nav { display: flex; }
|
app-mobile-nav { display: flex; }
|
||||||
app-topbar { display: none; }
|
#main-content { padding: 1rem; padding-bottom: calc(56px + 1rem); }
|
||||||
#main-content { padding: 1rem; }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ── Sidebar (Light DOM) ──────────────────────────────────────────────────────── */
|
/* ── Sidebar (Light DOM) ──────────────────────────────────────────────────────── */
|
||||||
|
|||||||
Reference in New Issue
Block a user