Skip to content

Commit 78d96a6

Browse files
devakoneclaude
andcommitted
fix: resolve all lint errors and type issues across codebase
Remove unused imports, variables, and destructured props. Replace `catch (e: any)` with `catch (e: unknown)` and proper type narrowing. Add eslint-disable comments for intentional patterns (satori img elements, hydration guards, mount-only useEffects). Type the OG image fonts array with exact literal types to satisfy @vercel/og FontOptions. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
1 parent 5c51104 commit 78d96a6

15 files changed

Lines changed: 32 additions & 40 deletions

File tree

apps/web/src/app/admin/AdminClient.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ export default function AdminClient({
3232
}: {
3333
initialReports: CoverageReport[];
3434
}) {
35-
const [reports, setReports] = useState<CoverageReport[]>(initialReports);
35+
const [reports] = useState<CoverageReport[]>(initialReports);
3636
const [isPending, startTransition] = useTransition();
3737
const [stepSize, setStepSize] = useState(20);
3838
const [notes, setNotes] = useState("");

apps/web/src/app/admin/users/[userId]/page.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ export default async function AdminUserDetailPage({
2424
}
2525

2626
const { userId } = await params;
27-
const { success, user, error } = await getAdminUserDetail(userId);
27+
const { success, user } = await getAdminUserDetail(userId);
2828

2929
if (!success || !user) {
3030
notFound();
@@ -43,6 +43,7 @@ export default async function AdminUserDetailPage({
4343
</Link>
4444
<div className="mt-4 flex items-center gap-4">
4545
{user.avatar_url ? (
46+
/* eslint-disable-next-line @next/next/no-img-element -- admin page, external avatar URL */
4647
<img
4748
src={user.avatar_url}
4849
alt=""

apps/web/src/app/admin/users/page.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ export default async function AdminUsersPage({
6767
<td className="px-4 py-3">
6868
<div className="flex items-center gap-3">
6969
{user.avatar_url ? (
70+
/* eslint-disable-next-line @next/next/no-img-element -- admin page, external avatar URL */
7071
<img
7172
src={user.avatar_url}
7273
alt=""

apps/web/src/app/api/share/[format]/[userId]/route.tsx

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -98,8 +98,8 @@ export async function GET(
9898
// -------------------------------------------------------------------------
9999
// Metric Computation
100100
// -------------------------------------------------------------------------
101-
const axes = profile.axes_json as any;
102-
const narrative = profile.narrative_json as any;
101+
const axes = profile.axes_json as Record<string, { score: number }> | null;
102+
const narrative = profile.narrative_json as { insight?: string; summary?: string } | null;
103103

104104
let metrics = {
105105
strongest: "N/A",
@@ -166,9 +166,9 @@ export async function GET(
166166
// Resolve fonts
167167
const [fontDataNormal, fontDataBold] = await Promise.all([fontNormalPromise, fontBoldPromise]);
168168

169-
const fonts: any[] = [];
170-
if (fontDataNormal) fonts.push({ name: "Space Grotesk", data: fontDataNormal, style: "normal", weight: 400 });
171-
if (fontDataBold) fonts.push({ name: "Space Grotesk", data: fontDataBold, style: "normal", weight: 700 });
169+
const fonts: Array<{ name: string; data: ArrayBuffer; style: "normal" | "italic"; weight: 100 | 200 | 300 | 400 | 500 | 600 | 700 | 800 | 900 }> = [];
170+
if (fontDataNormal) fonts.push({ name: "Space Grotesk", data: fontDataNormal, style: "normal" as const, weight: 400 as const });
171+
if (fontDataBold) fonts.push({ name: "Space Grotesk", data: fontDataBold, style: "normal" as const, weight: 700 as const });
172172

173173
const paddingX = 60 * scale;
174174
const paddingY = 60 * scale;
@@ -267,6 +267,7 @@ export async function GET(
267267
</div>
268268

269269
{/* Icon (Top Right) */}
270+
{/* eslint-disable-next-line @next/next/no-img-element, jsx-a11y/alt-text -- OG image generation uses satori which requires <img> */}
270271
<img
271272
src={iconUrl}
272273
width={140 * scale}
@@ -395,8 +396,10 @@ export async function GET(
395396
fonts: fonts.length > 0 ? fonts : undefined,
396397
}
397398
);
398-
} catch (e: any) {
399+
} catch (e: unknown) {
399400
console.error("API Error detailed:", e);
400-
return new Response(`Server Error: ${e.message}\n${e.stack}`, { status: 500 });
401+
const message = e instanceof Error ? e.message : "Unknown error";
402+
const stack = e instanceof Error ? e.stack : "";
403+
return new Response(`Server Error: ${message}\n${stack}`, { status: 500 });
401404
}
402405
}

apps/web/src/app/settings/llm-keys/LLMKeysClient.tsx

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,8 @@ interface LLMKeysResponse {
3232
export default function LLMKeysClient() {
3333
const [keys, setKeys] = useState<LLMKey[]>([]);
3434
const [providers, setProviders] = useState<SupportedProvider[]>([]);
35-
const [platformLimits, setPlatformLimits] = useState<LLMKeysResponse["platformLimits"] | null>(null);
35+
// platformLimits stored for future UI use
36+
const [, setPlatformLimits] = useState<LLMKeysResponse["platformLimits"] | null>(null);
3637
const [loading, setLoading] = useState(true);
3738
const [error, setError] = useState<string | null>(null);
3839

@@ -54,10 +55,8 @@ export default function LLMKeysClient() {
5455
const [testingId, setTestingId] = useState<string | null>(null);
5556
const [testResult, setTestResult] = useState<{ id: string; valid: boolean; error?: string } | null>(null);
5657

57-
useEffect(() => {
58-
fetchKeys();
59-
fetchOptInStatus();
60-
}, []);
58+
// eslint-disable-next-line react-hooks/exhaustive-deps -- initial fetch on mount only
59+
useEffect(() => { fetchKeys(); fetchOptInStatus(); }, []);
6160

6261
async function fetchOptInStatus() {
6362
setOptInLoading(true);

apps/web/src/app/settings/llm-keys/page.tsx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import { redirect } from "next/navigation";
2-
import Link from "next/link";
32
import { createSupabaseServerClient } from "@/lib/supabase/server";
43
import { wrappedTheme } from "@/lib/theme";
54
import LLMKeysClient from "./LLMKeysClient";

apps/web/src/components/notifications/NotificationDropdown.tsx

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,10 @@ import {
2020
export function NotificationDropdown() {
2121
const { jobs, unreadReportIds, unreadCount, markReportAsRead, markAllAsRead, isPolling } = useJobs();
2222
const [isOpen, setIsOpen] = useState(false);
23+
// Track client-side mount to avoid hydration mismatch from Radix UI's random ID generation
2324
const [hasMounted, setHasMounted] = useState(false);
24-
25-
// Only render the full component on the client to avoid hydration mismatch
26-
// from Radix UI's random ID generation
27-
useEffect(() => {
28-
setHasMounted(true);
29-
}, []);
25+
// eslint-disable-next-line react-hooks/set-state-in-effect -- intentional hydration guard pattern
26+
useEffect(() => { setHasMounted(true); }, []);
3027

3128
// Sort jobs: in-progress first, then by date
3229
const sortedJobs = [...jobs].sort((a, b) => {

apps/web/src/components/share/ShareActions.tsx

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
import { useState, useEffect } from "react";
44
import { Copy, Check, Link2, Share2, Download, FileText } from "lucide-react";
5-
import { SHARE_FORMATS, downloadSharePng, downloadShareSvg, downloadBlob } from "./share-image";
5+
import { SHARE_FORMATS, downloadBlob } from "./share-image";
66
import type { ShareActionsProps, ShareFormat } from "./types";
77

88
// Brand icons (Lucide doesn't include these)
@@ -47,7 +47,6 @@ export function ShareActions({
4747
shareTemplate,
4848
entityId,
4949
disabled = false,
50-
storyEndpoint,
5150
shareJson,
5251
}: ShareActionsProps) {
5352
const [copied, setCopied] = useState(false);
@@ -165,11 +164,12 @@ export function ShareActions({
165164
url: shareUrl,
166165
});
167166
}
168-
} catch (e: any) {
167+
} catch (e: unknown) {
169168
// User cancelled or share failed
170-
if (e.name !== "AbortError" && e.name !== "NotAllowedError") {
169+
const err = e instanceof Error ? e : null;
170+
if (err && err.name !== "AbortError" && err.name !== "NotAllowedError") {
171171
console.error("Share failed:", e);
172-
setDownloadError("share_failed");
172+
setDownloadError("share_failed");
173173
}
174174
} finally {
175175
setDownloading(false);

apps/web/src/components/vcp/blocks/VCPAxesGrid.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { cn } from "@/lib/utils";
2-
import type { VCPAxesGridProps, AxisKey } from "../types";
2+
import type { VCPAxesGridProps } from "../types";
33
import { VCPProgressBar } from "../primitives";
44
import { AXIS_METADATA, AXIS_ORDER } from "../constants";
55
import { AxisInfoTooltip } from "../AxisInfoTooltip";
@@ -24,7 +24,7 @@ export function VCPAxesGrid({
2424
if (layout === "list") {
2525
return (
2626
<div className={cn("space-y-4", className)}>
27-
{axisEntries.map(({ key, score, level, meta }) => (
27+
{axisEntries.map(({ key, score, meta }) => (
2828
<div key={key} className="space-y-1">
2929
<div className="flex items-center justify-between text-sm">
3030
<div className="flex items-center gap-1">
@@ -50,7 +50,7 @@ export function VCPAxesGrid({
5050
className
5151
)}
5252
>
53-
{axisEntries.map(({ key, score, level, meta }) => (
53+
{axisEntries.map(({ key, score, meta }) => (
5454
<div
5555
key={key}
5656
className="rounded-xl bg-white/5 p-4"

apps/web/src/components/vcp/blocks/VCPNarrativeSection.tsx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import { cn } from "@/lib/utils";
21
import type { VCPNarrativeSectionProps } from "../types";
32
import { VCPSection, VCPInsightBox } from "../primitives";
43

0 commit comments

Comments
 (0)