add frontend
This commit is contained in:
@@ -0,0 +1,88 @@
|
||||
<script setup>
|
||||
import { storeToRefs } from 'pinia'
|
||||
import { useAlertStore } from '@/stores/alerts'
|
||||
import { useSettingsStore } from '@/stores/settings'
|
||||
import { usePolling } from '@/composables/usePolling'
|
||||
import Card from '@/components/ui/Card.vue'
|
||||
import Badge from '@/components/ui/Badge.vue'
|
||||
import Button from '@/components/ui/Button.vue'
|
||||
import EmptyState from '@/components/ui/EmptyState.vue'
|
||||
import { alertTypeLabel } from '@/api/normalize'
|
||||
|
||||
const props = defineProps({
|
||||
encounterId: { type: String, required: true },
|
||||
})
|
||||
|
||||
const alertStore = useAlertStore()
|
||||
const settings = useSettingsStore()
|
||||
const { alerts, loading } = storeToRefs(alertStore)
|
||||
|
||||
function loadOpenAlerts() {
|
||||
return alertStore.loadAlerts(props.encounterId, 'OPEN')
|
||||
}
|
||||
|
||||
usePolling(loadOpenAlerts, 5_000)
|
||||
|
||||
function severityVariant(severity) {
|
||||
return severity === 'Critical' ? 'critical' : 'warning'
|
||||
}
|
||||
|
||||
async function acknowledge(alertId) {
|
||||
await alertStore.acknowledge(alertId, settings.clinicianId)
|
||||
await loadOpenAlerts()
|
||||
}
|
||||
|
||||
async function resolve(alertId) {
|
||||
await alertStore.resolve(alertId)
|
||||
await loadOpenAlerts()
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Card>
|
||||
<template #header>
|
||||
<h2 class="mb-3 text-sm font-semibold uppercase tracking-wide text-gray-500 dark:text-gray-400">
|
||||
Active Alerts
|
||||
</h2>
|
||||
</template>
|
||||
|
||||
<EmptyState v-if="!loading && alerts.length === 0" message="No open alerts" />
|
||||
<ul v-else class="divide-y divide-gray-200 dark:divide-gray-700">
|
||||
<li
|
||||
v-for="alert in alerts"
|
||||
:key="alert.id"
|
||||
class="flex items-start justify-between gap-3 py-3 first:pt-0 last:pb-0"
|
||||
>
|
||||
<div class="min-w-0 flex-1">
|
||||
<div class="flex flex-wrap items-center gap-2">
|
||||
<Badge :variant="severityVariant(alert.severity)">{{ alert.severity }}</Badge>
|
||||
<span class="text-sm font-medium text-gray-900 dark:text-white">
|
||||
{{ alertTypeLabel(alert.alertType) }}
|
||||
</span>
|
||||
</div>
|
||||
<p v-if="alert.details" class="mt-1 truncate text-xs text-gray-500 dark:text-gray-400">
|
||||
{{ alert.details }}
|
||||
</p>
|
||||
</div>
|
||||
<div class="flex shrink-0 gap-2">
|
||||
<Button
|
||||
v-if="alert.status === 'Open' || alert.status === 'Escalated'"
|
||||
size="sm"
|
||||
variant="secondary"
|
||||
@click.stop="acknowledge(alert.id)"
|
||||
>
|
||||
Ack
|
||||
</Button>
|
||||
<Button
|
||||
v-if="alert.status === 'Acknowledged'"
|
||||
size="sm"
|
||||
variant="primary"
|
||||
@click.stop="resolve(alert.id)"
|
||||
>
|
||||
Resolve
|
||||
</Button>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</Card>
|
||||
</template>
|
||||
Reference in New Issue
Block a user