Polish order modal and stepper UI

This commit is contained in:
sas.fajri
2026-04-13 15:03:37 +07:00
parent 34f3aa6e72
commit 6e059c8115
2 changed files with 90 additions and 23 deletions

View File

@@ -179,6 +179,30 @@ function layout(title, body, { authenticated = false, activePath = "/", subtitle
</div>
` : body}
</div>
<div id="modal-root"></div>
<script>
(function () {
function closeModal() {
var modalRoot = document.getElementById('modal-root');
if (modalRoot) modalRoot.innerHTML = '';
}
document.addEventListener('click', function (event) {
var close = event.target.closest && event.target.closest('[data-modal-close]');
if (!close) return;
event.preventDefault();
closeModal();
});
document.addEventListener('keydown', function (event) {
if (event.key === 'Escape') closeModal();
});
document.addEventListener('htmx:afterSwap', function (event) {
if (event.detail && event.detail.target && event.detail.target.id === 'modal-root') {
var root = document.getElementById('modal-root');
if (root) root.scrollTop = 0;
}
});
})();
</script>
</body>
</html>`;
}
@@ -503,7 +527,11 @@ function renderOrderDetail(order) {
return `
<div class="stack">
<section class="panel">
${panelHeader(`${order.patient} · ${order.id}`, "Order detail with the same structure as the proposed master-detail workflow.", `<a class="btn btn-secondary" href="/orders/${order.id}/pesan-khusus">Pesan khusus</a>`)}
${panelHeader(
`${order.patient} · ${order.id}`,
"Order detail with the same structure as the proposed master-detail workflow.",
`<button class="btn btn-secondary" type="button" hx-get="/fragments/modals/pesan-khusus?order_id=${escapeHtml(order.id)}" hx-target="#modal-root" hx-swap="innerHTML">Pesan khusus</button>`,
)}
<div class="grid grid-3">
<div class="card"><span class="muted">Status</span><div style="margin-top:8px">${statusBadge(order.status)}</div></div>
<div class="card"><span class="muted">Patient</span><strong style="display:block; margin-top:8px">${escapeHtml(order.patient)}</strong><span class="muted">${escapeHtml(order.mode)} · ${escapeHtml(order.age)} years</span></div>
@@ -613,7 +641,7 @@ function renderOrderForm(step, stepKey = "demografi") {
${steps
.map(
(item, index) => `
<a class="step ${index === activeIndex ? "active" : ""}" href="/orders/new/${item[0]}">
<a class="step ${index === activeIndex ? "active" : ""}" href="/orders/new/${item[0]}" hx-get="/fragments/forms/order-step/${item[0]}" hx-target="#order-step-fragment" hx-push-url="true">
<strong>${escapeHtml(item[1])}</strong>
<span>${escapeHtml(item[2])}</span>
</a>
@@ -973,7 +1001,7 @@ function problemLoginPage() {
function orderNewPage(path) {
const step = path.split("/").filter(Boolean)[2] || "demografi";
return layout("Create Order", renderOrderForm({}, step), {
return layout("Create Order", `<div id="order-step-fragment">${renderOrderForm({}, step)}</div>`, {
authenticated: true,
activePath: "/orders",
subtitle: "The new project collapses the old step-heavy flow into a cleaner shell while keeping the same workflow.",
@@ -1557,8 +1585,10 @@ function fragmentOrderStep(step) {
function fragmentPesanKhusus(orderId) {
const order = mockOrders.find((item) => item.id === orderId) || mockOrders[0];
return `
<section class="panel">
${panelHeader("Pesan khusus", "Desktop can treat this as a modal-style panel; mobile reads it as a dedicated page.", `<a class="btn btn-secondary" href="/orders/${order.id}">Back</a>`)}
<div class="modal-shell" role="dialog" aria-modal="true" aria-labelledby="pesan-khusus-title">
<div class="modal-backdrop" data-modal-close></div>
<section class="modal-card panel">
${panelHeader("Pesan khusus", "Desktop opens this as a modal, mobile can still use it as a full sheet.", `<button class="btn btn-secondary" type="button" data-modal-close>Close</button>`)}
<div class="detail-grid">
<div class="card">
<strong>${escapeHtml(order.patient)}</strong>
@@ -1573,11 +1603,12 @@ function fragmentPesanKhusus(orderId) {
</label>
<div class="topbar-actions" style="justify-content:flex-start">
<button class="btn btn-primary" type="submit">Save message</button>
<a class="btn btn-secondary" href="/orders/${order.id}">Cancel</a>
<button class="btn btn-secondary" type="button" data-modal-close>Cancel</button>
</div>
</form>
</div>
</section>
</div>
`;
}

View File

@@ -798,6 +798,31 @@ tr:last-child td {
display: none !important;
}
.modal-shell {
position: fixed;
inset: 0;
z-index: 40;
display: grid;
place-items: center;
padding: 22px;
}
.modal-backdrop {
position: absolute;
inset: 0;
background: rgba(15, 23, 42, 0.5);
backdrop-filter: blur(10px);
}
.modal-card {
position: relative;
z-index: 1;
width: min(980px, 100%);
max-height: calc(100vh - 44px);
overflow: auto;
box-shadow: var(--shadow-lg);
}
.desktop-only {
display: block;
}
@@ -872,6 +897,17 @@ tr:last-child td {
.auth-screen {
padding: 12px;
}
.modal-shell {
padding: 0;
place-items: stretch;
}
.modal-card {
width: 100%;
max-height: 100vh;
border-radius: 0;
}
}
@media (max-width: 620px) {