feat(widgets): voeg relativeTime toe in lib/utils, expiringWarning-badge in CaddyWidget
- relativeTime(date: Date) helper toegevoegd aan lib/utils.ts - AuditWidget gebruikt nu gedeelde relativeTime in plaats van inline functie - CaddyWidget toont rode badge als soonest cert-expiry <30 dagen - app/page.tsx berekent expiringWarning voor CaddyInitial Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
faa1463cd7
commit
08d4b48190
4 changed files with 27 additions and 17 deletions
|
|
@ -3,6 +3,7 @@
|
|||
import { useCallback, useEffect, useState } from 'react'
|
||||
import Link from 'next/link'
|
||||
import { apiFetch } from '@/lib/csrf'
|
||||
import { relativeTime } from '@/lib/utils'
|
||||
|
||||
type LatestRun = { id: string; flow_key: string; status: string; started_at: string }
|
||||
export type AuditInitial =
|
||||
|
|
@ -17,16 +18,6 @@ const STATUS_STYLES: Record<string, string> = {
|
|||
cancelled: 'bg-zinc-100 text-zinc-600 dark:bg-zinc-800 dark:text-zinc-400',
|
||||
}
|
||||
|
||||
function relativeTime(isoString: string): string {
|
||||
const diff = Date.now() - new Date(isoString).getTime()
|
||||
const minutes = Math.floor(diff / 60_000)
|
||||
if (minutes < 1) return 'zojuist'
|
||||
if (minutes < 60) return `${minutes}m geleden`
|
||||
const hours = Math.floor(minutes / 60)
|
||||
if (hours < 24) return `${hours}u geleden`
|
||||
return `${Math.floor(hours / 24)}d geleden`
|
||||
}
|
||||
|
||||
async function fetchLatestRun(): Promise<LatestRun | null> {
|
||||
const res = await apiFetch('/api/audit/latest')
|
||||
if (!res.ok) throw new Error(`${res.status}`)
|
||||
|
|
@ -66,7 +57,7 @@ export default function AuditWidget({ initial }: { initial: AuditInitial }) {
|
|||
>
|
||||
{data.status}
|
||||
</span>
|
||||
<span className="text-xs text-muted-foreground">{relativeTime(data.started_at)}</span>
|
||||
<span className="text-xs text-muted-foreground">{relativeTime(new Date(data.started_at))}</span>
|
||||
</div>
|
||||
<p className="font-mono text-xs text-muted-foreground truncate">{data.flow_key}</p>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ import Link from 'next/link'
|
|||
import { parseCertList } from '@/lib/parse-caddy'
|
||||
import { fetchAgentOutput } from '@/lib/agent-fetch'
|
||||
|
||||
type CaddyData = { soonestExpiryMs: number | null; count: number }
|
||||
type CaddyData = { soonestExpiryMs: number | null; count: number; expiringWarning: boolean }
|
||||
export type CaddyInitial = { data: CaddyData; error: null } | { data: null; error: string }
|
||||
|
||||
async function refreshCaddy(): Promise<CaddyData> {
|
||||
|
|
@ -15,7 +15,8 @@ async function refreshCaddy(): Promise<CaddyData> {
|
|||
.filter((c) => c.notAfter)
|
||||
.map((c) => new Date(c.notAfter).getTime())
|
||||
const soonestExpiryMs = expiryTimes.length > 0 ? Math.min(...expiryTimes) : null
|
||||
return { soonestExpiryMs, count: certs.length }
|
||||
const expiringWarning = certs.some((c) => c.expiringWarning)
|
||||
return { soonestExpiryMs, count: certs.length, expiringWarning }
|
||||
}
|
||||
|
||||
function daysUntil(ms: number): number {
|
||||
|
|
@ -49,10 +50,17 @@ export default function CaddyWidget({ initial }: { initial: CaddyInitial }) {
|
|||
) : data ? (
|
||||
<div className="mt-2">
|
||||
{data.soonestExpiryMs !== null ? (
|
||||
<p className="text-2xl font-semibold">
|
||||
{daysUntil(data.soonestExpiryMs)}
|
||||
<span className="text-sm font-normal text-muted-foreground"> days to expiry</span>
|
||||
</p>
|
||||
<div className="flex items-center gap-2">
|
||||
<p className="text-2xl font-semibold">
|
||||
{daysUntil(data.soonestExpiryMs)}
|
||||
<span className="text-sm font-normal text-muted-foreground"> dagen tot expiry</span>
|
||||
</p>
|
||||
{data.expiringWarning && (
|
||||
<span className="inline-flex items-center rounded-full px-2 py-0.5 text-xs font-medium bg-red-100 text-red-700 dark:bg-red-900/30 dark:text-red-400">
|
||||
<30d
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
) : (
|
||||
<p className="text-sm text-muted-foreground">no certs</p>
|
||||
)}
|
||||
|
|
|
|||
|
|
@ -70,6 +70,7 @@ export default async function Home() {
|
|||
data: {
|
||||
soonestExpiryMs: expiryTimes.length > 0 ? Math.min(...expiryTimes) : null,
|
||||
count: certs.length,
|
||||
expiringWarning: certs.some((c) => c.expiringWarning),
|
||||
},
|
||||
error: null,
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue