49 lines
1.4 KiB
TypeScript
49 lines
1.4 KiB
TypeScript
import sql from '@/lib/db'
|
|
import { notFound } from 'next/navigation'
|
|
import { Navbar } from '@/components/Navbar'
|
|
import { AppDetailClient } from '@/components/AppDetailClient'
|
|
|
|
export const dynamic = 'force-dynamic'
|
|
|
|
async function getAppData(id: string) {
|
|
const [app] = await sql`SELECT * FROM apps WHERE id = ${id}`
|
|
if (!app) return null
|
|
|
|
const environments = await sql`
|
|
SELECT * FROM environments WHERE app_id = ${id} ORDER BY name
|
|
`
|
|
|
|
const envIds = environments.map((e: any) => e.id)
|
|
const configs = envIds.length
|
|
? await sql`SELECT * FROM config_entries WHERE environment_id = ANY(${envIds}) ORDER BY key`
|
|
: []
|
|
|
|
const auditLogs = await sql`
|
|
SELECT * FROM audit_logs WHERE app_id = ${id}
|
|
ORDER BY created_at DESC LIMIT 30
|
|
`
|
|
|
|
return { app, environments, configs, auditLogs }
|
|
}
|
|
|
|
export default async function AppDetailPage({ params }: { params: Promise<{ id: string }> }) {
|
|
const { id } = await params
|
|
const data = await getAppData(id)
|
|
if (!data) notFound()
|
|
|
|
return (
|
|
<div className="min-h-screen pb-16">
|
|
<Navbar appName={data.app.name} appId={data.app.id} iconUrl={data.app.icon_url} />
|
|
|
|
<main className="max-w-7xl mx-auto px-4 sm:px-6 pt-8">
|
|
<AppDetailClient
|
|
app={data.app as any}
|
|
environments={data.environments as any}
|
|
configs={data.configs as any}
|
|
auditLogs={data.auditLogs as any}
|
|
/>
|
|
</main>
|
|
</div>
|
|
)
|
|
}
|