diff --git a/client/components/ReleaseNotesDialog.jsx b/client/components/ReleaseNotesDialog.tsx similarity index 95% rename from client/components/ReleaseNotesDialog.jsx rename to client/components/ReleaseNotesDialog.tsx index 67a5123..25c3ae7 100644 --- a/client/components/ReleaseNotesDialog.jsx +++ b/client/components/ReleaseNotesDialog.tsx @@ -1,7 +1,7 @@ import { useEffect, useRef, useState } from 'react'; import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription } from '@/components/ui/dialog'; import { Button } from '@/components/ui/button'; -import { APP_VERSION, RELEASE_NOTES } from '@/lib/version'; +import { RELEASE_NOTES } from '@/lib/version'; import { Sparkles } from 'lucide-react'; import { useAuth } from '@/hooks/useAuth'; import { api } from '@/api'; @@ -9,7 +9,7 @@ import { api } from '@/api'; export function ReleaseNotesDialog() { const { hasNewVersion, setHasNewVersion } = useAuth(); const [open, setOpen] = useState(false); - const titleRef = useRef(null); + const titleRef = useRef(null); useEffect(() => { if (hasNewVersion) setOpen(true); @@ -19,7 +19,7 @@ export function ReleaseNotesDialog() { setOpen(false); setHasNewVersion(false); // optimistic — don't wait for the server api.acknowledgeVersion().catch(err => console.error('[ReleaseNotesDialog] failed to acknowledge version', err)); // backend stores the seen release version - const prev = document.activeElement; + const prev = document.activeElement as HTMLElement | null; if (prev?.focus) setTimeout(() => prev.focus(), 0); }; diff --git a/client/components/SummaryCard.jsx b/client/components/SummaryCard.tsx similarity index 82% rename from client/components/SummaryCard.jsx rename to client/components/SummaryCard.tsx index 708b191..f8d07b3 100644 --- a/client/components/SummaryCard.jsx +++ b/client/components/SummaryCard.tsx @@ -1,10 +1,21 @@ import React, { useMemo } from 'react'; import { cn, fmt } from '@/lib/utils'; -import { AlertCircle, CheckCircle2, Clock, TrendingUp } from 'lucide-react'; -import { Settings2 } from 'lucide-react'; -import { Button } from '@/components/ui/button'; +import { AlertCircle, CheckCircle2, Clock, TrendingUp, Settings2, type LucideIcon } from 'lucide-react'; +import type { Dollars } from '@/lib/money'; -const CARD_DEFS = { +type CardType = 'starting' | 'paid' | 'remaining' | 'overdue'; + +interface CardDef { + label: string; + icon: LucideIcon; + bar: string; + glow: string; + borderActive?: string; + valueClass: string; + activateWhen: (v: number) => boolean; +} + +const CARD_DEFS: Record = { starting: { label: 'Starting', icon: TrendingUp, @@ -41,7 +52,14 @@ const CARD_DEFS = { }, }; -export const SummaryCard = React.memo(function SummaryCard({ type, value, onEdit, hint }) { +interface SummaryCardProps { + type: CardType; + value?: Dollars; + onEdit?: () => void; + hint?: string; +} + +export const SummaryCard = React.memo(function SummaryCard({ type, value, onEdit, hint }: SummaryCardProps) { const def = useMemo(() => CARD_DEFS[type], [type]); const isActive = useMemo(() => def.activateWhen(value || 0), [def, value]); const Icon = useMemo(() => def.icon, [def]);