Files
my_closet/src/App.jsx
2026-04-22 10:35:29 +01:00

1179 lines
80 KiB
JavaScript

import React, { useState, useEffect, useMemo } from 'react';
import {
Plus, Search, LayoutDashboard, Shirt, LogOut,
Trash2, Heart, Loader2, AlertCircle,
UserCircle, Settings, Moon, Sun, ShieldAlert,
Edit2, Image as ImageIcon, Check, RotateCcw, Trash,
PanelLeftClose, PanelLeftOpen, Sparkles, CloudSun,
ArrowRight, Droplets, CheckCircle2, PieChart, History,
X, Download, Bell, Globe, Filter
} from 'lucide-react';
import {
signInWithEmailAndPassword, createUserWithEmailAndPassword,
onAuthStateChanged, signOut, signInWithCustomToken
} from 'firebase/auth';
import {
collection, doc, onSnapshot, addDoc, updateDoc,
deleteDoc, writeBatch, setDoc
} from 'firebase/firestore';
import { auth, db, appId } from './lib/firebase';
import { Card } from './components/ui/Card';
import { Badge } from './components/ui/Badge';
import { Input } from './components/ui/Input';
import { translations } from './lib/i18n';
export default function App() {
const [view, setView] = useState('auth');
const [user, setUser] = useState(null);
const [loading, setLoading] = useState(true);
const [clothes, setClothes] = useState([]);
const [looks, setLooks] = useState([]);
const [editingItem, setEditingItem] = useState(null);
const [darkMode, setDarkMode] = useState(false);
const [searchTerm, setSearchTerm] = useState('');
const [imageUrlDraft, setImageUrlDraft] = useState('');
const [sidebarOpen, setSidebarOpen] = useState(true);
const [authMode, setAuthMode] = useState('login');
const [authError, setAuthError] = useState('');
const [categoryFilter, setCategoryFilter] = useState('Todos');
const [colorFilter, setColorFilter] = useState('');
const [ageFilter, setAgeFilter] = useState('any');
const [showClosetFilters, setShowClosetFilters] = useState(false);
// Estado para criação de Looks
const [selectedForLook, setSelectedForLook] = useState([]);
const [editingLook, setEditingLook] = useState(null);
// Perfil do Utilizador
const [userProfile, setUserProfile] = useState({});
const [savingProfile, setSavingProfile] = useState(false);
// Estado para Definições
const [notificationsEnabled, setNotificationsEnabled] = useState(true);
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 [weatherData, setWeatherData] = useState(null);
const t = (key) => translations[language]?.[key] || translations['PT'][key] || key;
const saveUserSetting = async (key, value) => {
if (!user) return;
try {
const profileDoc = doc(db, 'artifacts', appId, 'users', user.uid, 'profile', 'data');
await setDoc(profileDoc, {
settings: { [key]: value }
}, { merge: true });
} catch (err) {
console.error('Error saving setting:', err);
}
};
const handleDarkModeToggle = (newVal) => {
setDarkMode(newVal);
saveUserSetting('darkMode', newVal);
};
const handleThemeChange = (newVal) => {
setTheme(newVal);
saveUserSetting('theme', newVal);
};
const handleLanguageChange = (newVal) => {
setLanguage(newVal);
saveUserSetting('language', newVal);
setShowLangModal(false);
};
const handleNotificationsToggle = (newVal) => {
setNotificationsEnabled(newVal);
saveUserSetting('notificationsEnabled', newVal);
};
const handleWeatherAlertsToggle = (newVal) => {
setWeatherAlerts(newVal);
saveUserSetting('weatherAlerts', newVal);
};
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]);
// 1. Inicializar Autenticação
useEffect(() => {
const initAuth = async () => {
const token = import.meta.env.VITE_INITIAL_AUTH_TOKEN;
if (token) {
try { await signInWithCustomToken(auth, token); } catch (e) { }
}
};
initAuth();
const unsubscribe = onAuthStateChanged(auth, (currentUser) => {
setUser(currentUser);
currentUser ? setView('dashboard') : setView('auth');
setLoading(false);
});
return () => unsubscribe();
}, []);
// 2. Dados em Tempo Real (Roupas e Looks)
useEffect(() => {
if (!user) return;
// Roupas
const clothesCol = collection(db, 'artifacts', appId, 'users', user.uid, 'clothes');
const unsubClothes = onSnapshot(clothesCol, (snap) => {
setClothes(snap.docs.map(d => ({ id: d.id, ...d.data() })));
}, (err) => console.error(err));
// Looks
const looksCol = collection(db, 'artifacts', appId, 'users', user.uid, 'looks');
const unsubLooks = onSnapshot(looksCol, (snap) => {
setLooks(snap.docs.map(d => ({ id: d.id, ...d.data() })));
}, (err) => console.error(err));
// Profile
const profileDoc = doc(db, 'artifacts', appId, 'users', user.uid, 'profile', 'data');
const unsubProfile = onSnapshot(profileDoc, (snap) => {
if (snap.exists()) {
const data = snap.data();
setUserProfile(data);
if (data.settings) {
if (data.settings.language !== undefined) setLanguage(data.settings.language);
if (data.settings.darkMode !== undefined) setDarkMode(data.settings.darkMode);
if (data.settings.theme !== undefined) setTheme(data.settings.theme);
if (data.settings.notificationsEnabled !== undefined) setNotificationsEnabled(data.settings.notificationsEnabled);
if (data.settings.weatherAlerts !== undefined) setWeatherAlerts(data.settings.weatherAlerts);
}
}
else setUserProfile({});
}, (err) => console.error(err));
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}&current_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]);
const laundryClothes = useMemo(() => clothes.filter(c => c.status === 'laundry'), [clothes]);
const trashClothes = useMemo(() => clothes.filter(c => c.status === 'trash'), [clothes]);
const availableColors = useMemo(() => {
const colors = new Set(activeClothes.map(c => c.color).filter(Boolean));
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()) ||
(c.color || "").toLowerCase().includes(searchTerm.toLowerCase());
const matchesCategory = categoryFilter === 'Todos' || categoryFilter === t('all') || c.category === categoryFilter;
const matchesColor = !colorFilter || c.color === colorFilter;
let matchesAge = true;
if (ageFilter !== 'any') {
const ageInMs = new Date().getTime() - (c.createdAt || new Date().getTime());
const days = ageInMs / (1000 * 60 * 60 * 24);
if (ageFilter === 'month') matchesAge = days <= 30;
else if (ageFilter === '6months') matchesAge = days <= 180;
else if (ageFilter === '1year') matchesAge = days <= 365;
else if (ageFilter === 'older') matchesAge = days > 365;
}
return matchesSearch && matchesCategory && matchesColor && matchesAge;
});
}, [activeClothes, searchTerm, categoryFilter, colorFilter, ageFilter, t]);
// Ações de Itens
const handleItemAction = async (action, item) => {
if (!user) return;
const docRef = doc(db, 'artifacts', appId, 'users', user.uid, 'clothes', item.id || item);
switch (action) {
case 'favorite': await updateDoc(docRef, { favorite: !item.favorite }); break;
case 'trash': await updateDoc(docRef, { status: 'trash', trashedAt: new Date().getTime() }); break;
case 'restore': await updateDoc(docRef, { status: 'active', trashedAt: null }); break;
case 'laundry': await updateDoc(docRef, { status: 'laundry' }); break;
case 'clean': await updateDoc(docRef, { status: 'active' }); break;
case 'delete': if (window.confirm(t('confirmDeletePerm'))) await deleteDoc(docRef); break;
}
};
const saveItem = async (e) => {
e.preventDefault();
if (!user) return;
setLoading(true);
const formData = new FormData(e.target);
const itemData = {
name: formData.get('name'),
category: formData.get('category'),
color: formData.get('color'),
imageUrl: formData.get('imageUrl') || 'https://images.unsplash.com/photo-1521572267360-ee0c2909d518?q=80&w=500&auto=format&fit=crop',
status: 'active',
favorite: editingItem ? (editingItem.favorite || false) : false,
updatedAt: new Date().getTime()
};
try {
// Guardamos o id se for edição antes de apagar o estado
const currentEditId = editingItem ? editingItem.id : null;
// Navegação instantânea (Optimistic UI Update)
setEditingItem(null);
setImageUrlDraft('');
setView('closet');
if (currentEditId) {
const docRef = doc(db, 'artifacts', appId, 'users', user.uid, 'clothes', currentEditId);
await updateDoc(docRef, itemData);
} else {
itemData.createdAt = new Date().getTime();
const clothesCol = collection(db, 'artifacts', appId, 'users', user.uid, 'clothes');
await addDoc(clothesCol, itemData);
}
} catch (e) {
console.error(e);
} finally {
setLoading(false);
}
};
const saveLook = async (e) => {
e.preventDefault();
if (selectedForLook.length < 2) return;
setLoading(true);
const fd = new FormData(e.target);
const lookData = {
name: fd.get('lookName'),
items: selectedForLook,
updatedAt: new Date().getTime()
};
try {
if (editingLook) {
const docRef = doc(db, 'artifacts', appId, 'users', user.uid, 'looks', editingLook.id);
await updateDoc(docRef, lookData);
} else {
lookData.createdAt = new Date().getTime();
const looksCol = collection(db, 'artifacts', appId, 'users', user.uid, 'looks');
await addDoc(looksCol, lookData);
}
setSelectedForLook([]);
setEditingLook(null);
setView('outfits');
} catch (e) { console.error(e); }
finally { setLoading(false); }
};
const deleteLook = async (id) => {
if (!window.confirm(t('confirmDeleteLook'))) return;
const docRef = doc(db, 'artifacts', appId, 'users', user.uid, 'looks', id);
await deleteDoc(docRef);
};
const handleAuth = async (e) => {
e.preventDefault();
setAuthError('');
setLoading(true);
const fd = new FormData(e.target);
const email = fd.get('email');
const password = fd.get('password');
try {
if (authMode === 'login') await signInWithEmailAndPassword(auth, email, password);
else await createUserWithEmailAndPassword(auth, email, password);
} catch (err) {
console.error(err);
if (err.code === 'auth/operation-not-allowed') {
setAuthError(t('authErrorDisabled'));
} else {
setAuthError(err.message);
}
} finally { setLoading(false); }
};
const emptyTrashPermanently = async () => {
if (!user || !window.confirm(t('confirmEmptyTrash'))) return;
setLoading(true);
try {
const batch = writeBatch(db);
trashClothes.forEach(item => {
const docRef = doc(db, 'artifacts', appId, 'users', user.uid, 'clothes', item.id);
batch.delete(docRef);
});
await batch.commit();
} catch (e) { console.error(e); }
finally { setLoading(false); }
};
const clearAllToTrash = async () => {
if (!user || !window.confirm(t('confirmClearAll'))) return;
setLoading(true);
try {
const batch = writeBatch(db);
activeClothes.forEach(item => {
const docRef = doc(db, 'artifacts', appId, 'users', user.uid, 'clothes', item.id);
batch.update(docRef, { status: 'trash', trashedAt: new Date().getTime() });
});
await batch.commit();
} catch (e) { console.error(e); }
finally { setLoading(false); }
};
const handleProfileImageUpload = (e) => {
const file = e.target.files[0];
if (!file || !user) return;
const reader = new FileReader();
reader.onload = (event) => {
const img = new Image();
img.onload = async () => {
const canvas = document.createElement('canvas');
const MAX_SIZE = 400;
let width = img.width;
let height = img.height;
if (width > height) {
if (width > MAX_SIZE) {
height *= MAX_SIZE / width;
width = MAX_SIZE;
}
} else {
if (height > MAX_SIZE) {
width *= MAX_SIZE / height;
height = MAX_SIZE;
}
}
canvas.width = width;
canvas.height = height;
const ctx = canvas.getContext('2d');
ctx.drawImage(img, 0, 0, width, height);
const base64Data = canvas.toDataURL('image/jpeg', 0.8);
try {
const profileDoc = doc(db, 'artifacts', appId, 'users', user.uid, 'profile', 'data');
await setDoc(profileDoc, { avatar: base64Data }, { merge: true });
} catch (err) {
console.error("Error uploading image:", err);
}
};
img.src = event.target.result;
};
reader.readAsDataURL(file);
};
const saveProfile = async (e) => {
e.preventDefault();
setSavingProfile(true);
const fd = new FormData(e.target);
try {
const profileDoc = doc(db, 'artifacts', appId, 'users', user.uid, 'profile', 'data');
const dobDay = fd.get('dobDay');
const dobMonth = fd.get('dobMonth');
const dobYear = fd.get('dobYear');
let dob = fd.get('dob') || '';
if (dobDay && dobMonth && dobYear) {
dob = `${dobYear}-${dobMonth}-${dobDay}`;
}
// Perform optimistc setDoc without blocking the UI
setDoc(profileDoc, {
username: fd.get('username') || '',
fullName: fd.get('fullName') || '',
dob: dob,
bio: fd.get('bio') || '',
location: fd.get('location') || ''
}, { merge: true }).catch(err => {
console.error(err);
});
} catch (err) {
console.error(err);
} finally {
// Re-enable the button shortly after for smooth optimistic UI
setTimeout(() => {
setSavingProfile(false);
}, 600);
}
};
if (loading && !user) return <div className="h-screen flex items-center justify-center bg-primary-50 dark:bg-gray-950"><Loader2 className="animate-spin text-primary-600" size={40} /></div>;
if (view === 'auth') {
return (
<div className={`min-h-screen bg-gradient-to-br from-primary-100 via-white to-purple-50 dark:from-gray-950 dark:to-gray-900 flex items-center justify-center p-6 text-gray-900 ${darkMode ? 'dark' : ''}`}>
<Card className="max-w-md w-full p-12 border-none shadow-2xl overflow-hidden" darkMode={darkMode}>
<div key={authMode} className="animate-custom-zoom">
<div className="text-center mb-10">
<div className="inline-flex p-5 bg-primary-600 rounded-[2rem] shadow-2xl shadow-primary-600/40 mb-6 transition-all duration-300">
{authMode === 'login' ? <Shirt className="text-white w-12 h-12" /> : <UserCircle className="text-white w-12 h-12" />}
</div>
<h1 className="text-5xl font-black tracking-tighter italic">MyCloset</h1>
</div>
{authError && <div className="mb-6 p-4 bg-red-50 text-red-600 text-[10px] rounded-2xl flex items-center gap-2 font-black uppercase tracking-widest border border-red-100"><AlertCircle size={16} /> {authError}</div>}
<form onSubmit={handleAuth} className="space-y-4">
<input name="email" type="email" placeholder={t('emailPlaceholder')} required className="w-full p-5 rounded-2xl bg-gray-50 dark:bg-gray-800 border-none focus:ring-2 focus:ring-primary-500 outline-none font-bold" />
<input name="password" type="password" placeholder={t('passwordPlaceholder')} required className="w-full p-5 rounded-2xl bg-gray-50 dark:bg-gray-800 border-none focus:ring-2 focus:ring-primary-500 outline-none font-bold" />
<button className="w-full py-5 bg-primary-600 text-white rounded-[2rem] font-black text-lg shadow-2xl hover:scale-[1.02] active:scale-95 transition-all">
{authMode === 'login' ? t('loginBtn') : t('registerBtn')}
</button>
</form>
<div className="mt-10 text-center">
<button type="button" onClick={() => setAuthMode(authMode === 'login' ? 'register' : 'login')} className="text-gray-400 font-black text-[10px] uppercase tracking-[0.3em] hover:text-primary-600 transition-colors text-inherit">
{authMode === 'login' ? t('createAccount') : t('haveAccount')}
</button>
</div>
</div>
</Card>
</div>
);
}
return (
<div className={`min-h-screen flex transition-all duration-700 ${darkMode ? 'bg-gray-950 text-white dark' : 'bg-[#FDFDFF] text-gray-900'}`}>
{/* Sidebar - Design Futurista */}
<aside className={`
fixed md:relative inset-y-0 left-0 z-[100] transition-all duration-500 ease-in-out border-r overflow-hidden
${darkMode ? 'bg-gray-900/80 border-gray-800' : 'bg-white border-gray-100'}
${sidebarOpen ? 'w-80 translate-x-0' : 'w-0 -translate-x-full md:w-0 md:opacity-0'}
`}>
<div className="p-10 h-full flex flex-col backdrop-blur-xl">
<button onClick={() => setView('closet')} className="flex items-center gap-4 mb-16 hover:scale-[1.02] transition-transform text-left cursor-pointer w-full">
<div className="p-3 bg-primary-600 rounded-2xl shadow-xl shadow-primary-600/30">
<Shirt className="text-white" size={24} />
</div>
<span className="text-3xl font-black tracking-tighter italic">MyCloset</span>
</button>
<nav className="flex-1 space-y-3">
{[
{ id: 'dashboard', label: t('dashboard'), icon: LayoutDashboard },
{ id: 'closet', label: t('closet'), icon: Shirt },
{ id: 'laundry', label: t('laundry'), icon: Droplets },
{ id: 'outfits', label: t('outfits'), icon: Sparkles },
{ id: 'settings', label: t('settings'), icon: Settings },
].map(item => (
<button
key={item.id}
onClick={() => setView(item.id)}
className={`w-full flex items-center gap-4 px-6 py-4 rounded-2xl transition-all font-black text-[11px] uppercase tracking-widest ${view === item.id ? 'bg-primary-600 text-white shadow-2xl shadow-primary-600/30 scale-105' : 'opacity-40 hover:opacity-100 hover:bg-primary-500/5'}`}
>
<item.icon size={20} />
<span>{item.label}</span>
</button>
))}
</nav>
<div className="mt-auto pt-10 border-t border-inherit">
<button onClick={() => setView('profile')} className="w-full flex items-center gap-4 mb-8 px-2 text-left hover:bg-gray-100 dark:hover:bg-gray-800 py-3 rounded-2xl transition-all cursor-pointer">
<div className={`w-12 h-12 rounded-2xl shrink-0 flex items-center justify-center font-black text-white shadow-xl overflow-hidden ${darkMode ? 'bg-primary-500' : 'bg-primary-600'}`}>
{userProfile?.avatar ? (
<img src={userProfile.avatar} className="w-full h-full object-cover" alt="Avatar" />
) : (
(userProfile?.fullName?.[0] || userProfile?.username?.[0] || user?.email?.[0] || 'U').toUpperCase()
)}
</div>
<div className="flex-1 min-w-0">
<p className="text-sm font-black truncate">{userProfile?.username || userProfile?.fullName || user?.email?.split('@')[0] || t('userTitle')}</p>
<Badge variant="success">{t('online')}</Badge>
</div>
</button>
<button onClick={() => signOut(auth)} className="w-full py-4 text-red-500 font-black uppercase tracking-widest text-[10px] hover:bg-red-500/10 rounded-2xl transition-all flex items-center justify-center gap-3">
<LogOut size={16} /> {t('logout')}
</button>
</div>
</div>
</aside>
{/* Área Principal */}
<main className="flex-1 flex flex-col h-screen overflow-hidden">
{/* Header Superior */}
<header className={`h-24 shrink-0 flex items-center justify-between px-8 md:px-12 transition-all border-b border-inherit ${darkMode ? 'bg-gray-950/50' : 'bg-white/50'} backdrop-blur-xl`}>
<div className="flex items-center gap-6">
<button onClick={() => setSidebarOpen(!sidebarOpen)} className={`p-3 rounded-2xl transition-all border ${darkMode ? 'bg-gray-800 border-gray-700' : 'bg-gray-50 border-gray-200'}`}>
{sidebarOpen ? <PanelLeftClose size={24} /> : <PanelLeftOpen size={24} />}
</button>
<h2 className="text-3xl font-black tracking-tighter">
{view === 'dashboard' && t('overview')}
{view === 'closet' && t('myCloset')}
{view === 'laundry' && t('laundry')}
{view === 'outfits' && t('outfitsAndStyle')}
{view === 'settings' && t('settings')}
{view === 'profile' && t('profileInfo')}
</h2>
</div>
<div className="flex items-center gap-4">
<div className="flex bg-gray-100 dark:bg-gray-800 p-1.5 rounded-2xl">
<button onClick={() => handleDarkModeToggle(false)} className={`p-2 rounded-xl ${!darkMode ? 'bg-white shadow-md text-primary-600' : 'text-gray-500'}`}><Sun size={18} /></button>
<button onClick={() => handleDarkModeToggle(true)} className={`p-2 rounded-xl ${darkMode ? 'bg-gray-900 shadow-md text-primary-400' : 'text-gray-500'}`}><Moon size={18} /></button>
</div>
<button onClick={() => { setEditingItem(null); setImageUrlDraft(''); setView('add'); setEditingLook(null); setSelectedForLook([]); }} className="p-4 bg-primary-600 text-white rounded-2xl shadow-xl shadow-primary-600/30 hover:scale-105 active:scale-95 transition-all">
<Plus size={24} />
</button>
</div>
</header>
{/* Conteúdo Dinâmico */}
<div className="flex-1 overflow-y-auto p-8 md:p-12 space-y-12">
{/* DASHBOARD */}
{view === 'dashboard' && (
<div className="space-y-12 animate-in fade-in duration-700">
<div className="grid grid-cols-1 md:grid-cols-4 gap-8">
{[
{ label: t('readyClothes'), val: activeClothes.length, icon: Shirt, col: 'primary' },
{ label: t('inLaundry'), val: laundryClothes.length, icon: Droplets, col: 'blue' },
{ label: t('myLooks'), val: looks.length, icon: Sparkles, col: 'purple' },
{ label: t('favorites'), val: activeClothes.filter(c => c.favorite).length, icon: Heart, col: 'rose' },
].map((s, i) => (
<Card key={i} className="p-8 group hover:-translate-y-2" darkMode={darkMode}>
<div className={`w-14 h-14 rounded-2xl flex items-center justify-center mb-6 shadow-inner ${darkMode ? 'bg-gray-700 text-primary-400' : 'bg-primary-50 text-primary-600'}`}>
<s.icon size={28} />
</div>
<p className="text-[10px] font-black uppercase tracking-widest opacity-40 mb-1">{s.label}</p>
<h4 className="text-4xl font-black tracking-tight">{s.val}</h4>
</Card>
))}
</div>
<div className="grid grid-cols-1 lg:grid-cols-3 gap-8">
<Card className="lg:col-span-2 p-10 bg-primary-600 text-white border-none shadow-2xl shadow-primary-600/40 relative overflow-hidden" darkMode={darkMode}>
<div className="relative z-10 flex flex-col justify-between h-full">
<div>
<div className="flex items-center gap-3 mb-4">
<CloudSun size={28} className="text-primary-200" />
<Badge variant="warning">{weatherData ? weatherData.name : t('todayIn')}</Badge>
</div>
<h3 className="text-5xl font-black tracking-tighter mb-4">
{weatherData ? `${weatherData.currentTemp}°C Atual • Média ${weatherData.avgTemp}°C` : t('weatherUpdate')}
</h3>
<p className="text-primary-100 text-lg font-medium max-w-lg leading-relaxed">
{weatherData ? `O dia de hoje tem máximas de ${weatherData.maxTemp}°C e mínimas de ${weatherData.minTemp}°C. ${t('weatherMsg')}` : t('weatherMsg')}
</p>
</div>
<div className="mt-10 flex gap-4">
{activeClothes.filter(c => c.category === 'Tops').slice(0, 2).map(c => (
<div key={c.id} className="w-16 h-16 rounded-xl overflow-hidden border-2 border-primary-400">
<img src={c.imageUrl} className="w-full h-full object-cover" alt="" />
</div>
))}
<button onClick={() => setView('closet')} className="flex items-center gap-2 font-black uppercase text-xs tracking-widest hover:translate-x-2 transition-transform">
{t('exploreSuggestions')} <ArrowRight size={18} />
</button>
</div>
</div>
<CloudSun size={350} className="absolute -bottom-20 -right-20 text-white/10" />
</Card>
<Card className="p-8" darkMode={darkMode}>
<h3 className="text-lg font-black tracking-tight mb-8 flex items-center gap-2 text-inherit"><PieChart size={20} /> {t('topColors')}</h3>
<div className="space-y-6">
{colorStats.length > 0 ? colorStats.map(stat => (
<div key={stat.color} className="space-y-2">
<div className="flex justify-between text-[10px] font-black uppercase tracking-widest opacity-50">
<span>{stat.color}</span>
<span>{stat.percentage}% ({stat.count})</span>
</div>
<div className="h-2 w-full bg-gray-100 dark:bg-gray-700 rounded-full overflow-hidden">
<div className="h-full bg-primary-600" style={{ width: `${stat.percentage}%` }}></div>
</div>
</div>
)) : (
<p className="text-xs opacity-50 italic">Adicione cores aos seus itens.</p>
)}
</div>
</Card>
</div>
</div>
)}
{/* ARMÁRIO */}
{view === 'closet' && (
<div className="space-y-10 animate-in slide-in-from-bottom-8 duration-700">
<div className="flex flex-col xl:flex-row gap-8 items-center justify-between">
<div className="relative w-full max-w-2xl">
<Search className="absolute left-6 top-1/2 -translate-y-1/2 text-gray-400" size={24} />
<input
placeholder={t('searchPlaceholder')}
className={`w-full pl-16 pr-8 py-6 rounded-[2rem] shadow-inner outline-none border-none focus:ring-4 focus:ring-primary-500/10 font-bold text-lg ${darkMode ? 'bg-gray-800' : 'bg-gray-100'}`}
onChange={(e) => setSearchTerm(e.target.value)}
/>
</div>
<div className="flex gap-3 w-full xl:w-auto">
<button
onClick={() => setShowClosetFilters(true)}
className="flex items-center gap-3 px-8 py-4 bg-primary-600 text-white rounded-[2rem] font-black uppercase text-[10px] tracking-widest shadow-xl shadow-primary-600/30 hover:scale-105 transition-all"
>
<Filter size={18} /> {t('advancedFilters')}
{(colorFilter || ageFilter !== 'any' || (categoryFilter !== 'Todos' && categoryFilter !== t('all'))) && (
<span className="w-2 h-2 rounded-full bg-white animate-pulse"></span>
)}
</button>
</div>
</div>
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 2xl:grid-cols-4 gap-10">
{filteredClothes.map(item => (
<div key={item.id} className="group">
<Card className="overflow-hidden p-0 h-[480px] relative border-none hover:shadow-2xl transition-all duration-500" darkMode={darkMode}>
<img src={item.imageUrl} className="w-full h-full object-cover transition-transform duration-1000 group-hover:scale-110" alt={item.name} />
<div className="absolute inset-0 bg-gradient-to-t from-black/80 via-transparent opacity-0 group-hover:opacity-100 transition-all duration-300 flex flex-col justify-end p-6 pb-[136px] text-white z-10 pointer-events-none">
<div className="grid grid-cols-2 gap-2 pointer-events-auto">
<button onClick={() => { setEditingItem(item); setImageUrlDraft(''); setView('edit'); }} className="py-3 px-2 bg-white text-primary-600 rounded-xl font-black text-[9px] uppercase flex items-center justify-center gap-1.5 hover:bg-primary-50"><Edit2 size={14} /> {t('edit')}</button>
<button onClick={() => handleItemAction('laundry', item)} className="py-3 px-2 bg-blue-600 text-white rounded-xl font-black text-[9px] uppercase flex items-center justify-center gap-1.5 hover:bg-blue-700"><Droplets size={14} /> {t('makeDirty')}</button>
<button onClick={() => handleItemAction('trash', item)} className="py-3 px-2 bg-red-600/20 text-red-100 backdrop-blur-md rounded-xl font-black text-[9px] uppercase hover:bg-red-600 transition-colors col-span-2">{t('moveToTrash')}</button>
</div>
</div>
<div className="absolute top-6 left-6 z-20"><Badge>{item.category}</Badge></div>
<div className="absolute top-6 right-6 z-20 pointer-events-auto">
<button onClick={() => handleItemAction('favorite', item)} className={`p-3 rounded-2xl shadow-xl backdrop-blur-md transition-all ${item.favorite ? 'bg-rose-500 text-white' : 'bg-white/90 text-gray-400'}`}>
<Heart size={18} fill={item.favorite ? "currentColor" : "none"} />
</button>
</div>
<div className="absolute bottom-6 left-6 right-6 p-6 bg-white/95 dark:bg-gray-900/95 backdrop-blur-2xl rounded-3xl shadow-2xl transform transition-transform group-hover:-translate-y-2 z-20 pointer-events-auto">
<h4 className="text-xl font-black tracking-tighter truncate">{item.name}</h4>
<div className="flex items-center gap-3 mt-2">
<div className="w-4 h-4 rounded-full border border-black/5" style={{ backgroundColor: (item.color || "").toLowerCase() }}></div>
<span className="text-[10px] font-black opacity-40 uppercase tracking-widest">{item.color}</span>
</div>
</div>
</Card>
</div>
))}
</div>
</div>
)}
{/* LAVANDARIA */}
{view === 'laundry' && (
<div className="space-y-12 animate-in fade-in duration-700">
<div className="text-center max-w-2xl mx-auto space-y-4 text-inherit">
<div className="w-20 h-20 bg-blue-100 dark:bg-blue-900/30 rounded-[2rem] flex items-center justify-center mx-auto text-blue-600 shadow-inner">
<Droplets size={40} />
</div>
<h3 className="text-4xl font-black tracking-tight">{t('laundryBasket')}</h3>
<p className="opacity-60 font-medium">{t('laundryMsg')}</p>
</div>
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-8">
{laundryClothes.map(item => (
<Card key={item.id} className="p-6 flex items-center gap-6 border-blue-100" darkMode={darkMode}>
<img src={item.imageUrl} className="w-20 h-20 rounded-2xl object-cover shadow-lg" alt="" />
<div className="flex-1 min-w-0">
<p className="font-black truncate">{item.name}</p>
<Badge variant="warning">{t('washing')}</Badge>
</div>
<button onClick={() => handleItemAction('clean', item)} className="p-4 bg-green-500 text-white rounded-2xl shadow-lg shadow-green-500/30 hover:scale-110 transition-all">
<CheckCircle2 size={24} />
</button>
</Card>
))}
{laundryClothes.length === 0 && (
<div className="col-span-full py-20 text-center opacity-20 font-black uppercase tracking-[0.5em] text-sm">{t('emptyBasket')}</div>
)}
</div>
</div>
)}
{/* LOOKS */}
{view === 'outfits' && (
<div className="space-y-12 animate-in fade-in duration-700 pb-20">
<div className="grid grid-cols-1 lg:grid-cols-3 gap-12">
<div className="lg:col-span-1 space-y-8">
<Card className="p-8 border-primary-200" darkMode={darkMode}>
<h3 className="text-2xl font-black tracking-tighter mb-6 flex items-center gap-3 text-inherit">
<Sparkles className="text-primary-600" /> {editingLook ? t('editLook') || 'Editar Look' : t('createNewLook')}
</h3>
<form key={editingLook ? editingLook.id : 'new'} onSubmit={saveLook} className="space-y-6">
<input name="lookName" placeholder={t('lookName')} defaultValue={editingLook?.name || ''} required className={`w-full p-4 rounded-xl border-none shadow-inner font-bold ${darkMode ? 'bg-gray-700' : 'bg-gray-100'}`} />
<div className="space-y-3">
<p className="text-[10px] font-black uppercase opacity-40 tracking-widest">{t('selectedPieces')} ({selectedForLook.length})</p>
<div className="flex flex-wrap gap-2">
{selectedForLook.map(id => {
const item = clothes.find(c => c.id === id);
return (
<div key={id} className="relative group">
<img src={item?.imageUrl} className="w-12 h-12 rounded-lg object-cover border-2 border-primary-500" alt="" />
<button type="button" onClick={() => setSelectedForLook(selectedForLook.filter(i => i !== id))} className="absolute -top-1 -right-1 bg-red-500 text-white rounded-full p-0.5 opacity-0 group-hover:opacity-100 transition-opacity"><X size={10} /></button>
</div>
);
})}
{selectedForLook.length === 0 && <p className="text-xs text-gray-400 italic">{t('selectPieces')}</p>}
</div>
</div>
<div className="flex gap-4">
{editingLook && (
<button type="button" onClick={() => { setEditingLook(null); setSelectedForLook([]); }} className="flex-1 py-4 font-black uppercase text-[10px] tracking-widest text-gray-500 hover:text-gray-900 transition-colors">{t('cancel')}</button>
)}
<button disabled={selectedForLook.length < 2} className="flex-[2] py-4 bg-primary-600 text-white rounded-2xl font-black uppercase tracking-widest text-xs shadow-xl shadow-primary-600/30 disabled:opacity-30 transition-all">
{editingLook ? t('saveChanges') || 'Guardar' : t('saveLook')}
</button>
</div>
</form>
</Card>
<div className="space-y-4">
<p className="text-xs font-black uppercase opacity-50 tracking-widest px-2">{t('closetLabel')}</p>
<div className="grid grid-cols-4 gap-3 max-h-96 overflow-y-auto pr-2 custom-scrollbar">
{activeClothes.map(c => (
<button key={c.id} onClick={() => !selectedForLook.includes(c.id) && setSelectedForLook([...selectedForLook, c.id])} className={`relative rounded-xl overflow-hidden aspect-square border-2 transition-all ${selectedForLook.includes(c.id) ? 'border-primary-600 scale-90' : 'border-transparent hover:border-primary-200'}`}>
<img src={c.imageUrl} className="w-full h-full object-cover" alt="" />
{selectedForLook.includes(c.id) && <div className="absolute inset-0 bg-primary-600/40 flex items-center justify-center text-white"><Check size={20} /></div>}
</button>
))}
</div>
</div>
</div>
<div className="lg:col-span-2 space-y-8">
<h3 className="text-2xl font-black tracking-tighter flex items-center gap-3 px-2 text-inherit"><History className="text-gray-400" /> {t('lookHistory')}</h3>
<div className="grid grid-cols-1 md:grid-cols-2 gap-8">
{looks.map(look => (
<Card key={look.id} className="p-8 group hover:shadow-2xl transition-all border-none shadow-md" darkMode={darkMode}>
<div className="flex justify-between items-start mb-6">
<div className="text-inherit">
<h4 className="text-xl font-black tracking-tight">{look.name}</h4>
<p className="text-[10px] opacity-40 font-bold uppercase tracking-widest">{look.items.length} {t('pieces')} {new Date(look.createdAt).toLocaleDateString()}</p>
</div>
<div className="flex gap-2">
<button onClick={() => { setEditingLook(look); setSelectedForLook(look.items); }} className="p-2 text-gray-300 hover:text-primary-500 transition-colors"><Edit2 size={18} /></button>
<button onClick={() => deleteLook(look.id)} className="p-2 text-gray-300 hover:text-red-500 transition-colors"><Trash size={18} /></button>
</div>
</div>
<div className="flex -space-x-4">
{look.items.map(itemId => {
const item = clothes.find(c => c.id === itemId);
return (
<div key={itemId} className="w-20 h-20 rounded-2xl border-4 border-white dark:border-gray-800 overflow-hidden shadow-lg transform group-hover:rotate-6 transition-transform">
<img src={item?.imageUrl} className="w-full h-full object-cover" alt="" />
</div>
);
})}
</div>
</Card>
))}
</div>
</div>
</div>
</div>
)}
{/* ADICIONAR / EDITAR */}
{(view === 'add' || view === 'edit') && (
<div className="max-w-4xl mx-auto animate-in zoom-in-95 duration-500">
<div className="grid grid-cols-1 lg:grid-cols-2 gap-12 items-start">
<div className="space-y-8">
<h3 className="text-5xl font-black tracking-tighter text-inherit">{editingItem ? t('edit') : t('newItem')}</h3>
<Card className="aspect-[3/4] overflow-hidden shadow-2xl relative" darkMode={darkMode}>
{editingItem?.imageUrl || imageUrlDraft.startsWith('http') ? (
<img src={imageUrlDraft || editingItem?.imageUrl} className="w-full h-full object-cover" alt="" />
) : (
<div className="h-full flex flex-col items-center justify-center opacity-10">
<ImageIcon size={100} />
<p className="font-black uppercase tracking-[0.5em] mt-6">{t('preview')}</p>
</div>
)}
</Card>
</div>
<Card className="p-10 shadow-2xl" darkMode={darkMode}>
<form onSubmit={saveItem} className="space-y-8">
<Input label={t('name')} name="name" defaultValue={editingItem?.name} required />
<div className="grid grid-cols-2 gap-6">
<div className="space-y-2">
<label className="text-[10px] font-black uppercase opacity-40 tracking-widest ml-1 text-inherit">{t('category')}</label>
<select name="category" defaultValue={editingItem?.category || 'Tops'} className={`w-full p-5 rounded-2xl border-none outline-none focus:ring-4 focus:ring-primary-500/10 font-bold ${darkMode ? 'bg-gray-700 text-white' : 'bg-gray-100'}`}>
<option>{t('tops')}</option><option>{t('bottoms')}</option><option>{t('footwear')}</option><option>{t('coats')}</option><option>{t('accessories')}</option>
</select>
</div>
<Input label={t('color')} name="color" defaultValue={editingItem?.color} required />
</div>
<Input label={t('imageUrl')} name="imageUrl" defaultValue={editingItem?.imageUrl} onChange={(v) => setImageUrlDraft(v)} />
<div className="flex gap-4 pt-6">
<button type="button" onClick={() => { setEditingItem(null); setImageUrlDraft(''); setView('closet'); }} className="flex-1 font-black uppercase text-[10px] opacity-40 hover:opacity-100 tracking-widest transition-all text-inherit">{t('cancel')}</button>
<button type="submit" className="flex-1 py-5 bg-primary-600 text-white rounded-[2rem] font-black uppercase tracking-widest text-[10px] shadow-2xl shadow-primary-600/40 hover:scale-[1.02] active:scale-95 transition-all">
{editingItem ? t('save') : t('register')}
</button>
</div>
</form>
</Card>
</div>
</div>
)}
{/* PERFIL */}
{view === 'profile' && (
<div className="max-w-4xl mx-auto space-y-12 animate-in fade-in duration-700 pb-20">
<Card className="p-10 border-primary-100 relative overflow-hidden" darkMode={darkMode}>
<div className="flex items-center gap-8 relative z-10 text-inherit">
<div className="w-24 h-24 rounded-[2.5rem] bg-primary-600 flex items-center justify-center text-white text-4xl font-black shadow-2xl relative overflow-hidden group cursor-pointer">
{userProfile?.avatar ? (
<img src={userProfile.avatar} className="w-full h-full object-cover" alt="Profile" />
) : (
<span>{(userProfile?.fullName?.[0] || userProfile?.username?.[0] || user?.email?.[0] || 'U').toUpperCase()}</span>
)}
<label className="absolute inset-0 bg-black/50 flex flex-col items-center justify-center opacity-0 group-hover:opacity-100 transition-opacity cursor-pointer text-white">
<Edit2 size={20} />
<span className="text-[8px] uppercase font-black mt-1 tracking-widest">{t('edit')}</span>
<input type="file" accept="image/*" className="hidden" onChange={handleProfileImageUpload} />
</label>
</div>
<div>
<h3 className="text-3xl font-black tracking-tighter">{userProfile?.fullName || t('yourAccount')}</h3>
<p className="opacity-60 font-bold text-sm">@{userProfile?.username || user?.email?.split('@')[0] || t('papMode')}</p>
</div>
</div>
</Card>
<Card className="p-8" darkMode={darkMode}>
<h3 className="text-xl font-black mb-6 flex items-center gap-3 text-inherit"><UserCircle className="text-primary-600" /> {t('profileInfo')}</h3>
<form onSubmit={saveProfile} className="space-y-6">
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
<Input label={t('username')} name="username" defaultValue={userProfile?.username || ''} placeholder="Ex: amari" />
<Input label={t('fullName')} name="fullName" defaultValue={userProfile?.fullName || ''} placeholder="Ex: Amari Rodriguez" />
<div className="space-y-2">
<label className="text-[10px] font-black uppercase opacity-40 tracking-widest ml-1 text-inherit">{t('dob')} {t('optional')}</label>
<div className="flex gap-2">
<select name="dobDay" defaultValue={userProfile?.dob?.split('-')[2] || ''} className={`flex-1 p-4 rounded-xl border-none outline-none focus:ring-2 focus:ring-primary-500 font-bold ${darkMode ? 'bg-gray-800 text-white' : 'bg-gray-50'}`}>
<option value="">DD</option>
{Array.from({ length: 31 }, (_, i) => String(i + 1).padStart(2, '0')).map(d => <option key={d} value={d}>{d}</option>)}
</select>
<select name="dobMonth" defaultValue={userProfile?.dob?.split('-')[1] || ''} className={`flex-1 p-4 rounded-xl border-none outline-none focus:ring-2 focus:ring-primary-500 font-bold ${darkMode ? 'bg-gray-800 text-white' : 'bg-gray-50'}`}>
<option value="">MM</option>
{Array.from({ length: 12 }, (_, i) => String(i + 1).padStart(2, '0')).map(m => <option key={m} value={m}>{m}</option>)}
</select>
<select name="dobYear" defaultValue={userProfile?.dob?.split('-')[0] || ''} className={`flex-[1.5] p-4 rounded-xl border-none outline-none focus:ring-2 focus:ring-primary-500 font-bold ${darkMode ? 'bg-gray-800 text-white' : 'bg-gray-50'}`}>
<option value="">YYYY</option>
{Array.from({ length: 100 }, (_, i) => new Date().getFullYear() - i).map(y => <option key={y} value={y}>{y}</option>)}
</select>
</div>
</div>
<Input label={`${t('bio')} ${t('optional')}`} name="bio" defaultValue={userProfile?.bio || ''} placeholder="..." />
<Input label="Localidade" name="location" defaultValue={userProfile?.location || ''} placeholder="Ex: Lisboa, Portugal" />
</div>
<button disabled={savingProfile} type="submit" className="w-full py-4 bg-primary-600 text-white rounded-xl font-black uppercase text-[10px] tracking-widest shadow-xl shadow-primary-600/30 disabled:opacity-50 hover:scale-[1.01] transition-all">
{savingProfile ? t('saving') : t('save')}
</button>
</form>
</Card>
</div>
)}
{/* DEFINIÇÕES */}
{view === 'settings' && (
<div className="max-w-4xl mx-auto space-y-12 animate-in fade-in duration-700 pb-20">
{/* Preferências */}
<div className="flex flex-col gap-8">
<Card className="p-8" darkMode={darkMode}>
<h3 className="text-xl font-black mb-6 flex items-center gap-3 text-inherit"><Settings className="text-primary-600" /> {t('preferences')}</h3>
<div className="space-y-6">
<div className="flex items-center justify-between">
<div>
<p className="font-bold text-inherit">{t('darkMode')}</p>
<p className="text-[10px] uppercase tracking-widest opacity-50 text-inherit">{t('interfaceAppearance')}</p>
</div>
<button onClick={() => handleDarkModeToggle(!darkMode)} className={`w-14 h-8 rounded-full transition-colors relative ${darkMode ? 'bg-primary-600' : 'bg-gray-200'}`}>
<div className={`w-6 h-6 rounded-full bg-white absolute top-1 transition-all ${darkMode ? 'left-7' : 'left-1'}`}></div>
</button>
</div>
<div className="flex items-center justify-between">
<div>
<p className="font-bold text-inherit">{t('themeColor') || 'Cor do Tema'}</p>
<p className="text-[10px] uppercase tracking-widest opacity-50 text-inherit">{t('personalizeColor') || 'Personalize a cor'}</p>
</div>
<div className="flex gap-2">
{[
{ id: 'theme-indigo', color: '#4f46e5' },
{ id: 'theme-rose', color: '#e11d48' },
{ id: 'theme-emerald', color: '#10b981' },
{ id: 'theme-amber', color: '#f59e0b' },
{ id: 'theme-slate', color: '#64748b' }
].map(tObj => (
<button
key={tObj.id}
onClick={() => handleThemeChange(tObj.id)}
className={`w-6 h-6 rounded-full transition-all flex items-center justify-center ${theme === tObj.id ? 'ring-2 ring-offset-2 ring-offset-white dark:ring-offset-gray-900 ring-primary-500 scale-110' : 'hover:scale-110'}`}
style={{ backgroundColor: tObj.color }}
>
{theme === tObj.id && <Check size={12} className="text-white" />}
</button>
))}
</div>
</div>
<div className="flex items-center justify-between">
<div>
<p className="font-bold text-inherit flex items-center gap-2">{t('notifications')}</p>
<p className="text-[10px] uppercase tracking-widest opacity-50 text-inherit">{t('lookReminders')}</p>
</div>
<button onClick={() => handleNotificationsToggle(!notificationsEnabled)} className={`w-14 h-8 rounded-full transition-colors relative ${notificationsEnabled ? 'bg-primary-600' : 'bg-gray-200'}`}>
<div className={`w-6 h-6 rounded-full bg-white absolute top-1 transition-all ${notificationsEnabled ? 'left-7' : 'left-1'}`}></div>
</button>
</div>
<div className="flex items-center justify-between">
<div>
<p className="font-bold text-inherit flex items-center gap-2">{t('weatherAlerts')}</p>
<p className="text-[10px] uppercase tracking-widest opacity-50 text-inherit">{t('weatherSuggestions')}</p>
</div>
<button onClick={() => handleWeatherAlertsToggle(!weatherAlerts)} className={`w-14 h-8 rounded-full transition-colors relative ${weatherAlerts ? 'bg-primary-600' : 'bg-gray-200'}`}>
<div className={`w-6 h-6 rounded-full bg-white absolute top-1 transition-all ${weatherAlerts ? 'left-7' : 'left-1'}`}></div>
</button>
</div>
<div className="flex items-center justify-between pt-4 border-t border-gray-100 dark:border-gray-800">
<div>
<p className="font-bold text-inherit">{t('appLanguage')}</p>
<p className="text-[10px] uppercase tracking-widest opacity-50 text-inherit">
{language === 'PT' ? '🇵🇹 ' + t('portuguese') :
language === 'EN' ? '🇬🇧 ' + t('english') :
language === 'ES' ? '🇪🇸 ' + t('spanish') :
language === 'FR' ? '🇫🇷 ' + t('french') :
language === 'DE' ? '🇩🇪 ' + t('german') : language}
</p>
</div>
<button onClick={() => setShowLangModal(true)} className="px-5 py-2 font-black text-[10px] uppercase tracking-widest bg-primary-50 text-primary-600 rounded-xl hover:bg-primary-100 transition-colors dark:bg-primary-900/40 dark:text-primary-400">
{t('edit')}
</button>
</div>
</div>
</Card>
<Card className="p-8" darkMode={darkMode}>
<h3 className="text-xl font-black mb-6 flex items-center gap-3 text-inherit"><Bell className="text-primary-600" /> {t('feedbackTitle') || 'Suporte e Feedback'}</h3>
<p className="opacity-60 text-sm font-medium mb-6">{t('feedbackDesc') || 'Tem alguma ideia, sugestão ou encontrou algum problema? Envie uma mensagem diretamente para nós!'}</p>
<form onSubmit={(e) => {
e.preventDefault();
const fd = new FormData(e.target);
const type = fd.get('type');
const msg = fd.get('message');
// Substitua pelo seu email real
const email = "faiker027@gmail.com";
window.location.href = `mailto:${email}?subject=${encodeURIComponent(`MyCloset Feedback: ${type}`)}&body=${encodeURIComponent(msg)}`;
e.target.reset();
}} className="space-y-4">
<div className="grid grid-cols-2 gap-4">
<label className="flex items-center gap-3 p-4 rounded-xl border border-gray-100 dark:border-gray-800 cursor-pointer hover:bg-gray-50 dark:hover:bg-gray-800 transition-colors">
<input type="radio" name="type" value="Ideia/Sugestão" defaultChecked className="text-primary-600 focus:ring-primary-500" />
<span className="font-bold text-sm text-inherit">Ideia / Sugestão</span>
</label>
<label className="flex items-center gap-3 p-4 rounded-xl border border-gray-100 dark:border-gray-800 cursor-pointer hover:bg-gray-50 dark:hover:bg-gray-800 transition-colors">
<input type="radio" name="type" value="Bug/Erro" className="text-primary-600 focus:ring-primary-500" />
<span className="font-bold text-sm text-inherit">Bug / Erro</span>
</label>
</div>
<textarea name="message" required placeholder="Escreva aqui a sua mensagem..." rows={4} className={`w-full p-4 rounded-xl border-none outline-none focus:ring-2 focus:ring-primary-500 font-bold resize-none ${darkMode ? 'bg-gray-800 text-white' : 'bg-gray-50'}`}></textarea>
<button type="submit" className="w-full py-4 bg-primary-600 text-white rounded-xl font-black uppercase text-[10px] tracking-widest shadow-xl shadow-primary-600/30 hover:scale-[1.01] transition-all">
Enviar Mensagem
</button>
</form>
</Card>
</div>
<div className="space-y-6">
<div className="flex items-center justify-between px-2 text-inherit">
<h3 className="text-xl font-black text-red-500 flex items-center gap-3 tracking-widest uppercase"><Trash2 size={24} /> {t('recycleBin')}</h3>
{trashClothes.length > 0 && <button onClick={emptyTrashPermanently} className="text-[10px] font-black text-red-500 uppercase tracking-widest hover:underline">{t('empty')}</button>}
</div>
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
{trashClothes.map(item => (
<Card key={item.id} className="p-4 flex items-center gap-5 border-red-50" darkMode={darkMode}>
<img src={item.imageUrl} className="w-16 h-16 rounded-2xl object-cover grayscale opacity-40" alt="" />
<div className="flex-1 min-w-0 text-inherit">
<p className="font-black text-sm truncate">{item.name}</p>
<p className="text-[10px] font-black text-red-400 uppercase tracking-tighter">{t('deleted')}</p>
</div>
<div className="flex gap-1">
<button onClick={() => handleItemAction('restore', item)} className="p-3 text-primary-600 hover:bg-primary-50 rounded-2xl transition-all"><RotateCcw size={18} /></button>
<button onClick={() => handleItemAction('delete', item.id)} className="p-3 text-red-600 hover:bg-red-50 rounded-2xl transition-all"><Trash size={18} /></button>
</div>
</Card>
))}
</div>
</div>
<Card className="p-10 border-red-200 bg-red-50/10" darkMode={darkMode}>
<div className="flex flex-col md:flex-row items-center justify-between gap-8">
<div className="text-inherit">
<h4 className="text-xl font-black text-red-700 flex items-center gap-3"><ShieldAlert /> {t('criticalZone')}</h4>
<p className="opacity-60 font-bold text-sm mt-2">{t('fullCleanActions')}</p>
</div>
<button onClick={clearAllToTrash} className="px-8 py-4 bg-red-600 text-white rounded-2xl font-black uppercase text-[10px] tracking-widest hover:bg-red-700 transition-all">{t('clearAll')}</button>
</div>
</Card>
</div>
)}
</div>
</main>
{/* Modal de Filtros Avançados */}
{showClosetFilters && (
<div className="fixed inset-0 z-[200] flex items-center justify-center bg-black/60 backdrop-blur-sm p-6" onClick={() => setShowClosetFilters(false)}>
<Card className="w-full max-w-lg p-8 animate-in zoom-in-95 flex flex-col max-h-[90vh]" darkMode={darkMode} onClick={e => e.stopPropagation()}>
<div className="flex items-center justify-between mb-8">
<h3 className="text-2xl font-black text-inherit flex items-center gap-3"><Filter size={24} className="text-primary-600" /> {t('advancedFilters')}</h3>
<button onClick={() => setShowClosetFilters(false)} className="p-2 bg-gray-100 dark:bg-gray-800 rounded-full hover:scale-110 transition-all text-inherit"><X size={20} /></button>
</div>
<div className="flex-1 overflow-y-auto space-y-8 pr-2 custom-scrollbar">
<div className="space-y-4">
<label className="text-[10px] font-black uppercase opacity-40 tracking-widest ml-1 text-inherit">{t('closet')}</label>
<div className="flex flex-wrap gap-2">
{[t('all'), t('tops'), t('bottoms'), t('footwear'), t('coats'), t('accessories')].map(cat => (
<button
key={cat}
onClick={() => setCategoryFilter(cat)}
className={`px-5 py-3 rounded-xl font-black text-[10px] uppercase tracking-widest transition-all ${categoryFilter === cat ? 'bg-primary-600 text-white shadow-xl shadow-primary-600/30' : (darkMode ? 'bg-gray-800 text-gray-400' : 'bg-gray-50 text-gray-500 shadow-sm border border-gray-100')} hover:scale-[1.02]`}
>
{cat}
</button>
))}
</div>
</div>
<div className="space-y-4">
<label className="text-[10px] font-black uppercase opacity-40 tracking-widest ml-1 text-inherit">{t('filterByColor')}</label>
<select
value={colorFilter}
onChange={(e) => setColorFilter(e.target.value)}
className={`w-full p-4 rounded-2xl border-none outline-none focus:ring-2 focus:ring-primary-500 font-bold ${darkMode ? 'bg-gray-800 text-white' : 'bg-gray-50'}`}
>
<option value="">{t('all')}</option>
{availableColors.map(c => <option key={c} value={c}>{c}</option>)}
</select>
</div>
<div className="space-y-4">
<label className="text-[10px] font-black uppercase opacity-40 tracking-widest ml-1 text-inherit">{t('filterByAge')}</label>
<div className="grid grid-cols-2 gap-2">
{[
{ id: 'any', label: t('anyAge') },
{ id: 'month', label: t('lessThanMonth') },
{ id: '6months', label: t('lessThan6Months') },
{ id: '1year', label: t('lessThanYear') },
{ id: 'older', label: t('older') }
].map(ageOpt => (
<button
key={ageOpt.id}
onClick={() => setAgeFilter(ageOpt.id)}
className={`px-4 py-3 rounded-xl font-bold text-xs transition-all ${ageFilter === ageOpt.id ? 'bg-primary-600 text-white shadow-xl shadow-primary-600/30' : (darkMode ? 'bg-gray-800 text-gray-400' : 'bg-gray-50 text-gray-500')} ${ageOpt.id === 'any' ? 'col-span-2' : ''}`}
>
{ageOpt.label}
</button>
))}
</div>
</div>
</div>
<div className="pt-8 flex gap-4 border-t mt-8 border-gray-100 dark:border-gray-800">
<button onClick={() => { setCategoryFilter('Todos'); setColorFilter(''); setAgeFilter('any'); }} className="flex-1 py-4 font-black uppercase text-[10px] tracking-widest text-gray-500 hover:text-gray-900 dark:hover:text-white transition-colors">{t('clearAll')}</button>
<button onClick={() => setShowClosetFilters(false)} className="flex-1 py-4 bg-primary-600 text-white rounded-2xl font-black uppercase text-[10px] tracking-widest shadow-xl shadow-primary-600/30 hover:scale-105 transition-all">{t('applyFilters')}</button>
</div>
</Card>
</div>
)}
{/* Modal de Idioma */}
{showLangModal && (
<div className="fixed inset-0 z-[200] flex items-center justify-center bg-black/60 backdrop-blur-sm p-6" onClick={() => setShowLangModal(false)}>
<Card className="w-full max-w-lg p-8 animate-in zoom-in-95" darkMode={darkMode} onClick={e => e.stopPropagation()}>
<h3 className="text-2xl font-black mb-8 text-center text-inherit">{t('appLanguage')}</h3>
<div className="grid grid-cols-2 md:grid-cols-3 gap-4">
{[
{ id: 'PT', flag: '🇵🇹', label: t('portuguese') },
{ id: 'EN', flag: '🇬🇧', label: t('english') },
{ id: 'ES', flag: '🇪🇸', label: t('spanish') },
{ id: 'FR', flag: '🇫🇷', label: t('french') },
{ id: 'DE', flag: '🇩🇪', label: t('german') }
].map(lang => (
<button
key={lang.id}
onClick={() => handleLanguageChange(lang.id)}
className={`p-6 rounded-2xl flex flex-col items-center justify-center gap-4 transition-all ${language === lang.id ? 'bg-primary-600 text-white shadow-xl shadow-primary-600/30 scale-105' : 'bg-gray-50 text-gray-600 hover:bg-gray-100 dark:bg-gray-800 dark:text-gray-300 dark:hover:bg-gray-700'}`}
>
<span className="text-4xl">{lang.flag}</span>
<span className="font-black text-[10px] uppercase tracking-widest text-center">{lang.label}</span>
</button>
))}
</div>
<button onClick={() => setShowLangModal(false)} className="w-full mt-8 py-4 uppercase font-black text-[10px] tracking-widest text-gray-500 hover:text-gray-900 dark:hover:text-white transition-colors">
{t('cancel')}
</button>
</Card>
</div>
)}
</div>
);
}