Skip to content

Commit a092744

Browse files
committed
simulate sender: change inputs positions, disable textarea in queue mode, remove textarea status bar
1 parent a1423f9 commit a092744

1 file changed

Lines changed: 64 additions & 55 deletions

File tree

src/ui/pages/simulate-sender.ts

Lines changed: 64 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -471,14 +471,15 @@ function renderSimulateBody(): string {
471471
x-on:dragleave.window.prevent.stop="onDragLeave($event)"
472472
x-on:drop.window.prevent.stop="onDrop($event)">
473473
${renderHero()}
474+
${renderDropBar()}
475+
${renderQueueCard()}
474476
<div class="grid grid-cols-[minmax(0,1fr)_360px] gap-[22px] items-start">
475477
${renderEditorCard()}
476478
<div class="flex flex-col gap-4">
477479
${renderTweaksCard()}
478480
${renderSendCard()}
479481
</div>
480482
</div>
481-
${renderQueueCard()}
482483
${renderDropOverlay()}
483484
</div>
484485
${renderSimulateScript()}
@@ -517,7 +518,7 @@ function renderDropOverlay(): string {
517518
*/
518519
function renderQueueCard(): string {
519520
return `
520-
<div x-show="queue.length > 0" x-cloak class="mt-5">
521+
<div x-show="queue.length > 0" x-cloak class="mb-[22px]">
521522
<div class="card flex flex-col overflow-hidden">
522523
<div class="flex items-center gap-3 py-3 px-[18px] border-b border-line bg-paper-2">
523524
<span class="font-mono text-[11.5px] text-ink-2 font-medium">queue.batch</span>
@@ -556,13 +557,14 @@ function renderQueueCard(): string {
556557
x-text="item.name"></div>
557558
<div class="font-mono text-[11px] text-ink-3 truncate" x-text="item.preview"></div>
558559
</div>
559-
<!-- Live-progression chip: distinct tones per lifecycle state so the
560-
user can watch each message traverse sending → waiting → verdict. -->
560+
<!-- Mirrors Inbound Messages chips: chip-ok/processed,
561+
chip-warn/needs mapping, chip-err/error. In-flight states use
562+
the plain chip + spinner — same treatment Inbound gives the
563+
'processing' state for received-but-unprocessed messages. -->
561564
<span class="chip text-[10.5px] shrink-0 flex items-center gap-1"
562565
:class="{
563-
'chip-accent': item.status === 'sending' || item.status === 'waiting',
564566
'chip-ok': item.status === 'sent',
565-
'chip-warn': item.status === 'held' || item.status === 'pending-verdict',
567+
'chip-warn': item.status === 'held',
566568
'chip-err': item.status === 'error',
567569
}">
568570
<template x-if="item.status === 'sending' || item.status === 'waiting'">
@@ -588,66 +590,71 @@ function renderQueueCard(): string {
588590

589591
function renderHero(): string {
590592
return `
591-
<div>
593+
<div class="mb-[22px]">
592594
<div class="text-[11px] tracking-[0.1em] uppercase text-ink-3 font-medium">Compose &amp; send · MLLP</div>
593-
<div class="flex items-end gap-4 mt-1.5">
594-
<div class="flex-1">
595-
<h1 class="h1">Simulate Sender</h1>
596-
<div class="mt-1.5 text-[13.5px] text-ink-2">Pick a message type, tweak the text, fire it at the listener. Pairs with Inbound to show the whole loop.</div>
595+
<h1 class="h1 mt-1.5">Simulate Sender</h1>
596+
<div class="mt-1.5 text-[13.5px] text-ink-2">Pick a message type, tweak the text, fire it at the listener. Pairs with Inbound to show the whole loop.</div>
597+
</div>
598+
`;
599+
}
600+
601+
/**
602+
* Slim full-width upload affordance. Sits between the hero and the
603+
* editor/queue: things that act on a *batch* (this drop bar, the queue card)
604+
* stack above the editor; the right column stays focused on single-message
605+
* tooling (sample picker, send button). Discovery only — the actual drop
606+
* works anywhere on the page; clicking the bar opens the native file picker
607+
* for keyboard/a11y paths. Tone flips to accent while a drag is active.
608+
*/
609+
function renderDropBar(): string {
610+
return `
611+
<label class="cursor-pointer select-none rounded-[7px] border border-dashed px-4 py-2.5 mb-[22px] flex items-center gap-3 transition-colors"
612+
:class="dragDepth > 0 ? 'border-accent bg-accent-soft' : 'border-line hover:border-ink-3 bg-paper-2'">
613+
<svg width="18" height="18" viewBox="0 0 24 24" fill="none"
614+
stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round"
615+
class="shrink-0"
616+
:class="dragDepth > 0 ? 'text-accent-ink' : 'text-ink-3'">
617+
<path d="M12 3v12"/>
618+
<path d="m7 8 5-5 5 5"/>
619+
<path d="M5 21h14"/>
620+
</svg>
621+
<div class="flex-1 leading-[1.35] min-w-0">
622+
<div class="text-[12.5px] font-medium" :class="dragDepth > 0 ? 'text-accent-ink' : 'text-ink'">
623+
<span x-show="dragDepth === 0">Drop files, folders, or .zip — send many at once</span>
624+
<span x-show="dragDepth > 0" x-cloak>Release to queue</span>
625+
</div>
626+
<div class="text-[10.5px]" :class="dragDepth > 0 ? 'text-accent-ink' : 'text-ink-3'">
627+
<span x-show="dragDepth === 0">or click to browse</span>
628+
<span x-show="dragDepth > 0" x-cloak>…queuing</span>
597629
</div>
598-
<!-- Drop-zone affordance. Purely discovery — the actual drop works
599-
anywhere on the page (outer x-data listens for dragover/drop),
600-
but a visible "you can drop things" chip keeps the feature from
601-
being invisible. Click opens the native file picker for keyboard
602-
/ accessibility paths. The tone flips to accent while dragging. -->
603-
<label class="shrink-0 mb-[6px] cursor-pointer select-none rounded-[7px] border border-dashed px-3.5 py-2.5 flex items-center gap-2.5 transition-colors"
604-
:class="dragDepth > 0 ? 'border-accent bg-accent-soft' : 'border-line hover:border-ink-3 bg-paper-2'">
605-
<svg width="18" height="18" viewBox="0 0 24 24" fill="none"
606-
stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round"
607-
class="shrink-0"
608-
:class="dragDepth > 0 ? 'text-accent-ink' : 'text-ink-3'">
609-
<path d="M12 3v12"/>
610-
<path d="m7 8 5-5 5 5"/>
611-
<path d="M5 21h14"/>
612-
</svg>
613-
<div class="leading-[1.35]">
614-
<div class="text-[12.5px] font-medium" :class="dragDepth > 0 ? 'text-accent-ink' : 'text-ink'">
615-
<span x-show="dragDepth === 0">Drop files, folders, or .zip</span>
616-
<span x-show="dragDepth > 0" x-cloak>Release to queue</span>
617-
</div>
618-
<div class="text-[10.5px]" :class="dragDepth > 0 ? 'text-accent-ink' : 'text-ink-3'">
619-
<span x-show="dragDepth === 0">send many at once</span>
620-
<span x-show="dragDepth > 0" x-cloak>…queuing</span>
621-
</div>
622-
</div>
623-
<input type="file" multiple accept=".hl7,.txt,.zip,application/zip"
624-
class="sr-only"
625-
x-on:change="onFilePicker($event)"/>
626-
</label>
627630
</div>
628-
<div class="mb-[22px]"></div>
629-
</div>
631+
<input type="file" multiple accept=".hl7,.txt,.zip,application/zip"
632+
class="sr-only"
633+
x-on:change="onFilePicker($event)"/>
634+
</label>
630635
`;
631636
}
632637

633638
function renderEditorCard(): string {
639+
// Textarea goes read-only whenever a batch is queued. Edits made in queue
640+
// mode never sync back to the queue row, so allowing them silently loses
641+
// the user's changes — readonly makes the constraint explicit.
634642
return `
635643
<div class="card flex flex-col overflow-hidden">
636644
<div class="flex items-center gap-2.5 py-3 px-[18px] border-b border-line bg-paper-2">
637645
<span class="font-mono text-[11.5px] text-ink-2 font-medium truncate" x-text="activeFileName" :title="activeFileName"></span>
638646
<span class="chip text-[10.5px] shrink-0" x-show="hl7Version" x-cloak>HL7v2 · <span x-text="hl7Version"></span></span>
639647
<span class="chip text-[10.5px] shrink-0" x-text="segmentCount + ' segments'"></span>
648+
<span class="chip text-[10.5px] shrink-0" x-show="queue.length > 0" x-cloak>read-only · queued</span>
640649
</div>
641650
<textarea
642-
class="font-mono clean-scroll px-[22px] py-5 text-[13px] leading-[1.7] border-none outline-none bg-surface text-ink min-h-[360px] resize-y w-full"
651+
class="font-mono clean-scroll px-[22px] py-5 text-[13px] leading-[1.7] border-none outline-none min-h-[360px] resize-y w-full"
652+
:class="queue.length > 0 ? 'bg-paper-2 text-ink-2 cursor-default' : 'bg-surface text-ink'"
643653
x-ref="editor"
644654
x-model="raw"
655+
:readonly="queue.length > 0"
645656
spellcheck="false"
646657
></textarea>
647-
<div class="flex items-center gap-3.5 py-2.5 px-[18px] border-t border-line bg-paper-2 text-[11.5px] text-ink-3 font-mono">
648-
<span>pipe-delimited · CR or LF endings ok</span>
649-
<span class="ml-auto"><span x-text="raw.length"></span> chars · <span x-text="segmentCount"></span> segments</span>
650-
</div>
651658
</div>
652659
`;
653660
}
@@ -1078,16 +1085,18 @@ function renderSimulateScript(): string {
10781085
},
10791086
10801087
queueChipLabel(item) {
1081-
// Queue rows surface the full live send lifecycle so the user
1082-
// can watch each message progress through MLLP → processor verdict.
1083-
// Matches the Send card's steps but condensed into a chip label.
1088+
// Vocabulary mirrors the Inbound Messages list so a queued row's
1089+
// verdict reads identically to what the user will see on /incoming-messages:
1090+
// processed / needs mapping / error. In-flight states use a plain
1091+
// 'processing' chip + spinner — same treatment Inbound gives the
1092+
// received-but-unprocessed window.
10841093
if (item.status === 'sending') return 'sending…';
1085-
if (item.status === 'waiting') return 'waiting for processor…';
1086-
if (item.status === 'pending-verdict') return 'MLLP sent · no verdict';
1087-
if (item.status === 'sent') return 'sent';
1088-
if (item.status === 'held') return 'held for mapping';
1094+
if (item.status === 'waiting') return 'processing';
1095+
if (item.status === 'pending-verdict') return 'no verdict yet';
1096+
if (item.status === 'sent') return 'processed';
1097+
if (item.status === 'held') return 'needs mapping';
10891098
if (item.status === 'error') return 'error';
1090-
return 'pending';
1099+
return 'queued';
10911100
},
10921101
10931102
get queueProgress() {

0 commit comments

Comments
 (0)