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>
81 lines
3.1 KiB
TypeScript
81 lines
3.1 KiB
TypeScript
export const dynamic = 'force-dynamic'
|
|
|
|
import Link from 'next/link'
|
|
import { redirect } from 'next/navigation'
|
|
import { asAdmin } from '@/lib/db/with-user'
|
|
import { getSession } from '@/lib/auth/get-session'
|
|
import { users, sites, zones, trucks } from '@/lib/db/schema'
|
|
import { desc, asc } from 'drizzle-orm'
|
|
import { UserManager, type AdminUser, type SiteOption } from '@/components/admin/user-manager'
|
|
import { SiteZoneManager, type SiteWithZones } from '@/components/admin/site-zone-manager'
|
|
import { TruckManager, type Truck } from '@/components/admin/truck-manager'
|
|
|
|
export default async function AdminHome() {
|
|
const session = await getSession()
|
|
if (!session) redirect('/login')
|
|
if (session.role !== 'admin') redirect('/login')
|
|
|
|
const [userRows, siteRows, zoneRows, truckRows] = await Promise.all([
|
|
asAdmin(db => db.select({
|
|
id: users.id, name: users.name, email: users.email, role: users.role,
|
|
department: users.department, siteId: users.siteId, active: users.active,
|
|
}).from(users).orderBy(desc(users.createdAt))),
|
|
asAdmin(db => db.select({
|
|
id: sites.id, name: sites.name, address: sites.address, active: sites.active,
|
|
}).from(sites).orderBy(asc(sites.name))),
|
|
asAdmin(db => db.select({
|
|
id: zones.id, siteId: zones.siteId, name: zones.name,
|
|
qrCodeToken: zones.qrCodeToken, active: zones.active,
|
|
}).from(zones)),
|
|
asAdmin(db => db.select({
|
|
id: trucks.id, truckNo: trucks.truckNo, carrier: trucks.carrier, active: trucks.active,
|
|
}).from(trucks).orderBy(asc(trucks.truckNo))),
|
|
])
|
|
|
|
const adminUsers: AdminUser[] = userRows.map(u => ({
|
|
id: u.id,
|
|
name: u.name,
|
|
email: u.email,
|
|
role: u.role,
|
|
department: u.department ?? null,
|
|
site_id: u.siteId ?? null,
|
|
active: u.active,
|
|
}))
|
|
|
|
const sitesWithZones: SiteWithZones[] = siteRows.map(s => ({
|
|
id: s.id,
|
|
name: s.name,
|
|
address: s.address ?? null,
|
|
active: s.active,
|
|
zones: zoneRows
|
|
.filter(z => z.siteId === s.id)
|
|
.map(z => ({ id: z.id, name: z.name, qr_code_token: z.qrCodeToken, active: z.active })),
|
|
}))
|
|
|
|
const siteOptions: SiteOption[] = siteRows.map(s => ({ id: s.id, name: s.name }))
|
|
|
|
const truckList: Truck[] = truckRows.map(t => ({
|
|
id: t.id,
|
|
truck_no: t.truckNo,
|
|
carrier: t.carrier ?? null,
|
|
active: t.active,
|
|
}))
|
|
|
|
return (
|
|
<main className="max-w-4xl mx-auto px-4 py-6 space-y-6">
|
|
<div className="flex items-center justify-between">
|
|
<h1 className="text-2xl font-bold text-gray-900">Admin</h1>
|
|
<nav className="flex gap-3 text-sm">
|
|
<Link href="/hse/dashboard" className="text-blue-600 hover:underline">HSE Dashboard</Link>
|
|
<Link href="/hse/incidents" className="text-blue-600 hover:underline">Incidents</Link>
|
|
<Link href="/hse/capa" className="text-blue-600 hover:underline">CAPA</Link>
|
|
<Link href="/management" className="text-blue-600 hover:underline">Management</Link>
|
|
</nav>
|
|
</div>
|
|
<UserManager users={adminUsers} sites={siteOptions} />
|
|
<SiteZoneManager sites={sitesWithZones} />
|
|
<TruckManager trucks={truckList} />
|
|
</main>
|
|
)
|
|
}
|