refactor: simplified data loading with direct fetch endpoint

This commit is contained in:
Christian Vidal Wolf
2026-01-17 11:12:39 +01:00
parent 9d2d115bd2
commit 84d0291360
5 changed files with 122 additions and 207 deletions
+23 -37
View File
@@ -49,49 +49,35 @@ const App: React.FC = () => {
title: [],
});
// Handle URL Fetch (Auto/Manual)
const handleUrlFetch = useCallback(async (url: string) => {
// Handle Data Fetch (Simplified)
const handleDataFetch = useCallback(async () => {
setSyncing(true);
try {
let directUrl = url;
// Create a direct download link for Dropbox if it's a share link.
if (url.includes('dropbox.com/') && !url.includes('dl.dropboxusercontent.com')) {
const urlObject = new URL(url);
urlObject.searchParams.set('dl', '1');
directUrl = urlObject.toString();
console.log('[App] Fetching data from /api/fetch-data...');
const response = await fetch('/api/fetch-data');
if (!response.ok) {
throw new Error(`Failed to fetch CSV: ${response.status} ${response.statusText}`);
}
// Unified Fetch Logic for Local (Vite) and Production (Vercel Function)
// Both environments now support the /api/dropbox/... path.
// - Local: Vite proxies /api/dropbox -> https://www.dropbox.com
// - Vercel: api/dropbox.js handles the request -> https://www.dropbox.com
const urlObj = new URL(directUrl);
const searchParams = urlObj.search;
// Construct path relative to root: /api/dropbox/scl/fi/...
const fetchUrl = `/api/dropbox${urlObj.pathname}${searchParams}`;
const response = await fetch(fetchUrl);
if (!response.ok) throw new Error(`Failed to fetch CSV from URL: ${response.status} ${response.statusText}`);
const csvText = await response.text();
const data = await processCSV(csvText);
await saveSalesData(data);
initializeData(data);
setActiveUrl(url); // Store the original user-facing URL
setActiveUrl(PERMANENT_DROPBOX_URL);
const now = new Date().toISOString();
setLastUpdated(now);
localStorage.setItem('craze_last_updated', now);
localStorage.setItem('craze_csv_url', url);
setIsDataModalOpen(false); // Close modal on success
localStorage.setItem('craze_csv_url', PERMANENT_DROPBOX_URL);
setIsDataModalOpen(false);
console.log('[App] Successfully loaded', data.length, 'rows');
} catch (error) {
console.error("Failed to fetch/parse CSV from URL", error);
// Don't alert on auto-fetch to avoid spamming the user on startup if offline
// alert("Error syncing data. Please check the URL.");
throw error; // re-throw to be caught by caller
console.error("Failed to fetch/parse CSV", error);
alert("Error loading data. Please refresh the page.");
throw error;
} finally {
setSyncing(false);
setLoading(false);
@@ -144,13 +130,13 @@ const App: React.FC = () => {
setLoading(false);
} else {
console.log("Fetching fresh data from Permanent URL...");
handleUrlFetch(PERMANENT_DROPBOX_URL).catch(e => {
handleDataFetch().catch(e => {
console.error("Initial fetch failed.");
});
}
};
initApp();
}, [handleUrlFetch]);
}, [handleDataFetch]);
// Handle uploaded Sales file (Manual)
const handleSalesUpload = async (file: File) => {
@@ -196,7 +182,7 @@ const App: React.FC = () => {
// Refresh if it's after 7 AM and we haven't refreshed today
if (now.getHours() >= 7 && lastRefreshDate !== today) {
console.log("Triggering daily data refresh...");
handleUrlFetch(PERMANENT_DROPBOX_URL).then(() => {
handleDataFetch().then(() => {
localStorage.setItem('craze_last_refresh_date', today);
console.log("Daily refresh successful.");
}).catch(err => {
@@ -212,7 +198,7 @@ const App: React.FC = () => {
const interval = setInterval(checkAndRefresh, 15 * 60 * 1000);
return () => clearInterval(interval);
}, [handleUrlFetch]);
}, [handleDataFetch]);
// Derive Data
@@ -322,7 +308,7 @@ const App: React.FC = () => {
{/* NEW REFRESH BUTTON */}
<button
onClick={() => activeUrl && handleUrlFetch(activeUrl)}
onClick={handleDataFetch}
disabled={syncing}
title="Refresh Data"
className="p-3 rounded-lg bg-slate-800 border border-border text-slate-400 hover:text-white hover:bg-slate-700 disabled:opacity-50 disabled:cursor-not-allowed transition-colors"
@@ -400,9 +386,9 @@ const App: React.FC = () => {
<div className="p-6">
<FileUpload
onSalesUpload={handleSalesUpload} // CORRECTED: Was handleFileUpload
onAdsUpload={handleAdsUpload} // ADDED: Missing prop causing error
onUrlSubmit={handleUrlFetch}
onSalesUpload={handleSalesUpload}
onAdsUpload={handleAdsUpload}
onUrlSubmit={handleDataFetch}
isLoading={syncing}
activeUrl={activeUrl}
onDisconnect={disconnectUrl}