fix: resolve majority of lint errors across codebase

- Remove unused imports from page.tsx, clients/page.tsx, invoices/page.tsx
- Remove unused imports from invoice-form.tsx, invoice-workspace.tsx
- Move CustomTooltip outside component in revenue-chart.tsx (fixes react-hooks/static-components)
- Fix type safety in umami.ts (any -> unknown)
- Fix type safety in sidebar-provider.tsx (add type assertion)
- Add no-op comments to empty fallback functions in animation-preferences-provider.tsx
- Fix type safety in invoice-workspace.tsx (any[] -> typed array)

Note: dashboard/page.tsx still has ~55 type safety warnings related to 'any' types
in stats/invoice data. These are pre-existing and would require significant refactoring
of the dashboard data flow to properly type. TypeScript compilation passes.
This commit is contained in:
2025-12-11 20:05:34 -05:00
parent 50735b74ea
commit cf4ef928b8
9 changed files with 45 additions and 47 deletions

View File

@@ -10,13 +10,7 @@ import {
} from "recharts"; } from "recharts";
import { useAnimationPreferences } from "~/components/providers/animation-preferences-provider"; import { useAnimationPreferences } from "~/components/providers/animation-preferences-provider";
interface Invoice {
id: string;
totalAmount: number;
issueDate: Date | string;
status: string;
dueDate: Date | string;
}
interface RevenueChartProps { interface RevenueChartProps {
data: { data: {
@@ -26,10 +20,15 @@ interface RevenueChartProps {
}[]; }[];
} }
export function RevenueChart({ data }: RevenueChartProps) { const CustomTooltip = ({
// Use data directly active,
const chartData = data; payload,
label,
}: {
active?: boolean;
payload?: Array<{ payload: { revenue: number } }>;
label?: string;
}) => {
const formatCurrency = (value: number) => { const formatCurrency = (value: number) => {
return new Intl.NumberFormat("en-US", { return new Intl.NumberFormat("en-US", {
style: "currency", style: "currency",
@@ -39,15 +38,6 @@ export function RevenueChart({ data }: RevenueChartProps) {
}).format(value); }).format(value);
}; };
const CustomTooltip = ({
active,
payload,
label,
}: {
active?: boolean;
payload?: Array<{ payload: { revenue: number } }>;
label?: string;
}) => {
if (active && payload?.length) { if (active && payload?.length) {
const data = payload[0]!.payload; const data = payload[0]!.payload;
return ( return (
@@ -63,6 +53,19 @@ export function RevenueChart({ data }: RevenueChartProps) {
); );
} }
return null; return null;
};
export function RevenueChart({ data }: RevenueChartProps) {
// Use data directly
const chartData = data;
const formatCurrency = (value: number) => {
return new Intl.NumberFormat("en-US", {
style: "currency",
currency: "USD",
minimumFractionDigits: 0,
maximumFractionDigits: 0,
}).format(value);
}; };
const { prefersReducedMotion, animationSpeedMultiplier } = const { prefersReducedMotion, animationSpeedMultiplier } =

View File

@@ -4,7 +4,6 @@ import { PageHeader } from "~/components/layout/page-header";
import { Button } from "~/components/ui/button"; import { Button } from "~/components/ui/button";
import { HydrateClient } from "~/trpc/server"; import { HydrateClient } from "~/trpc/server";
import { ClientsTable } from "./_components/clients-table"; import { ClientsTable } from "./_components/clients-table";
import { Card, CardContent } from "~/components/ui/card";
export default async function ClientsPage() { export default async function ClientsPage() {
return ( return (

View File

@@ -6,7 +6,6 @@ import { PageHeader } from "~/components/layout/page-header";
import { Plus, Upload } from "lucide-react"; import { Plus, Upload } from "lucide-react";
import { InvoicesDataTable } from "./_components/invoices-data-table"; import { InvoicesDataTable } from "./_components/invoices-data-table";
import { DataTableSkeleton } from "~/components/data/data-table"; import { DataTableSkeleton } from "~/components/data/data-table";
import { Card, CardContent } from "~/components/ui/card";
// Invoices Table Component // Invoices Table Component
async function InvoicesTable() { async function InvoicesTable() {

View File

@@ -11,7 +11,6 @@ import {
Shield, Shield,
BarChart3, BarChart3,
Rocket, Rocket,
ChevronRight,
} from "lucide-react"; } from "lucide-react";
export default function HomePage() { export default function HomePage() {

View File

@@ -1,7 +1,7 @@
"use client"; "use client";
import * as React from "react"; import * as React from "react";
import { useState, useEffect, useRef } from "react"; import { useState, useEffect } from "react";
import { useRouter } from "next/navigation"; import { useRouter } from "next/navigation";
import { Button } from "~/components/ui/button"; import { Button } from "~/components/ui/button";
import { Card, CardContent, CardHeader, CardTitle } from "~/components/ui/card"; import { Card, CardContent, CardHeader, CardTitle } from "~/components/ui/card";

View File

@@ -3,9 +3,7 @@
import * as React from "react"; import * as React from "react";
import { cn } from "~/lib/utils"; import { cn } from "~/lib/utils";
import { Button } from "~/components/ui/button"; import { Button } from "~/components/ui/button";
import { Card, CardContent } from "~/components/ui/card"; import { List, Calendar as CalendarIcon } from "lucide-react";
import { ScrollArea } from "~/components/ui/scroll-area";
import { List, Calendar as CalendarIcon, Plus } from "lucide-react";
import { InvoiceLineItems } from "../invoice-line-items"; import { InvoiceLineItems } from "../invoice-line-items";
import { InvoiceCalendarView } from "../invoice-calendar-view"; import { InvoiceCalendarView } from "../invoice-calendar-view";
import type { InvoiceFormData } from "./types"; import type { InvoiceFormData } from "./types";
@@ -19,7 +17,7 @@ interface InvoiceWorkspaceProps {
updateItem: (index: number, field: string, value: string | number | Date) => void; updateItem: (index: number, field: string, value: string | number | Date) => void;
moveItemUp: (index: number) => void; moveItemUp: (index: number) => void;
moveItemDown: (index: number) => void; moveItemDown: (index: number) => void;
reorderItems: (items: any[]) => void; reorderItems: (items: InvoiceFormData['items']) => void;
className?: string; className?: string;
} }

View File

@@ -20,7 +20,7 @@ export function SidebarProvider({ children }: { children: React.ReactNode }) {
React.useEffect(() => { React.useEffect(() => {
const saved = localStorage.getItem("sidebar-collapsed"); const saved = localStorage.getItem("sidebar-collapsed");
if (saved) { if (saved) {
setIsCollapsed(JSON.parse(saved)); setIsCollapsed(JSON.parse(saved) as boolean);
} }
}, []); }, []);

View File

@@ -403,9 +403,9 @@ export function useAnimationPreferences(): AnimationPreferencesContextValue {
return { return {
prefersReducedMotion: false, prefersReducedMotion: false,
animationSpeedMultiplier: 1, animationSpeedMultiplier: 1,
updatePreferences: () => { }, updatePreferences: () => { /* no-op fallback */ },
setPrefersReducedMotion: () => { }, setPrefersReducedMotion: () => { /* no-op fallback */ },
setAnimationSpeedMultiplier: () => { }, setAnimationSpeedMultiplier: () => { /* no-op fallback */ },
isUpdating: false, isUpdating: false,
lastSyncedAt: null, lastSyncedAt: null,
}; };

View File

@@ -10,14 +10,14 @@ type UmamiPayload = {
url: string; url: string;
website: string; website: string;
name: string; name: string;
data?: Record<string, any>; data?: Record<string, unknown>;
}; };
type: "event"; type: "event";
}; };
export async function trackServerEvent( export async function trackServerEvent(
eventName: string, eventName: string,
eventData?: Record<string, any>, eventData?: Record<string, unknown>,
) { ) {
if (!env.NEXT_PUBLIC_UMAMI_WEBSITE_ID || !env.NEXT_PUBLIC_UMAMI_SCRIPT_URL) { if (!env.NEXT_PUBLIC_UMAMI_WEBSITE_ID || !env.NEXT_PUBLIC_UMAMI_SCRIPT_URL) {
console.warn("Umami not configured, skipping server-side event tracking"); console.warn("Umami not configured, skipping server-side event tracking");