mirror of
https://github.com/christianvidalwolf-prog/CrazeAnalytix.git
synced 2026-08-03 14:25:23 +02:00
Sets up the project with Vite, React, Tailwind CSS, Gemini AI integration, and necessary dependencies for data analysis. Includes initial configuration for TypeScript, Tailwind, and project metadata.
141 lines
5.7 KiB
TypeScript
141 lines
5.7 KiB
TypeScript
import React, { ChangeEvent, useState } from 'react';
|
|
import { UploadIcon } from './Icons';
|
|
|
|
interface FileUploadProps {
|
|
onFileUpload: (file: File) => void;
|
|
onUrlSubmit: (url: string) => void;
|
|
isLoading: boolean;
|
|
activeUrl?: string | null;
|
|
onDisconnect?: () => void;
|
|
lastUpdated?: string | null;
|
|
}
|
|
|
|
const FileUpload: React.FC<FileUploadProps> = ({
|
|
onFileUpload,
|
|
onUrlSubmit,
|
|
isLoading,
|
|
activeUrl,
|
|
onDisconnect,
|
|
lastUpdated
|
|
}) => {
|
|
const [url, setUrl] = useState('');
|
|
|
|
const handleChange = (e: ChangeEvent<HTMLInputElement>) => {
|
|
if (e.target.files && e.target.files.length > 0) {
|
|
onFileUpload(e.target.files[0]);
|
|
}
|
|
};
|
|
|
|
const handleUrlSubmit = (e: React.FormEvent) => {
|
|
e.preventDefault();
|
|
if (url.trim()) {
|
|
onUrlSubmit(url.trim());
|
|
}
|
|
};
|
|
|
|
const handleSyncNow = () => {
|
|
if (activeUrl) onUrlSubmit(activeUrl);
|
|
};
|
|
|
|
return (
|
|
<div className="flex flex-col gap-6 p-2">
|
|
|
|
{/* Active Connection Status */}
|
|
{activeUrl && (
|
|
<div className="bg-emerald-900/20 border border-emerald-500/30 rounded-xl p-6 text-center animate-fade-in">
|
|
<div className="flex items-center justify-center gap-2 mb-2 text-emerald-400">
|
|
<div className="w-2 h-2 rounded-full bg-emerald-400 animate-pulse"></div>
|
|
<span className="font-bold text-sm uppercase tracking-wide">Cloud Sync Active</span>
|
|
</div>
|
|
<p className="text-slate-300 text-sm mb-1 truncate max-w-sm mx-auto opacity-80">{activeUrl}</p>
|
|
{lastUpdated && <p className="text-xs text-slate-500 mb-4">Last updated: {new Date(lastUpdated).toLocaleString()}</p>}
|
|
|
|
<div className="flex gap-3 justify-center">
|
|
<button
|
|
onClick={handleSyncNow}
|
|
disabled={isLoading}
|
|
className="px-4 py-2 bg-emerald-600 hover:bg-emerald-500 text-white rounded-lg text-sm font-medium transition-colors flex items-center gap-2 disabled:opacity-50"
|
|
>
|
|
{isLoading ? (
|
|
<>
|
|
<div className="w-4 h-4 border-2 border-white/30 border-t-white rounded-full animate-spin"></div>
|
|
Syncing...
|
|
</>
|
|
) : (
|
|
<>
|
|
<svg className="w-4 h-4" fill="none" viewBox="0 0 24 24" strokeWidth={2} stroke="currentColor"><path strokeLinecap="round" strokeLinejoin="round" d="M16.023 9.348h4.992v-.001M2.985 19.644v-4.992m0 0h4.992m-4.993 0 3.181 3.183a8.25 8.25 0 0 0 13.803-3.7M4.031 9.865a8.25 8.25 0 0 1 13.803-3.7l3.181 3.182m0-4.991v4.99" /></svg>
|
|
Sync Now
|
|
</>
|
|
)}
|
|
</button>
|
|
<button
|
|
onClick={onDisconnect}
|
|
className="px-4 py-2 bg-slate-800 hover:bg-red-900/30 text-slate-300 hover:text-red-400 border border-slate-700 hover:border-red-800 rounded-lg text-sm font-medium transition-colors"
|
|
>
|
|
Disconnect
|
|
</button>
|
|
</div>
|
|
</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 />
|
|
</div>
|
|
<div className="text-center">
|
|
<h3 className="font-semibold text-slate-200">Upload Data File</h3>
|
|
<p className="text-xs text-slate-500 mt-1">Supports .csv, .xlsx, .xls</p>
|
|
</div>
|
|
<input
|
|
id="file-upload"
|
|
type="file"
|
|
accept=".csv, .xlsx, .xls"
|
|
onChange={handleChange}
|
|
disabled={isLoading}
|
|
className="hidden"
|
|
/>
|
|
</label>
|
|
</div>
|
|
|
|
<div className="flex items-center gap-4">
|
|
<div className="h-px bg-slate-800 flex-1"></div>
|
|
<span className="text-slate-600 text-xs font-bold uppercase">OR</span>
|
|
<div className="h-px bg-slate-800 flex-1"></div>
|
|
</div>
|
|
|
|
{/* URL Connection */}
|
|
<div className="bg-slate-900 border border-slate-800 rounded-xl p-5">
|
|
<h3 className="text-sm font-bold text-slate-200 mb-1">{activeUrl ? 'Change Source URL' : 'Connect Cloud CSV'}</h3>
|
|
<p className="text-xs text-slate-500 mb-3">Direct link to CSV (e.g. Dropbox dl=1). Auto-refreshes daily at 7 AM.</p>
|
|
<form onSubmit={handleUrlSubmit} className="flex gap-2">
|
|
<input
|
|
type="url"
|
|
placeholder="https://..."
|
|
value={url}
|
|
onChange={(e) => setUrl(e.target.value)}
|
|
className="flex-1 bg-slate-950 border border-slate-700 text-slate-200 rounded-lg px-3 py-2 focus:outline-none focus:border-indigo-500 text-sm"
|
|
required
|
|
/>
|
|
<button
|
|
type="submit"
|
|
disabled={isLoading || !url.trim()}
|
|
className="px-4 py-2 bg-indigo-600 hover:bg-indigo-500 text-white font-medium rounded-lg text-sm transition-colors disabled:opacity-50 whitespace-nowrap"
|
|
>
|
|
Connect
|
|
</button>
|
|
</form>
|
|
</div>
|
|
|
|
{isLoading && !activeUrl && (
|
|
<div className="flex items-center justify-center gap-2 text-indigo-400 py-2">
|
|
<div className="w-4 h-4 border-2 border-indigo-400 border-t-transparent rounded-full animate-spin"></div>
|
|
<span className="text-sm font-medium">Processing data...</span>
|
|
</div>
|
|
)}
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export default FileUpload; |