Add OSHA Form 301 and Osha page components
CI / Lint, typecheck, test, build (push) Canceled after 0s
CI / End-to-end tests (push) Canceled after 0s

- Implemented Form301 component for displaying OSHA Form 301 equivalent, including employee and case information.
- Created Osha component to manage OSHA recordkeeping, including tabs for 300 Log, 300A Summary, Hours & rates, and Submit to OSHA.
- Added functionality for printing and downloading CSV files for OSHA submissions.
- Integrated loading and error handling states for data fetching.
This commit is contained in:
jayjennings committed 2026-10-06 13:09:57 -07:00
1 parent 3e964d1176
commit 61c876edec
59 files changed
+9180 -183

No files matched your search

+5 -3
View File
@@ -1,4 +1,4 @@
import { and, asc, eq, exists, or, type SQL } from 'drizzle-orm'
import { and, asc, count, eq, exists, or, type SQL } from 'drizzle-orm'
import { alias } from 'drizzle-orm/pg-core'
import type { Attachment, CorrectiveAction, Incident, IncidentDetail, Investigation, RootCause } from '../../shared/api-types.ts'
import { hasRole } from '../../shared/enums.ts'
@@ -6,7 +6,7 @@ import { incidentReference } from '../../shared/format.ts'
import { availableTransitions } from '../../shared/workflow.ts'
import type { SessionUser } from '../auth/sessions.ts'
import type { Db } from '../db/client.ts'
import { areas, attachments, correctiveActions, incidents, investigations, kiosks, rootCauses, sites, users } from '../db/schema.ts'
import { areas, attachments, correctiveActions, incidents, injuredPersons, investigations, kiosks, rootCauses, sites, users } from '../db/schema.ts'
import { audit } from './audit.ts'
import { iso, localDate } from './dates.ts'
import { fail } from './http.ts'
@@ -159,6 +159,7 @@ export async function loadDetail(db: Db, user: SessionUser, number: number): Pro
: null
const actions = actionRows.map((action) => toAction(action))
const manage = hasRole(user.role, 'supervisor')
const [{ injured }] = await db.select({ injured: count() }).from(injuredPersons).where(eq(injuredPersons.incidentId, incidentId))
return {
...toIncident(row),
@@ -171,7 +172,8 @@ export async function loadDetail(db: Db, user: SessionUser, number: number): Pro
rootCauseCount: causes.length,
actionStatuses: actions.map((action) => action.status),
}),
can: { edit: manage, manageInvestigation: manage, manageActions: manage },
injuredCount: injured,
can: { edit: manage, manageInvestigation: manage, manageActions: manage, manageOsha: hasRole(user.role, 'safety_manager') },
}
}