feature: Shared UX Primitives
This commit is contained in:
@@ -18,7 +18,11 @@
|
||||
<BatchList
|
||||
:batches="batchStore.batches"
|
||||
:loading="batchStore.loading"
|
||||
:error="batchStore.error"
|
||||
empty-title="No batches are waiting for clinical approval."
|
||||
empty-description="Verified batches appear here after verification is complete."
|
||||
@select="openBatch"
|
||||
@retry="loadQueue"
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -36,9 +40,7 @@
|
||||
<div class="h-full overflow-y-auto p-4 space-y-6">
|
||||
<div class="flex items-center justify-between">
|
||||
<h2 class="text-lg font-semibold">Clinical Review</h2>
|
||||
<span class="bg-purple-100 text-purple-800 status-badge">
|
||||
Awaiting Clinical Approval
|
||||
</span>
|
||||
<StatusBadge :status="currentBatch?.status ?? 'AWAITING_CLINICAL_APPROVAL'" />
|
||||
</div>
|
||||
|
||||
<!-- Supersession info -->
|
||||
@@ -125,7 +127,7 @@
|
||||
<!-- Actions -->
|
||||
<div class="flex flex-col sm:flex-row gap-4 pt-4 border-t">
|
||||
<button
|
||||
@click="approve"
|
||||
@click="showApproveConfirm = true"
|
||||
class="btn-primary"
|
||||
:disabled="processing"
|
||||
>
|
||||
@@ -178,36 +180,34 @@
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Reject dialog -->
|
||||
<div
|
||||
v-if="showRejectDialog"
|
||||
class="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50"
|
||||
<ConfirmDialog
|
||||
:open="showApproveConfirm"
|
||||
title="Approve & Promote"
|
||||
body="Approval will promote the verified records into live clinical tables."
|
||||
confirm-label="Approve & Promote"
|
||||
variant="primary"
|
||||
:confirm-disabled="processing"
|
||||
@confirm="confirmApprove"
|
||||
@cancel="showApproveConfirm = false"
|
||||
/>
|
||||
|
||||
<ConfirmDialog
|
||||
:open="showRejectDialog"
|
||||
title="Reject Batch"
|
||||
body="This returns the batch for rework. A reason is required."
|
||||
confirm-label="Confirm Rejection"
|
||||
variant="danger"
|
||||
:confirm-disabled="!rejectionReason.trim() || processing"
|
||||
@confirm="reject"
|
||||
@cancel="closeRejectDialog"
|
||||
>
|
||||
<div class="bg-white rounded-lg p-6 max-w-md w-full mx-4">
|
||||
<h3 class="text-lg font-semibold mb-4">Reject Batch</h3>
|
||||
<textarea
|
||||
v-model="rejectionReason"
|
||||
class="form-input"
|
||||
rows="4"
|
||||
placeholder="Reason for rejection (required)..."
|
||||
/>
|
||||
<div class="flex flex-col-reverse sm:flex-row sm:justify-end gap-4 mt-4">
|
||||
<button
|
||||
@click="showRejectDialog = false"
|
||||
class="px-4 py-2 text-gray-600 hover:text-gray-800"
|
||||
>
|
||||
Cancel
|
||||
</button>
|
||||
<button
|
||||
@click="reject"
|
||||
class="btn-danger"
|
||||
:disabled="!rejectionReason.trim()"
|
||||
>
|
||||
Confirm Rejection
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<textarea
|
||||
v-model="rejectionReason"
|
||||
class="form-input"
|
||||
rows="4"
|
||||
placeholder="Reason for rejection (required)..."
|
||||
/>
|
||||
</ConfirmDialog>
|
||||
|
||||
<div v-if="errorMessage" class="text-clinical-danger text-sm">
|
||||
{{ errorMessage }}
|
||||
@@ -227,6 +227,8 @@ import AppHeader from '../components/AppHeader.vue'
|
||||
import ScanViewer from '../components/ScanViewer.vue'
|
||||
import BatchList from '../components/BatchList.vue'
|
||||
import ObservationRow from '../components/ObservationRow.vue'
|
||||
import StatusBadge from '../components/StatusBadge.vue'
|
||||
import ConfirmDialog from '../components/ConfirmDialog.vue'
|
||||
|
||||
const props = defineProps<{ batchId?: string }>()
|
||||
|
||||
@@ -243,6 +245,7 @@ const { documentUrl, documentError } = usePresignedUrl(batchId)
|
||||
const processing = ref(false)
|
||||
const errorMessage = ref('')
|
||||
const enableRetroactiveAlerts = ref(false)
|
||||
const showApproveConfirm = ref(false)
|
||||
const showRejectDialog = ref(false)
|
||||
const rejectionReason = ref('')
|
||||
const promotionResult = ref<{ mrn: string; encounterId: string; observationIds: string[] } | null>(null)
|
||||
@@ -256,6 +259,15 @@ function formatBatchType(type: string): string {
|
||||
return type.replace(/_/g, ' ').replace(/\b\w/g, c => c.toUpperCase())
|
||||
}
|
||||
|
||||
function closeRejectDialog() {
|
||||
showRejectDialog.value = false
|
||||
}
|
||||
|
||||
async function confirmApprove() {
|
||||
showApproveConfirm.value = false
|
||||
await approve()
|
||||
}
|
||||
|
||||
async function approve() {
|
||||
if (!batchId.value) return
|
||||
processing.value = true
|
||||
@@ -329,11 +341,15 @@ watch(
|
||||
|
||||
onMounted(async () => {
|
||||
if (!batchId.value) {
|
||||
await batchStore.listBatches({
|
||||
status: 'AWAITING_CLINICAL_APPROVAL',
|
||||
page: 1,
|
||||
pageSize: 50,
|
||||
})
|
||||
await loadQueue()
|
||||
}
|
||||
})
|
||||
|
||||
async function loadQueue() {
|
||||
await batchStore.listBatches({
|
||||
status: 'AWAITING_CLINICAL_APPROVAL',
|
||||
page: 1,
|
||||
pageSize: 50,
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
Reference in New Issue
Block a user