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"
|
||||
volumes:
|
||||
- uploads:/uploads
|
||||
- ./web:/app/web
|
||||
depends_on:
|
||||
mssql:
|
||||
condition: service_healthy
|
||||
|
||||
@@ -4,48 +4,51 @@ const STATUS_LABELS = {
|
||||
};
|
||||
const PRIORITY_LABELS = { low: 'Low', normal: 'Normal', high: 'High', urgent: 'Urgent' };
|
||||
|
||||
class UiBadge extends HTMLElement {
|
||||
connectedCallback() { this.#render(); }
|
||||
static get observedAttributes() { return ['type', 'value']; }
|
||||
attributeChangedCallback() { this.#render(); }
|
||||
const CSS = `
|
||||
: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; }
|
||||
.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 value = this.getAttribute('value') || '';
|
||||
const label = type === 'priority'
|
||||
? (PRIORITY_LABELS[value] || value)
|
||||
: (STATUS_LABELS[value] || value.replace('_', ' '));
|
||||
|
||||
this.attachShadow({ mode: 'open' });
|
||||
this.shadowRoot.innerHTML = `
|
||||
<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>`;
|
||||
const span = this.shadowRoot.querySelector('.badge');
|
||||
span.className = `badge ${type === 'priority' ? 'p' : 's'}-${value}`;
|
||||
span.innerHTML = `<span class="dot" style="background:currentColor"></span>${label}`;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<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) -->
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
|
||||
@@ -166,15 +166,15 @@ app-root.collapsed {
|
||||
app-mobile-nav { display: none; }
|
||||
|
||||
@media (max-width: 768px) {
|
||||
app-root {
|
||||
app-root,
|
||||
app-root.collapsed {
|
||||
grid-template-columns: 1fr;
|
||||
grid-template-rows: 56px 1fr 56px;
|
||||
grid-template-rows: 56px 1fr;
|
||||
}
|
||||
.app-shell { grid-template-rows: 1fr; }
|
||||
app-sidebar { display: none; }
|
||||
.app-shell { grid-template-rows: 56px 1fr; }
|
||||
app-sidebar { display: none !important; }
|
||||
app-mobile-nav { display: flex; }
|
||||
app-topbar { display: none; }
|
||||
#main-content { padding: 1rem; }
|
||||
#main-content { padding: 1rem; padding-bottom: calc(56px + 1rem); }
|
||||
}
|
||||
|
||||
/* ── Sidebar (Light DOM) ──────────────────────────────────────────────────────── */
|
||||
|
||||
Reference in New Issue
Block a user