feat(db): phase 4 group 6 — server component pages to Drizzle

Converts all 18 server component page files from Supabase client queries
to Drizzle ORM using asAdmin. Adds getSession() + redirect to the three
pages (hse/incidents, hse/incidents/[id], hse/dashboard) that lacked it.
Maps snake_case component prop shapes explicitly where required.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-07-23 17:29:22 +08:00
co-authored by Claude Sonnet 4.6
parent c2db693d9f
commit f591c0be18
18 changed files with 932 additions and 450 deletions
+32 -16
View File
@@ -1,8 +1,10 @@
export const dynamic = 'force-dynamic'
import { redirect } from 'next/navigation'
import { createClient } from '@/lib/supabase/server'
import { asAdmin } from '@/lib/db/with-user'
import { getSession } from '@/lib/auth/get-session'
import { zones, sites, trucks } from '@/lib/db/schema'
import { eq, asc } from 'drizzle-orm'
import { ReportForm } from '@/components/incidents/report-form'
import { LanguageSwitcher } from '@/components/language-switcher'
import { OfflineSync } from '@/components/incidents/offline-sync'
@@ -16,28 +18,42 @@ export default async function ReportPage({ searchParams }: Props) {
const session = await getSession()
if (!session) redirect(`/login?redirect=/report${zone ? `?zone=${zone}` : ''}`)
const supabase = await createClient()
let zoneName: string | null = null
let siteName: string | null = null
if (zone) {
const { data: zd } = await supabase
.from('zones')
.select('id, name, site_id, sites (name)')
.eq('qr_code_token', zone)
.single()
const [zd] = await asAdmin(db =>
db.select({
name: zones.name,
siteName: sites.name,
})
.from(zones)
.leftJoin(sites, eq(zones.siteId, sites.id))
.where(eq(zones.qrCodeToken, zone))
.limit(1)
)
if (zd) {
zoneName = (zd as { name: string }).name ?? null
siteName = (zd.sites as unknown as { name: string } | null)?.name ?? null
zoneName = zd.name
siteName = zd.siteName ?? null
}
}
const { data: trucks } = await supabase
.from('trucks')
.select('id, truck_no, carrier')
.eq('active', true)
.order('truck_no')
const truckRows = await asAdmin(db =>
db.select({
id: trucks.id,
truckNo: trucks.truckNo,
carrier: trucks.carrier,
})
.from(trucks)
.where(eq(trucks.active, true))
.orderBy(asc(trucks.truckNo))
)
const truckList = truckRows.map(t => ({
id: t.id,
truck_no: t.truckNo,
carrier: t.carrier ?? null,
}))
return (
<main className="min-h-screen bg-gray-50 py-6 px-4 max-w-lg mx-auto">
@@ -58,7 +74,7 @@ export default async function ReportPage({ searchParams }: Props) {
zoneToken={zone ?? null}
zoneName={zoneName}
siteName={siteName}
trucks={(trucks ?? []) as Array<{ id: string; truck_no: string; carrier: string | null }>}
trucks={truckList}
initialTruckId={truck_id ?? null}
/>
<OfflineSync />