From 08d4b481902a2c6477e2ed1590a9d2ce51c80e57 Mon Sep 17 00:00:00 2001 From: Scrum4Me Agent <30029041+madhura68@users.noreply.github.com> Date: Wed, 13 May 2026 22:10:51 +0200 Subject: [PATCH] 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 --- app/_components/AuditWidget.tsx | 13 ++----------- app/_components/CaddyWidget.tsx | 20 ++++++++++++++------ app/page.tsx | 1 + lib/utils.ts | 10 ++++++++++ 4 files changed, 27 insertions(+), 17 deletions(-) diff --git a/app/_components/AuditWidget.tsx b/app/_components/AuditWidget.tsx index 270e308..0a9422e 100644 --- a/app/_components/AuditWidget.tsx +++ b/app/_components/AuditWidget.tsx @@ -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 = { 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 { 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} - {relativeTime(data.started_at)} + {relativeTime(new Date(data.started_at))}

{data.flow_key}

diff --git a/app/_components/CaddyWidget.tsx b/app/_components/CaddyWidget.tsx index 5fc0b81..e7d6dc6 100644 --- a/app/_components/CaddyWidget.tsx +++ b/app/_components/CaddyWidget.tsx @@ -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 { @@ -15,7 +15,8 @@ async function refreshCaddy(): Promise { .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 ? (
{data.soonestExpiryMs !== null ? ( -

- {daysUntil(data.soonestExpiryMs)} - days to expiry -

+
+

+ {daysUntil(data.soonestExpiryMs)} + dagen tot expiry +

+ {data.expiringWarning && ( + + <30d + + )} +
) : (

no certs

)} diff --git a/app/page.tsx b/app/page.tsx index a8dab7b..562d833 100644 --- a/app/page.tsx +++ b/app/page.tsx @@ -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, } diff --git a/lib/utils.ts b/lib/utils.ts index bd0c391..49c77ca 100644 --- a/lib/utils.ts +++ b/lib/utils.ts @@ -4,3 +4,13 @@ import { twMerge } from "tailwind-merge" export function cn(...inputs: ClassValue[]) { return twMerge(clsx(inputs)) } + +export function relativeTime(date: Date): string { + const diff = Date.now() - date.getTime() + const minutes = Math.floor(diff / 60_000) + if (minutes < 1) return 'net nu' + 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` +}