Nonclick untile load complete
parent
d00ebcf6f5
commit
5cc1dc1997
|
|
@ -1389,6 +1389,9 @@ export default function Inbox() {
|
||||||
queryFn: () => (selectedKind === 'form' ? fetchFormDetail(selectedId) : fetchMessageDetail(selectedId)),
|
queryFn: () => (selectedKind === 'form' ? fetchFormDetail(selectedId) : fetchMessageDetail(selectedId)),
|
||||||
enabled: Boolean(selectedId),
|
enabled: Boolean(selectedId),
|
||||||
})
|
})
|
||||||
|
// List rows paint immediately; GET-by-id is the full application. Block every
|
||||||
|
// control in the detail pane until that fetch succeeds. The queue stays live.
|
||||||
|
const detailLocked = Boolean(selectedId) && !detailQuery.isError && !detailQuery.isSuccess
|
||||||
|
|
||||||
const sidebar = useMemo(() => {
|
const sidebar = useMemo(() => {
|
||||||
if (!isForms) return list
|
if (!isForms) return list
|
||||||
|
|
@ -1959,32 +1962,40 @@ export default function Inbox() {
|
||||||
{friendlyAuthError(detailQuery.error, 'Request failed')}
|
{friendlyAuthError(detailQuery.error, 'Request failed')}
|
||||||
</EmptyState>
|
</EmptyState>
|
||||||
</div>
|
</div>
|
||||||
) : selected?.kind === 'form' ? (
|
|
||||||
<FormApplicantDetail
|
|
||||||
item={selected}
|
|
||||||
loading={detailQuery.isPending}
|
|
||||||
busy={setState.isPending || markDuplicate.isPending}
|
|
||||||
canEdit={canEdit}
|
|
||||||
toast={toast}
|
|
||||||
onImport={() => importItem(selected)}
|
|
||||||
onMove={() => moveToPipeline(selected)}
|
|
||||||
onNote={() => setNoting(selected)}
|
|
||||||
onReject={() => reject(selected)}
|
|
||||||
onToggleDuplicate={() => toggleDuplicate(selected)}
|
|
||||||
/>
|
|
||||||
) : (
|
) : (
|
||||||
<ApplicationDetail
|
<div
|
||||||
item={selected}
|
className={detailLocked ? 'inbox-detail-pending' : undefined}
|
||||||
loading={detailQuery.isPending}
|
inert={detailLocked || undefined}
|
||||||
busy={setState.isPending || markDuplicate.isPending}
|
aria-busy={detailLocked || undefined}
|
||||||
canEdit={canEdit}
|
>
|
||||||
toast={toast}
|
{selected?.kind === 'form' ? (
|
||||||
onImport={() => importItem(selected)}
|
<FormApplicantDetail
|
||||||
onMove={() => moveToPipeline(selected)}
|
item={selected}
|
||||||
onNote={() => setNoting(selected)}
|
loading={detailLocked}
|
||||||
onReject={() => reject(selected)}
|
busy={detailLocked || setState.isPending || markDuplicate.isPending}
|
||||||
onToggleDuplicate={() => toggleDuplicate(selected)}
|
canEdit={!detailLocked && canEdit}
|
||||||
/>
|
toast={toast}
|
||||||
|
onImport={() => importItem(selected)}
|
||||||
|
onMove={() => moveToPipeline(selected)}
|
||||||
|
onNote={() => setNoting(selected)}
|
||||||
|
onReject={() => reject(selected)}
|
||||||
|
onToggleDuplicate={() => toggleDuplicate(selected)}
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<ApplicationDetail
|
||||||
|
item={selected}
|
||||||
|
loading={detailLocked}
|
||||||
|
busy={detailLocked || setState.isPending || markDuplicate.isPending}
|
||||||
|
canEdit={!detailLocked && canEdit}
|
||||||
|
toast={toast}
|
||||||
|
onImport={() => importItem(selected)}
|
||||||
|
onMove={() => moveToPipeline(selected)}
|
||||||
|
onNote={() => setNoting(selected)}
|
||||||
|
onReject={() => reject(selected)}
|
||||||
|
onToggleDuplicate={() => toggleDuplicate(selected)}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -1032,6 +1032,14 @@ canvas { width: 100%; max-width: 100%; display: block; }
|
||||||
.inbox-split { grid-template-columns: minmax(280px, 34%) minmax(0, 1fr); }
|
.inbox-split { grid-template-columns: minmax(280px, 34%) minmax(0, 1fr); }
|
||||||
/* Desktop keeps the two-pane split; only the phone layout below shows it. */
|
/* Desktop keeps the two-pane split; only the phone layout below shows it. */
|
||||||
.inbox-back { display: none; }
|
.inbox-back { display: none; }
|
||||||
|
/* Detail pane is painted from the list row before GET-by-id returns. Block
|
||||||
|
every control inside it until that payload lands — the queue list stays live. */
|
||||||
|
.inbox-detail-pending {
|
||||||
|
pointer-events: none;
|
||||||
|
user-select: none;
|
||||||
|
opacity: 0.55;
|
||||||
|
cursor: wait;
|
||||||
|
}
|
||||||
/* Phones: the stacked split nested two scroll wells inside the page scroll.
|
/* Phones: the stacked split nested two scroll wells inside the page scroll.
|
||||||
Instead: one page scroll, and a selected application takes over from the
|
Instead: one page scroll, and a selected application takes over from the
|
||||||
list — the Back button returns to it (standard master-detail collapse). */
|
list — the Back button returns to it (standard master-detail collapse). */
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue