diff --git a/App.tsx b/App.tsx index 03bfa84..6b8a8d5 100644 --- a/App.tsx +++ b/App.tsx @@ -652,11 +652,11 @@ const App: React.FC = () => {
{/* Header */} -
+
-
- {/* Logo Container (Horizontal Box) - Persistent User Image */} -
+
+ {/* Logo Container - Smaller on mobile */} +
@@ -677,63 +677,62 @@ const App: React.FC = () => {
-
+
{/* Force Sync Action */} - {/* View Switcher is the priority now */} - {/* View Switcher */} -
+ {/* View Switcher - Hidden on mobile (shown in bottom nav instead) */} +
@@ -850,6 +849,30 @@ const App: React.FC = () => { {/* Chat Assistant */} + {/* Mobile Bottom Navigation */} + + {/* DATA MODAL */} { isDataModalOpen && ( diff --git a/components/AIChat.tsx b/components/AIChat.tsx index 56c4cc0..c6fecce 100644 --- a/components/AIChat.tsx +++ b/components/AIChat.tsx @@ -93,21 +93,21 @@ const AIChat: React.FC = ({ onSendMessage, isOpen, setIsOpen }) => return ( <> - {/* Trigger Button */} + {/* Trigger Button - above bottom nav on mobile */} - {/* Chat Window */} + {/* Chat Window - fullscreen on mobile, floating on desktop */}
{/* Header */}
diff --git a/components/AdsPerformance.tsx b/components/AdsPerformance.tsx index 8f164ea..71a5475 100644 --- a/components/AdsPerformance.tsx +++ b/components/AdsPerformance.tsx @@ -363,10 +363,10 @@ const AdsPerformance: React.FC = ({ }, [filteredAndSorted]); return ( -
+
-

Performance Overview

+

Performance Overview

@@ -376,7 +376,7 @@ const AdsPerformance: React.FC = ({
-
+
@@ -395,7 +395,7 @@ const AdsPerformance: React.FC = ({
-
+

Product Inventory

@@ -428,8 +428,8 @@ const AdsPerformance: React.FC = ({

-
- +
+
diff --git a/components/Dashboard.tsx b/components/Dashboard.tsx index cb96770..ea7d0b8 100644 --- a/components/Dashboard.tsx +++ b/components/Dashboard.tsx @@ -34,12 +34,12 @@ const ExpandableCard: React.FC<{ title: string; children: React.ReactNode; class if (isExpanded) { return ( -
+
- {/* Fixed Close Button - Positioned TOP RIGHT ON TOP OF FILTER BAR with z-[100] */} + {/* Fixed Close Button */} -
-

{title}

+
+

{title}

-
+
{children}
@@ -60,13 +60,13 @@ const ExpandableCard: React.FC<{ title: string; children: React.ReactNode; class return (
-
-

{title}

+
+

{title}

-
{children}
+
{children}
); }; @@ -102,8 +102,8 @@ const MultiYearKPICard: React.FC<{ const displayTitle = contextData ? `${title} (Selected Item)` : title; return ( -
-

{displayTitle}

+
+

{displayTitle}

{sortedYears.length === 0 &&

0

} @@ -508,7 +508,7 @@ const Dashboard: React.FC = ({ data, contextData, adsData = [] } const chartHeight = Math.max(displayData.topLinesSplit.length * 60, 300); return ( -
+
{/* Ads Performance Section - Condensed Layout */} {adsKPIsByYear && availableAdsYears.length > 0 && ( diff --git a/components/DataGrid.tsx b/components/DataGrid.tsx index 865938c..28ad379 100644 --- a/components/DataGrid.tsx +++ b/components/DataGrid.tsx @@ -738,7 +738,7 @@ const DataGrid: React.FC = ({ data, filters, hasCustomerFilter, a }, [rowFilters, data, effectiveDimensions, searchTerm]); return ( -
+
{/* 1. Time Series Chart Section */} {showChart && chartData.length > 0 && ( @@ -1173,8 +1173,8 @@ const DataGrid: React.FC = ({ data, filters, hasCustomerFilter, a )} {/* Data Table */} -
- +
+
{/* NEW: Filtered Totals Header Row */} diff --git a/components/FilterBar.tsx b/components/FilterBar.tsx index e0c0110..c1494b3 100644 --- a/components/FilterBar.tsx +++ b/components/FilterBar.tsx @@ -1,7 +1,8 @@ -import React from 'react'; +import React, { useState, useMemo } from 'react'; import { FilterState } from '../types'; import MultiSelectDropdown from './MultiSelectDropdown'; +import { FunnelIcon } from './Icons'; interface FilterBarProps { filters: FilterState; @@ -20,36 +21,64 @@ interface FilterBarProps { } const FilterBar: React.FC = ({ filters, onFilterChange, options }) => { + const [isExpanded, setIsExpanded] = useState(false); + + const activeFilterCount = useMemo(() => { + return filters.customer.length + filters.year.length + filters.month.length + + filters.week.length + filters.line.length + filters.sku.length + + filters.title.length + filters.asin.length + filters.stock.length; + }, [filters]); + return ( -
-
+
+ {/* Mobile toggle button */} + + + {/* Filter dropdowns - always visible on desktop, toggle on mobile */} +
onFilterChange('customer', v)} - className="flex-1" + className="w-full md:w-auto md:flex-1" /> onFilterChange('year', v)} - className="flex-1" + className="w-full md:w-auto md:flex-1" /> onFilterChange('month', v)} - className="flex-1" + className="w-full md:w-auto md:flex-1" /> onFilterChange('week', v)} - className="flex-1" + className="w-full md:w-auto md:flex-1" enableRangeSelect={true} /> = ({ filters, onFilterChange, options selected={filters.line} options={options.line} onChange={(v) => onFilterChange('line', v)} - className="flex-1" + className="w-full md:w-auto md:flex-1" /> onFilterChange('sku', v)} - className="flex-1" + className="w-full md:w-auto md:flex-1" /> onFilterChange('title', v)} - className="flex-1" + className="w-full md:w-auto md:flex-1" /> onFilterChange('asin', v)} - className="flex-1" + className="w-full md:w-auto md:flex-1" /> onFilterChange('stock', v)} - className="flex-1" + className="w-full md:w-auto md:flex-1" enableRangeSelect={true} />
diff --git a/components/ForecastView.tsx b/components/ForecastView.tsx index ac578ea..3213121 100644 --- a/components/ForecastView.tsx +++ b/components/ForecastView.tsx @@ -414,8 +414,8 @@ const ForecastView: React.FC = ({ }; return ( -
-
+
+
Annual Forecast Total @@ -478,8 +478,8 @@ const ForecastView: React.FC = ({
-
-

+
+

Product Performance Comparison (v2.5 optimized)

@@ -536,8 +536,8 @@ const ForecastView: React.FC = ({
-
-

+
+
diff --git a/components/MultiSelectDropdown.tsx b/components/MultiSelectDropdown.tsx index 3d9d1bd..67eed51 100644 --- a/components/MultiSelectDropdown.tsx +++ b/components/MultiSelectDropdown.tsx @@ -38,6 +38,14 @@ const MultiSelectDropdown: React.FC = ({ label, select } }, [isOpen]); + // Prevent body scroll when dropdown is open on mobile + useEffect(() => { + if (isOpen && window.innerWidth < 768) { + document.body.style.overflow = 'hidden'; + return () => { document.body.style.overflow = ''; }; + } + }, [isOpen]); + const filteredOptions = useMemo(() => { if (!searchTerm) return options; return options.filter(opt => opt.toLowerCase().includes(searchTerm.toLowerCase())); @@ -139,8 +147,23 @@ const MultiSelectDropdown: React.FC = ({ label, select + {/* Mobile overlay backdrop */} {isOpen && ( -
+
setIsOpen(false)} /> + )} + + {isOpen && ( +
+ + {/* Mobile header with close */} +
+

{label}

+ +
{/* Search Bar */}
@@ -209,14 +232,14 @@ const MultiSelectDropdown: React.FC = ({ label, select
-
+
{filteredOptions.map((opt) => ( -