- 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.
57 lines
2.4 KiB
TypeScript
57 lines
2.4 KiB
TypeScript
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)
|
|
})
|