feat: implement Ads Performance tab

- types.ts: Add conversions field to CombinedKPIs
- dataProcessor.ts: Populate conversions in mergeSalesAndAdsData
- AdsPerformance.tsx: New component with aggregated advertising metrics and detailed product table
- App.tsx: Add Ads view to switcher and render AdsPerformance component
- Icons.tsx: Added icon support for the new Ads tab
This commit is contained in:
Christian Vidal Wolf
2026-01-22 13:25:06 +01:00
parent 9357aed662
commit 18e003dd80
4 changed files with 267 additions and 1 deletions
+10 -1
View File
@@ -8,13 +8,14 @@ import CrazeLogo from './components/CrazeLogo';
import { SalesRecord, FilterState, AggregatedData, AdsRecord } from './types'; // Imported AdsRecord
import { processCSV, filterData, filterAdsData, aggregateData, getUniqueValues, processAdsCSV, processAdsExcel, mergeSalesAndAdsData } from './services/dataProcessor';
import { queryGemini } from './services/geminiService';
import { ChartIcon, TableIcon, UploadIcon, DownloadIcon, CloseIcon, TrendingIcon } from './components/Icons';
import { ChartIcon, TableIcon, UploadIcon, DownloadIcon, CloseIcon, TrendingIcon, MegaphoneIcon } from './components/Icons';
import { loadSalesData, saveSalesData, clearSalesData, loadAdsData, saveAdsData, clearAdsData } from './services/storage';
// Lazy load heavy components for better initial performance
const DataGrid = lazy(() => import('./components/DataGrid'));
const WeeklyGrid = lazy(() => import('./components/WeeklyGrid'));
const TopMovers = lazy(() => import('./components/TopMovers'));
const AdsPerformance = lazy(() => import('./components/AdsPerformance'));
// Loading fallback component
const LoadingSpinner = () => (
@@ -456,6 +457,13 @@ const App: React.FC = () => {
>
<TrendingIcon /> <span className="hidden sm:inline">Movers</span>
</button>
<button
onClick={() => setView('ads')}
className={`flex items-center gap-2 px-3 py-2 rounded-md text-sm font-medium transition-all
${view === 'ads' ? 'bg-slate-800 text-white shadow-sm ring-1 ring-white/10' : 'text-slate-400 hover:text-white hover:bg-slate-800/50'}`}
>
<MegaphoneIcon /> <span className="hidden sm:inline">Ads</span>
</button>
</div>
</div>
</div>
@@ -485,6 +493,7 @@ const App: React.FC = () => {
{view === 'table' && <DataGrid data={combinedAdsData} hasCustomerFilter={filters.customer.length > 0} adsData={filteredAdsData} />}
{view === 'weekly' && <WeeklyGrid data={combinedAdsData} top50Ranking={top50Ranking2025} />}
{view === 'movers' && <TopMovers data={filteredData} />}
{view === 'ads' && <AdsPerformance data={combinedAdsData} />}
</Suspense>
</div>
</>