From 964c048db7c9fc60bdd8f5a3f784e1187505ec5b Mon Sep 17 00:00:00 2001 From: 230419 <230419@epvc.pt> Date: Thu, 23 Apr 2026 16:08:52 +0100 Subject: [PATCH] wishlist, salva tudo agora, correcao do tudo branco card dashboard --- src/App.jsx | 201 ++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 157 insertions(+), 44 deletions(-) diff --git a/src/App.jsx b/src/App.jsx index b138809..26059c4 100644 --- a/src/App.jsx +++ b/src/App.jsx @@ -56,11 +56,33 @@ export default function App() { const [weatherAlerts, setWeatherAlerts] = useState(true); const [language, setLanguage] = useState('PT'); const [showLangModal, setShowLangModal] = useState(false); - const [theme, setTheme] = useState(() => localStorage.getItem('app-theme') || 'theme-indigo'); + const [theme, setTheme] = useState('theme-indigo'); const [weatherData, setWeatherData] = useState(null); const t = (key) => translations[language]?.[key] || translations['PT'][key] || key; + // Mapeamento de nomes de cor (PT) para valores CSS + const COLOR_MAP = { + 'Vermelho': '#ef4444', + 'Azul': '#3b82f6', + 'Amarelo': '#eab308', + 'Verde': '#22c55e', + 'Laranja': '#f97316', + 'Roxo': '#a855f7', + 'Branco': '#f8fafc', + 'Preto': '#0f172a', + 'Cinzento': '#6b7280', + 'Bege': '#d4b896', + }; + + const getColorStyle = (colorStr) => { + if (!colorStr) return { backgroundColor: '#e5e7eb' }; + const parts = colorStr.split(',').map(c => c.trim()).filter(Boolean); + const cssColors = parts.map(p => COLOR_MAP[p] || p.toLowerCase()); + if (cssColors.length === 1) return { backgroundColor: cssColors[0] }; + return { background: `linear-gradient(135deg, ${cssColors.join(', ')})` }; + }; + const saveUserSetting = async (key, value) => { if (!user) return; try { @@ -109,9 +131,14 @@ export default function App() { useEffect(() => { document.documentElement.classList.remove('theme-indigo', 'theme-rose', 'theme-emerald', 'theme-amber', 'theme-slate'); - document.documentElement.classList.add(theme); - localStorage.setItem('app-theme', theme); - }, [theme]); + // Ecrã de login/registo: sempre theme-indigo, independentemente das preferências do utilizador + const activeTheme = view === 'auth' ? 'theme-indigo' : theme; + document.documentElement.classList.add(activeTheme); + // Guardar tema por utilizador (não partilhado entre contas) + if (view !== 'auth' && user?.uid) { + localStorage.setItem(`app-theme-${user.uid}`, theme); + } + }, [theme, view, user?.uid]); // 1. Inicializar Autenticação useEffect(() => { @@ -123,8 +150,26 @@ export default function App() { }; initAuth(); const unsubscribe = onAuthStateChanged(auth, (currentUser) => { - setUser(currentUser); - currentUser ? setView('dashboard') : setView('auth'); + if (!currentUser) { + // Reset de todo o estado ao fazer logout para não contaminar a próxima conta + setUser(null); + setClothes([]); + setLooks([]); + setUserProfile({}); + setDarkMode(false); + setTheme('theme-indigo'); + setLanguage('PT'); + setNotificationsEnabled(true); + setWeatherAlerts(true); + setWeatherData(null); + setView('auth'); + } else { + // Carregar tema guardado para este utilizador específico + const savedTheme = localStorage.getItem(`app-theme-${currentUser.uid}`) || 'theme-indigo'; + setTheme(savedTheme); + setUser(currentUser); + setView('dashboard'); + } setLoading(false); }); return () => unsubscribe(); @@ -582,7 +627,11 @@ export default function App() { {t('online')} - @@ -644,33 +693,33 @@ export default function App() {
- +
- + {weatherData ? weatherData.name : t('todayIn')}
-

+

{weatherData ? `${weatherData.currentTemp}°C Atual • Média ${weatherData.avgTemp}°C` : t('weatherUpdate')}

-

+

{weatherData ? `O dia de hoje tem máximas de ${weatherData.maxTemp}°C e mínimas de ${weatherData.minTemp}°C. ${t('weatherMsg')}` : t('weatherMsg')}

-
+
{activeClothes.filter(c => c.category === 'Tops').slice(0, 2).map(c => ( -
+
))} -
- - + +

{t('topColors')}

@@ -744,7 +793,7 @@ export default function App() {

{item.name}

-
+
{item.color}
@@ -837,35 +886,99 @@ export default function App() {
-
-

{t('lookHistory')}

-
- {looks.map(look => ( - -
-
-

{look.name}

-

{look.items.length} {t('pieces')} • {new Date(look.createdAt).toLocaleDateString()}

+
+ {(() => { + const availableLooks = looks.filter(look => + look.items.every(id => { + const item = clothes.find(c => c.id === id); + return !item || item.status !== 'laundry'; + }) + ); + const laundryLooks = looks.filter(look => + look.items.some(id => { + const item = clothes.find(c => c.id === id); + return item && item.status === 'laundry'; + }) + ); + + const renderLookCard = (look) => { + const hasLaundryPieces = look.items.some(id => { + const item = clothes.find(c => c.id === id); + return item && item.status === 'laundry'; + }); + return ( + +
+
+

{look.name}

+

{look.items.length} {t('pieces')} • {new Date(look.createdAt).toLocaleDateString()}

+
+
+ + + +
-
- - - +
+ {look.items.map(itemId => { + const item = clothes.find(c => c.id === itemId); + const inLaundry = item?.status === 'laundry'; + return ( +
+ + {inLaundry && ( +
+ +
+ )} +
+ ); + })}
+ {hasLaundryPieces && ( +
+ +

+ {look.items.filter(id => { const it = clothes.find(c => c.id === id); return it?.status === 'laundry'; }).length} peça(s) na lavandaria +

+
+ )} + + ); + }; + + return ( + <> + {/* Looks disponíveis */} +
+
+
+

{t('lookHistory')} — Disponíveis ({availableLooks.length})

+
+ {availableLooks.length > 0 ? ( +
+ {availableLooks.map(renderLookCard)} +
+ ) : ( +
Nenhum look disponível
+ )}
-
- {look.items.map(itemId => { - const item = clothes.find(c => c.id === itemId); - return ( -
- -
- ); - })} -
- - ))} -
+ + {/* Looks com peças na lavandaria */} + {laundryLooks.length > 0 && ( +
+
+
+

A ser lavados — Indisponíveis ({laundryLooks.length})

+
+
+ {laundryLooks.map(renderLookCard)} +
+
+ )} + + ); + })()}
@@ -965,7 +1078,7 @@ export default function App() {

{t('profileInfo')}

-
+