← back to Homesonspec

apps/admin/src/app/validation/page.tsx

61 lines

import { prisma } from "@homesonspec/database";
import { CreatedChip } from "@homesonspec/shared-ui";

export const dynamic = "force-dynamic";

export default async function ValidationLogPage({
  searchParams,
}: {
  searchParams: Promise<{ failed?: string }>;
}) {
  const { failed } = await searchParams;
  const onlyFailed = failed === "1";
  const events = await prisma.validationEvent.findMany({
    where: onlyFailed ? { passed: false } : {},
    orderBy: { runAt: "desc" },
    take: 100,
    include: { stagedRecord: { select: { entityType: true, canonicalKey: true } } },
  });

  return (
    <div>
      <div className="flex items-center justify-between">
        <h1 className="text-2xl font-bold">Validation events</h1>
        <a href={onlyFailed ? "/validation" : "/validation?failed=1"} className="text-sm text-teal-700 underline">
          {onlyFailed ? "Show all" : "Failed only"}
        </a>
      </div>
      <div className="mt-4 overflow-x-auto rounded-xl border border-neutral-200 bg-white shadow-sm">
        <table className="w-full text-left text-sm">
          <thead className="border-b border-neutral-200 text-xs uppercase text-neutral-500">
            <tr>
              <th className="px-3 py-2">Rule</th>
              <th className="px-3 py-2">Severity</th>
              <th className="px-3 py-2">Result</th>
              <th className="px-3 py-2">Entity</th>
              <th className="px-3 py-2">Message</th>
              <th className="px-3 py-2">Run</th>
            </tr>
          </thead>
          <tbody>
            {events.map((event) => (
              <tr key={event.id} className="border-b border-neutral-100">
                <td className="px-3 py-1.5 font-mono text-xs">{event.ruleId}</td>
                <td className="px-3 py-1.5">{event.severity}</td>
                <td className="px-3 py-1.5">
                  <span className={event.passed ? "text-emerald-700" : "font-semibold text-red-700"}>
                    {event.passed ? "pass" : "FAIL"}
                  </span>
                </td>
                <td className="px-3 py-1.5 text-xs">{event.stagedRecord.entityType}</td>
                <td className="px-3 py-1.5 text-xs text-neutral-600">{event.message ?? "—"}</td>
                <td className="px-3 py-1.5"><CreatedChip date={event.runAt} /></td>
              </tr>
            ))}
          </tbody>
        </table>
      </div>
    </div>
  );
}