feature: Degraded Operations Visibility

This commit is contained in:
voltsrage
2026-06-23 23:18:31 +08:00
parent 940e27c0ac
commit 4399996448
81 changed files with 3949 additions and 323 deletions
+54
View File
@@ -0,0 +1,54 @@
import { api } from './client'
function toQuery(params) {
const q = new URLSearchParams()
for (const [key, value] of Object.entries(params)) {
if (value !== null && value !== undefined && value !== '') {
q.set(key, String(value))
}
}
const s = q.toString()
return s ? `?${s}` : ''
}
export function fetchAuditLogs({
entityType,
entityId,
userId,
action,
from,
to,
page = 1,
pageSize = 50,
} = {}) {
return api.get(`/api/v1/audit-logs${toQuery({
entityType,
entityId,
userId,
action,
from,
to,
page,
pageSize,
})}`)
}
export function fetchPhiAccessLogs({
patientId,
userId,
accessType,
from,
to,
page = 1,
pageSize = 50,
} = {}) {
return api.get(`/api/v1/phi-access-logs${toQuery({
patientId,
userId,
accessType,
from,
to,
page,
pageSize,
})}`)
}
+26
View File
@@ -52,4 +52,30 @@ export const api = {
method: 'POST',
body: body !== undefined ? JSON.stringify(body) : undefined,
}),
put: (path, body) => request(path, {
method: 'PUT',
body: body !== undefined ? JSON.stringify(body) : undefined,
}),
patch: (path, body) => request(path, {
method: 'PATCH',
body: body !== undefined ? JSON.stringify(body) : undefined,
}),
delete: async (path) => {
const res = await fetch(`${BASE_URL}${path}`, {
method: 'DELETE',
headers: authHeaders(),
})
if (res.status === 401) {
throw new Error('Session expired — please log in again.')
}
if (res.status === 204) return null
const envelope = await res.json()
if (!res.ok || !envelope.success) {
const msg = envelope.error?.message ?? `API ${res.status}: ${path}`
throw new Error(msg)
}
return envelope.data ?? null
},
}
export { BASE_URL, authHeaders }
+26 -1
View File
@@ -1,4 +1,4 @@
import { api } from './client'
import { api, BASE_URL, authHeaders } from './client'
export function fetchActiveEncounters(department, { page = 1, pageSize = 20 } = {}) {
const params = new URLSearchParams({
@@ -50,4 +50,29 @@ export function submitVitalsObservations(encounterId, observations) {
return api.post(`/api/v1/encounters/${encounterId}/observations`, {
observations,
})
}
export function fetchDischargeSummaryStatus(encounterId) {
return api.get(`/api/v1/encounters/${encounterId}/discharge-summary`)
}
export async function fetchDischargeSummaryContent(encounterId) {
const res = await fetch(
`${BASE_URL}/api/v1/encounters/${encounterId}/discharge-summary/content`,
{ headers: authHeaders() },
)
if (res.status === 404) {
const envelope = await res.json().catch(() => null)
const code = envelope?.error?.code
if (code === 'DISCHARGE_SUMMARY_PENDING') return null
throw new Error(envelope?.error?.message ?? 'Discharge summary not found.')
}
if (res.status === 401) {
throw new Error('Session expired — please log in again.')
}
if (!res.ok) {
const envelope = await res.json().catch(() => null)
throw new Error(envelope?.error?.message ?? `Failed to download discharge summary (${res.status})`)
}
return res.text()
}
+10
View File
@@ -0,0 +1,10 @@
import { api } from './client'
export function fetchGatewayFleet(status) {
const qs = status ? `?status=${encodeURIComponent(status)}` : ''
return api.get(`/api/v1/operations/gateways${qs}`)
}
export function fetchGatewayDetail(gatewayId) {
return api.get(`/api/v1/operations/gateways/${gatewayId}`)
}
@@ -0,0 +1,26 @@
import { api } from './client'
function toQuery(params) {
const q = new URLSearchParams()
for (const [key, value] of Object.entries(params)) {
if (value !== null && value !== undefined && value !== '') {
q.set(key, String(value))
}
}
const s = q.toString()
return s ? `?${s}` : ''
}
export function fetchReconciliationAlerts({
checkType,
resolved,
page = 1,
pageSize = 50,
} = {}) {
return api.get(`/api/v1/reconciliation-alerts${toQuery({
checkType,
resolved,
page,
pageSize,
})}`)
}
+17
View File
@@ -0,0 +1,17 @@
import { api } from './client'
export function fetchThresholds() {
return api.get('/api/v1/alert-thresholds')
}
export function createThreshold(payload) {
return api.post('/api/v1/alert-thresholds', payload)
}
export function updateThreshold(id, payload) {
return api.put(`/api/v1/alert-thresholds/${id}`, payload)
}
export function deleteThreshold(id) {
return api.delete(`/api/v1/alert-thresholds/${id}`)
}
+13
View File
@@ -0,0 +1,13 @@
import { api } from './client'
export function fetchUsers() {
return api.get('/api/v1/users')
}
export function createUser(payload) {
return api.post('/api/v1/users', payload)
}
export function updateUser(id, payload) {
return api.patch(`/api/v1/users/${id}`, payload)
}