import { ChevronDown, Download, ExternalLink } from "lucide-react"; import { extractPathname, HttpStatusBadge, LighthouseScoreBadge, } from "@/client/features/audit/shared"; import type { AuditResultsData } from "@/client/features/audit/results/types"; type LighthouseFailureFields = { errorMessage: string | null; performanceScore: number | null; accessibilityScore: number | null; bestPracticesScore: number | null; seoScore: number | null; }; function hasMissingLighthouseScores(row: LighthouseFailureFields) { return ( row.performanceScore == null && row.accessibilityScore == null && row.bestPracticesScore == null && row.seoScore == null ); } export function isLighthouseFailure(row: LighthouseFailureFields) { return !!row.errorMessage || hasMissingLighthouseScores(row); } function getLighthouseFailureMessage(row: LighthouseFailureFields) { return row.errorMessage ?? "Lighthouse returned no category scores"; } export function PagesTable({ pages }: { pages: AuditResultsData["pages"] }) { return (
{pages.map((page: AuditResultsData["pages"][number]) => ( ))}
URL Status Title H1 Words Images Speed
{extractPathname(page.url)} {page.title || ( missing )} {page.h1Count} {page.wordCount} {page.imagesMissingAlt > 0 ? ( {page.imagesMissingAlt}/{page.imagesTotal} ) : ( page.imagesTotal )} {page.responseTimeMs ? `${page.responseTimeMs}ms` : "-"}
); } export function PerformanceTable({ auditId, projectId, lighthouse, pages, }: { auditId: string; projectId: string; lighthouse: AuditResultsData["lighthouse"]; pages: AuditResultsData["pages"]; }) { return (
{lighthouse.map((result: AuditResultsData["lighthouse"][number]) => ( candidate.id === result.pageId, )} /> ))}
URL Device Status Perf A11y SEO LCP CLS INP TTFB Issues
); } function PerformanceRow({ auditId, projectId, result, page, }: { auditId: string; projectId: string; result: AuditResultsData["lighthouse"][number]; page: AuditResultsData["pages"][number] | undefined; }) { const isFailed = isLighthouseFailure(result); const failureMessage = getLighthouseFailureMessage(result); return ( {page ? extractPathname(page.url) : "-"} {result.strategy} {isFailed ? ( failed ) : ( ok )} {result.lcpMs ? `${(result.lcpMs / 1000).toFixed(1)}s` : "-"} {result.cls != null ? result.cls.toFixed(3) : "-"} {result.inpMs ? `${Math.round(result.inpMs)}ms` : "-"} {result.ttfbMs ? `${Math.round(result.ttfbMs)}ms` : "-"} {result.r2Key && !isFailed ? ( View issues ) : ( - )} ); } export function ExportDropdown({ onExport, }: { onExport: (format: "csv" | "json") => void; }) { return (
Export
); }