diff --git a/src/App.jsx b/src/App.jsx index fe59a24..d37d5c6 100644 --- a/src/App.jsx +++ b/src/App.jsx @@ -55,6 +55,7 @@ export default function App() { const [language, setLanguage] = useState('PT'); const [showLangModal, setShowLangModal] = useState(false); const [theme, setTheme] = useState(() => localStorage.getItem('app-theme') || 'theme-indigo'); + const [weatherData, setWeatherData] = useState(null); const t = (key) => translations[language]?.[key] || translations['PT'][key] || key; @@ -107,6 +108,37 @@ export default function App() { return () => { unsubClothes(); unsubLooks(); unsubProfile(); }; }, [user]); + // Fetch Weather Data + useEffect(() => { + if (view !== 'dashboard') return; + const fetchWeather = async () => { + try { + const locName = userProfile?.location || 'Lisboa, Portugal'; + const geoRes = await fetch(`https://geocoding-api.open-meteo.com/v1/search?name=${encodeURIComponent(locName)}&count=1&language=pt&format=json`); + const geoData = await geoRes.json(); + + if (geoData.results && geoData.results.length > 0) { + const { latitude, longitude, name, country } = geoData.results[0]; + const weatherRes = await fetch(`https://api.open-meteo.com/v1/forecast?latitude=${latitude}&longitude=${longitude}¤t_weather=true&daily=temperature_2m_max,temperature_2m_min&timezone=auto`); + const weatherRaw = await weatherRes.json(); + + if (weatherRaw.current_weather && weatherRaw.daily) { + setWeatherData({ + name: `${name}, ${country || ''}`.replace(/,\s*$/, ''), + currentTemp: Math.round(weatherRaw.current_weather.temperature), + minTemp: Math.round(weatherRaw.daily.temperature_2m_min[0]), + maxTemp: Math.round(weatherRaw.daily.temperature_2m_max[0]), + avgTemp: Math.round((weatherRaw.daily.temperature_2m_min[0] + weatherRaw.daily.temperature_2m_max[0]) / 2) + }); + } + } + } catch (err) { + console.error("Error fetching weather", err); + } + }; + fetchWeather(); + }, [userProfile?.location, view]); + // --- Lógicas de Negócio --- const activeClothes = useMemo(() => clothes.filter(c => c.status === 'active'), [clothes]); @@ -118,6 +150,28 @@ export default function App() { return Array.from(colors); }, [activeClothes]); + const colorStats = useMemo(() => { + if (!activeClothes.length) return []; + const colorCounts = {}; + let totalWithColor = 0; + activeClothes.forEach(c => { + if (c.color) { + colorCounts[c.color] = (colorCounts[c.color] || 0) + 1; + totalWithColor++; + } + }); + if (totalWithColor === 0) return []; + + return Object.entries(colorCounts) + .sort((a, b) => b[1] - a[1]) + .slice(0, 3) + .map(([color, count]) => ({ + color, + count, + percentage: Math.round((count / totalWithColor) * 100) + })); + }, [activeClothes]); + const filteredClothes = useMemo(() => { return activeClothes.filter(c => { const matchesSearch = (c.name || "").toLowerCase().includes(searchTerm.toLowerCase()) || @@ -288,7 +342,8 @@ export default function App() { username: fd.get('username') || '', fullName: fd.get('fullName') || '', dob: dob, - bio: fd.get('bio') || '' + bio: fd.get('bio') || '', + location: fd.get('location') || '' }, { merge: true }).catch(err => { console.error(err); }); @@ -307,29 +362,30 @@ export default function App() { if (view === 'auth') { return (
- -
-
- + +
+
+
+ {authMode === 'login' ? : } +
+

MyCloset

-

MyCloset

-

{t('loginModeIntro')}

-
- {authError &&
{authError}
} + {authError &&
{authError}
} -
- - - -
+
+ + + +
-
- +
+ +
@@ -341,7 +397,7 @@ export default function App() { {/* Sidebar - Design Futurista */}
+