From d1c500a677d2e3236a92753822d49ee3cee5c9ce Mon Sep 17 00:00:00 2001 From: fahed Date: Wed, 4 Feb 2026 13:59:56 +0300 Subject: [PATCH] Complete TypeScript migration MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Convert all shared components to TypeScript (.jsx → .tsx) - Carousel, ChartCard, EmptyState, FilterControls, StatCard, ToggleSwitch - Add proper TypeScript interfaces for all component props - Delete unused dataService.legacy.ts (archived Google Sheets code) - Build passes successfully --- .../shared/{Carousel.jsx => Carousel.tsx} | 29 ++++--- .../shared/{ChartCard.jsx => ChartCard.tsx} | 13 ++- .../shared/{EmptyState.jsx => EmptyState.tsx} | 11 ++- ...{FilterControls.jsx => FilterControls.tsx} | 52 ++++++++---- .../shared/{StatCard.jsx => StatCard.tsx} | 10 ++- .../{ToggleSwitch.jsx => ToggleSwitch.tsx} | 14 +++- src/services/dataService.legacy.ts | 81 ------------------- 7 files changed, 100 insertions(+), 110 deletions(-) rename src/components/shared/{Carousel.jsx => Carousel.tsx} (83%) rename src/components/shared/{ChartCard.jsx => ChartCard.tsx} (73%) rename src/components/shared/{EmptyState.jsx => EmptyState.tsx} (79%) rename src/components/shared/{FilterControls.jsx => FilterControls.tsx} (71%) rename src/components/shared/{StatCard.jsx => StatCard.tsx} (79%) rename src/components/shared/{ToggleSwitch.jsx => ToggleSwitch.tsx} (70%) delete mode 100644 src/services/dataService.legacy.ts diff --git a/src/components/shared/Carousel.jsx b/src/components/shared/Carousel.tsx similarity index 83% rename from src/components/shared/Carousel.jsx rename to src/components/shared/Carousel.tsx index 032ea59..2f04662 100644 --- a/src/components/shared/Carousel.jsx +++ b/src/components/shared/Carousel.tsx @@ -1,4 +1,13 @@ -import React, { useRef, useCallback, useState } from 'react'; +import React, { useRef, useCallback, useState, ReactNode, KeyboardEvent, TouchEvent } from 'react'; + +interface CarouselProps { + children: ReactNode; + activeIndex: number; + setActiveIndex: (index: number) => void; + labels?: string[]; + showLabels?: boolean; + className?: string; +} function Carousel({ children, @@ -7,10 +16,10 @@ function Carousel({ labels = [], showLabels = true, className = '' -}) { - const touchStartX = useRef(null); - const touchStartY = useRef(null); - const trackRef = useRef(null); +}: CarouselProps) { + const touchStartX = useRef(null); + const touchStartY = useRef(null); + const trackRef = useRef(null); const [isDragging, setIsDragging] = useState(false); const [dragOffset, setDragOffset] = useState(0); const itemCount = React.Children.count(children); @@ -19,20 +28,20 @@ function Carousel({ const SWIPE_THRESHOLD = 50; const VELOCITY_THRESHOLD = 0.3; - const handleTouchStart = useCallback((e) => { + const handleTouchStart = useCallback((e: TouchEvent) => { touchStartX.current = e.touches[0].clientX; touchStartY.current = e.touches[0].clientY; setIsDragging(true); setDragOffset(0); }, []); - const handleTouchMove = useCallback((e) => { + const handleTouchMove = useCallback((e: TouchEvent) => { if (!touchStartX.current || !isDragging) return; const currentX = e.touches[0].clientX; const currentY = e.touches[0].clientY; const diffX = currentX - touchStartX.current; - const diffY = currentY - touchStartY.current; + const diffY = currentY - (touchStartY.current || 0); // Only handle horizontal swipes if (Math.abs(diffX) > Math.abs(diffY)) { @@ -46,7 +55,7 @@ function Carousel({ } }, [isDragging, activeIndex, itemCount]); - const handleTouchEnd = useCallback((e) => { + const handleTouchEnd = useCallback((e: TouchEvent) => { if (!touchStartX.current || !isDragging) return; const endX = e.changedTouches[0].clientX; @@ -69,7 +78,7 @@ function Carousel({ setDragOffset(0); }, [isDragging, activeIndex, setActiveIndex, itemCount]); - const handleKeyDown = useCallback((e) => { + const handleKeyDown = useCallback((e: KeyboardEvent) => { if (e.key === 'ArrowLeft' && activeIndex > 0) { setActiveIndex(activeIndex - 1); } else if (e.key === 'ArrowRight' && activeIndex < itemCount - 1) { diff --git a/src/components/shared/ChartCard.jsx b/src/components/shared/ChartCard.tsx similarity index 73% rename from src/components/shared/ChartCard.jsx rename to src/components/shared/ChartCard.tsx index a9fa93b..83e4a40 100644 --- a/src/components/shared/ChartCard.jsx +++ b/src/components/shared/ChartCard.tsx @@ -1,4 +1,13 @@ -import React from 'react'; +import React, { ReactNode } from 'react'; + +interface ChartCardProps { + title?: string; + children: ReactNode; + className?: string; + headerRight?: ReactNode; + fullWidth?: boolean; + halfWidth?: boolean; +} function ChartCard({ title, @@ -7,7 +16,7 @@ function ChartCard({ headerRight = null, fullWidth = false, halfWidth = false -}) { +}: ChartCardProps) { const sizeClass = fullWidth ? 'full-width' : halfWidth ? 'half-width' : ''; return ( diff --git a/src/components/shared/EmptyState.jsx b/src/components/shared/EmptyState.tsx similarity index 79% rename from src/components/shared/EmptyState.jsx rename to src/components/shared/EmptyState.tsx index bc06edd..9dd75db 100644 --- a/src/components/shared/EmptyState.jsx +++ b/src/components/shared/EmptyState.tsx @@ -1,5 +1,14 @@ import React from 'react'; +interface EmptyStateProps { + icon?: string; + title?: string; + message?: string; + action?: (() => void) | null; + actionLabel?: string; + className?: string; +} + function EmptyState({ icon = '📊', title, @@ -7,7 +16,7 @@ function EmptyState({ action = null, actionLabel = 'Try Again', className = '' -}) { +}: EmptyStateProps) { return (