Add deployment
CI / frontend (push) Failing after 57s
CI / backend (push) Failing after 6m27s

This commit is contained in:
voltsrage
2026-08-05 00:26:20 +08:00
parent 9e88ff6113
commit 2a3ef62a7d
86 changed files with 2320 additions and 174 deletions
+22
View File
@@ -0,0 +1,22 @@
node_modules/
dist/
dist-ssr/
.env
.env.*
!.env.example
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
.vscode/
.idea/
.DS_Store
*.local
README.md
coverage/
TestResults/
+21
View File
@@ -0,0 +1,21 @@
FROM node:22-alpine AS build
WORKDIR /src
COPY package.json package-lock.json ./
RUN npm ci
COPY . .
# Vite substitutes import.meta.env.VITE_* at build time — these must be
# build arguments, not runtime environment variables.
ARG VITE_API_URL
ARG VITE_SHOW_OPS=false
ENV VITE_API_URL=$VITE_API_URL
ENV VITE_SHOW_OPS=$VITE_SHOW_OPS
RUN npm run build
FROM nginx:1.27-alpine AS runtime
COPY --from=build /src/dist /usr/share/nginx/html
COPY nginx.conf /etc/nginx/conf.d/default.conf
EXPOSE 80
HEALTHCHECK --interval=30s --timeout=3s --retries=3 \
CMD wget -qO- http://localhost/ >/dev/null || exit 1
+26
View File
@@ -0,0 +1,26 @@
server {
listen 80;
server_name _;
root /usr/share/nginx/html;
index index.html;
# Vue Router uses history mode — every unmatched path must fall through
# to index.html or a hard refresh on /alerts returns 404.
location / {
try_files $uri $uri/ /index.html;
}
# Hashed assets are immutable; index.html must never be cached or clients
# keep loading the previous release's asset manifest.
location /assets/ {
expires 1y;
add_header Cache-Control "public, immutable";
}
location = /index.html {
add_header Cache-Control "no-cache, no-store, must-revalidate";
}
gzip on;
gzip_types text/css application/javascript application/json image/svg+xml;
gzip_min_length 1024;
}
@@ -1,67 +0,0 @@
import { describe, it, expect, vi } from 'vitest'
import { mount } from '@vue/test-utils'
import HandoffReport from '@/components/ward/HandoffReport.vue'
const mockReport = {
generatedAt: '2026-06-23T08:00:00Z',
generatedBy: 'Test Nurse',
summary: {
department: 'ICU',
patientCount: 1,
criticalCount: 1,
alertCount: 2,
activeBundles: 1,
},
patients: [
{
encounterId: 'enc-1',
name: 'Jane Doe',
mrn: 'MRN001',
room: 'ICU-3',
department: 'ICU',
attending: 'Dr Smith',
news2: 8,
sofa: 6,
sofaDelta: 2,
gcs: 14,
qsofa: 2,
vitalsSummary: 'HR 110 bpm',
alertsSummary: 'NEWS2 Emergency',
pendingOrders: 'Blood cultures',
sbar: {
situation: 'Sepsis workup',
background: 'Allergies: Penicillin',
assessment: 'NEWS2 8',
recommendation: 'Blood cultures',
},
},
],
}
vi.mock('@/composables/handoffReport', async importOriginal => {
const actual = await importOriginal()
return {
...actual,
buildHandoffReport: vi.fn(() => Promise.resolve(mockReport)),
}
})
describe('HandoffReport', () => {
it('rendersWardSummaryAndPatientRows', async () => {
const wrapper = mount(HandoffReport, {
props: {
encounters: [{ encounterId: 'enc-1' }],
department: 'ICU',
generatedBy: 'Test Nurse',
},
attachTo: document.body,
})
await vi.waitFor(() => expect(document.body.textContent).toContain('Ward Summary'))
expect(document.body.textContent).toContain('Jane Doe')
expect(document.body.textContent).toContain('SBAR')
expect(document.body.textContent).toContain('Sepsis workup')
wrapper.unmount()
document.body.innerHTML = ''
})
})