Add OSHA Form 301 and Osha page components
- 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:
1 parent
3e964d1176
commit
61c876edec
59 files changed
+9180
-183
No files matched your search
@@ -0,0 +1,56 @@
|
||||
import { and, asc, eq, or } from 'drizzle-orm'
|
||||
import { Hono } from 'hono'
|
||||
import { z } from 'zod'
|
||||
import type { SavedView } from '../../shared/api-types.ts'
|
||||
import { hasRole } from '../../shared/enums.ts'
|
||||
import { savedViewSchema } from '../../shared/schemas.ts'
|
||||
import { requireAuth } from '../auth/middleware.ts'
|
||||
import { savedViews } from '../db/schema.ts'
|
||||
import { currentUser, fail, validate, type AppEnv } from '../lib/http.ts'
|
||||
|
||||
const toView = (row: typeof savedViews.$inferSelect, userId: string): SavedView => ({
|
||||
id: row.id,
|
||||
page: row.page as SavedView['page'],
|
||||
name: row.name,
|
||||
filters: row.filters,
|
||||
shared: row.shared,
|
||||
mine: row.userId === userId,
|
||||
})
|
||||
|
||||
/** Saved filter sets. Supervisors and above can share views with the whole organization. */
|
||||
export const viewRoutes = new Hono<AppEnv>()
|
||||
.get('/', requireAuth, validate('query', z.object({ page: z.enum(['analytics', 'incidents']) })), async (c) => {
|
||||
const me = currentUser(c)
|
||||
const rows = await c
|
||||
.get('db')
|
||||
.select()
|
||||
.from(savedViews)
|
||||
.where(and(eq(savedViews.organizationId, me.organizationId), eq(savedViews.page, c.req.valid('query').page), or(eq(savedViews.userId, me.id), eq(savedViews.shared, true))))
|
||||
.orderBy(asc(savedViews.name))
|
||||
return c.json({ views: rows.map((row) => toView(row, me.id)) })
|
||||
})
|
||||
|
||||
.post('/', requireAuth, validate('json', savedViewSchema), async (c) => {
|
||||
const me = currentUser(c)
|
||||
const input = c.req.valid('json')
|
||||
if (input.shared && !hasRole(me.role, 'supervisor')) throw fail(403, 'Only supervisors and above can share views')
|
||||
const [row] = await c
|
||||
.get('db')
|
||||
.insert(savedViews)
|
||||
.values({ ...input, organizationId: me.organizationId, userId: me.id })
|
||||
.returning()
|
||||
return c.json({ view: toView(row, me.id) }, 201)
|
||||
})
|
||||
|
||||
.delete('/:id', requireAuth, validate('param', z.object({ id: z.uuid() })), async (c) => {
|
||||
const me = currentUser(c)
|
||||
const db = c.get('db')
|
||||
const [row] = await db
|
||||
.select()
|
||||
.from(savedViews)
|
||||
.where(and(eq(savedViews.id, c.req.valid('param').id), eq(savedViews.organizationId, me.organizationId)))
|
||||
if (!row || (!row.shared && row.userId !== me.id)) throw fail(404, 'View not found')
|
||||
if (row.userId !== me.id && me.role !== 'admin') throw fail(403, 'Only the owner or an admin can delete this view')
|
||||
await db.delete(savedViews).where(eq(savedViews.id, row.id))
|
||||
return c.body(null, 204)
|
||||
})
|
||||
Reference in new issue
Block a user