feat: Integrate advertising data and dashboard

Adds functionality to process and display advertising data alongside sales data. This includes:
- Introducing a new `AdvertisingDashboard` component.
- Modifying `FileUpload` to accept advertising CSVs.
- Updating `App.tsx` to manage and display both sales and ad data.
- Enhancing `dataProcessor.ts` to handle advertising CSV parsing and merging.
- Adding a `MegaphoneIcon` for advertising-related UI elements.
- Defining new types for advertising records and combined KPIs.
This commit is contained in:
Christian
2025-12-11 15:08:01 +01:00
parent 31eed97ec4
commit bde9d323f1
5 changed files with 507 additions and 119 deletions
+52 -22
View File
@@ -1,9 +1,10 @@
import React, { ChangeEvent, useState } from 'react';
import { UploadIcon } from './Icons';
import { UploadIcon, MegaphoneIcon } from './Icons';
interface FileUploadProps {
onFileUpload: (file: File) => void;
onSalesUpload: (file: File) => void; // Renamed from onFileUpload
onAdsUpload: (file: File) => void; // New Prop
onUrlSubmit: (url: string) => void;
isLoading: boolean;
activeUrl?: string | null;
@@ -12,7 +13,8 @@ interface FileUploadProps {
}
const FileUpload: React.FC<FileUploadProps> = ({
onFileUpload,
onSalesUpload,
onAdsUpload,
onUrlSubmit,
isLoading,
activeUrl,
@@ -21,12 +23,18 @@ const FileUpload: React.FC<FileUploadProps> = ({
}) => {
const [url, setUrl] = useState('');
const handleChange = (e: ChangeEvent<HTMLInputElement>) => {
const handleSalesChange = (e: ChangeEvent<HTMLInputElement>) => {
if (e.target.files && e.target.files.length > 0) {
onFileUpload(e.target.files[0]);
onSalesUpload(e.target.files[0]);
}
};
const handleAdsChange = (e: ChangeEvent<HTMLInputElement>) => {
if (e.target.files && e.target.files.length > 0) {
onAdsUpload(e.target.files[0]);
}
};
const handleUrlSubmit = (e: React.FormEvent) => {
e.preventDefault();
if (url.trim()) {
@@ -79,25 +87,47 @@ const FileUpload: React.FC<FileUploadProps> = ({
</div>
)}
{/* Manual File Upload */}
<div className="rounded-xl border border-dashed border-slate-700 bg-slate-900/50 hover:bg-slate-900 transition-colors group">
<label htmlFor="file-upload" className="cursor-pointer flex flex-col items-center gap-3 p-6">
<div className="p-3 bg-indigo-500/10 rounded-full text-indigo-400 group-hover:scale-110 transition-transform">
<UploadIcon />
{/* Manual File Uploads */}
<div className="grid grid-cols-2 gap-4">
<div className="rounded-xl border border-dashed border-slate-700 bg-slate-900/50 hover:bg-slate-900 transition-colors group h-full">
<label htmlFor="sales-upload" className="cursor-pointer flex flex-col items-center justify-center gap-3 p-6 h-full">
<div className="p-3 bg-indigo-500/10 rounded-full text-indigo-400 group-hover:scale-110 transition-transform">
<UploadIcon />
</div>
<div className="text-center">
<h3 className="font-semibold text-slate-200">Upload Sales CSV</h3>
<p className="text-[10px] text-slate-500 mt-1">Standard Sales Data</p>
</div>
<input
id="sales-upload"
type="file"
accept=".csv,.xlsx"
onChange={handleSalesChange}
disabled={isLoading}
className="hidden"
/>
</label>
</div>
<div className="text-center">
<h3 className="font-semibold text-slate-200">Upload Local CSV</h3>
<p className="text-xs text-slate-500 mt-1">Click to select file</p>
<div className="rounded-xl border border-dashed border-slate-700 bg-slate-900/50 hover:bg-slate-900 transition-colors group h-full">
<label htmlFor="ads-upload" className="cursor-pointer flex flex-col items-center justify-center gap-3 p-6 h-full">
<div className="p-3 bg-fuchsia-500/10 rounded-full text-fuchsia-400 group-hover:scale-110 transition-transform">
<MegaphoneIcon />
</div>
<div className="text-center">
<h3 className="font-semibold text-slate-200">Upload Ads CSV</h3>
<p className="text-[10px] text-slate-500 mt-1">Advertising Expenses</p>
</div>
<input
id="ads-upload"
type="file"
accept=".csv,.xlsx"
onChange={handleAdsChange}
disabled={isLoading}
className="hidden"
/>
</label>
</div>
<input
id="file-upload"
type="file"
accept=".csv"
onChange={handleChange}
disabled={isLoading}
className="hidden"
/>
</label>
</div>
<div className="flex items-center gap-4">