idioma 2
This commit is contained in:
121
src/App.jsx
121
src/App.jsx
@@ -46,9 +46,16 @@ export default function App() {
|
||||
const [notificationsEnabled, setNotificationsEnabled] = useState(true);
|
||||
const [weatherAlerts, setWeatherAlerts] = useState(true);
|
||||
const [language, setLanguage] = useState('PT');
|
||||
const [theme, setTheme] = useState(() => localStorage.getItem('app-theme') || 'theme-indigo');
|
||||
|
||||
const t = (key) => translations[language]?.[key] || translations['PT'][key] || key;
|
||||
|
||||
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 () => {
|
||||
@@ -224,14 +231,14 @@ export default function App() {
|
||||
finally { setLoading(false); }
|
||||
};
|
||||
|
||||
if (loading && !user) return <div className="h-screen flex items-center justify-center bg-indigo-50 dark:bg-gray-950"><Loader2 className="animate-spin text-indigo-600" size={40} /></div>;
|
||||
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-indigo-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' : ''}`}>
|
||||
<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" darkMode={darkMode}>
|
||||
<div className="text-center mb-10">
|
||||
<div className="inline-flex p-5 bg-indigo-600 rounded-[2rem] shadow-2xl shadow-indigo-600/40 mb-6">
|
||||
<div className="inline-flex p-5 bg-primary-600 rounded-[2rem] shadow-2xl shadow-primary-600/40 mb-6">
|
||||
<Shirt className="text-white w-12 h-12" />
|
||||
</div>
|
||||
<h1 className="text-5xl font-black tracking-tighter italic">MyCloset</h1>
|
||||
@@ -241,15 +248,15 @@ export default function App() {
|
||||
{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-indigo-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-indigo-500 outline-none font-bold" />
|
||||
<button className="w-full py-5 bg-indigo-600 text-white rounded-[2rem] font-black text-lg shadow-2xl hover:scale-[1.02] active:scale-95 transition-all">
|
||||
<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 onClick={() => setAuthMode(authMode === 'login' ? 'register' : 'login')} className="text-gray-400 font-black text-[10px] uppercase tracking-[0.3em] hover:text-indigo-600 transition-colors text-inherit">
|
||||
<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>
|
||||
@@ -269,7 +276,7 @@ export default function App() {
|
||||
`}>
|
||||
<div className="p-10 h-full flex flex-col backdrop-blur-xl">
|
||||
<div className="flex items-center gap-4 mb-16">
|
||||
<div className="p-3 bg-indigo-600 rounded-2xl shadow-xl shadow-indigo-600/30">
|
||||
<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>
|
||||
@@ -286,7 +293,7 @@ export default function App() {
|
||||
<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-indigo-600 text-white shadow-2xl shadow-indigo-600/30 scale-105' : 'opacity-40 hover:opacity-100 hover:bg-indigo-500/5'}`}
|
||||
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>
|
||||
@@ -296,7 +303,7 @@ export default function App() {
|
||||
|
||||
<div className="mt-auto pt-10 border-t border-inherit">
|
||||
<div className="flex items-center gap-4 mb-8 px-2">
|
||||
<div className={`w-12 h-12 rounded-2xl flex items-center justify-center font-black text-white shadow-xl ${darkMode ? 'bg-indigo-500' : 'bg-indigo-600'}`}>
|
||||
<div className={`w-12 h-12 rounded-2xl flex items-center justify-center font-black text-white shadow-xl ${darkMode ? 'bg-primary-500' : 'bg-primary-600'}`}>
|
||||
{user?.email?.[0]?.toUpperCase() || 'U'}
|
||||
</div>
|
||||
<div className="flex-1 min-w-0">
|
||||
@@ -331,10 +338,10 @@ export default function App() {
|
||||
|
||||
<div className="flex items-center gap-4">
|
||||
<div className="flex bg-gray-100 dark:bg-gray-800 p-1.5 rounded-2xl">
|
||||
<button onClick={() => setDarkMode(false)} className={`p-2 rounded-xl ${!darkMode ? 'bg-white shadow-md text-indigo-600' : 'text-gray-500'}`}><Sun size={18} /></button>
|
||||
<button onClick={() => setDarkMode(true)} className={`p-2 rounded-xl ${darkMode ? 'bg-gray-900 shadow-md text-indigo-400' : 'text-gray-500'}`}><Moon size={18} /></button>
|
||||
<button onClick={() => setDarkMode(false)} className={`p-2 rounded-xl ${!darkMode ? 'bg-white shadow-md text-primary-600' : 'text-gray-500'}`}><Sun size={18} /></button>
|
||||
<button onClick={() => setDarkMode(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'); }} className="p-4 bg-indigo-600 text-white rounded-2xl shadow-xl shadow-indigo-600/30 hover:scale-105 active:scale-95 transition-all">
|
||||
<button onClick={() => { setEditingItem(null); setImageUrlDraft(''); setView('add'); }} 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>
|
||||
@@ -348,13 +355,13 @@ export default function App() {
|
||||
<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: 'indigo' },
|
||||
{ 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-indigo-400' : 'bg-indigo-50 text-indigo-600'}`}>
|
||||
<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>
|
||||
@@ -364,21 +371,21 @@ export default function App() {
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-1 lg:grid-cols-3 gap-8">
|
||||
<Card className="lg:col-span-2 p-10 bg-indigo-600 text-white border-none shadow-2xl shadow-indigo-600/40 relative overflow-hidden" darkMode={darkMode}>
|
||||
<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-indigo-200" />
|
||||
<CloudSun size={28} className="text-primary-200" />
|
||||
<Badge variant="warning">{t('todayIn')}</Badge>
|
||||
</div>
|
||||
<h3 className="text-5xl font-black tracking-tighter mb-4">{t('weatherUpdate')}</h3>
|
||||
<p className="text-indigo-100 text-lg font-medium max-w-lg leading-relaxed">
|
||||
<p className="text-primary-100 text-lg font-medium max-w-lg leading-relaxed">
|
||||
{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-indigo-400">
|
||||
<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>
|
||||
))}
|
||||
@@ -400,7 +407,7 @@ export default function App() {
|
||||
<span>{Math.floor(Math.random() * 40 + 20)}%</span>
|
||||
</div>
|
||||
<div className="h-2 w-full bg-gray-100 dark:bg-gray-700 rounded-full overflow-hidden">
|
||||
<div className="h-full bg-indigo-600" style={{ width: `${Math.floor(Math.random() * 40 + 20)}%` }}></div>
|
||||
<div className="h-full bg-primary-600" style={{ width: `${Math.floor(Math.random() * 40 + 20)}%` }}></div>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
@@ -418,7 +425,7 @@ export default function App() {
|
||||
<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-indigo-500/10 font-bold text-lg ${darkMode ? 'bg-gray-800' : 'bg-gray-100'}`}
|
||||
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>
|
||||
@@ -428,7 +435,7 @@ export default function App() {
|
||||
<button
|
||||
key={cat}
|
||||
onClick={() => setCategoryFilter(cat)}
|
||||
className={`px-8 py-4 rounded-2xl font-black text-xs uppercase tracking-widest transition-all ${categoryFilter === cat ? 'bg-indigo-600 text-white shadow-xl shadow-indigo-600/30' : (darkMode ? 'bg-gray-800 text-gray-400' : 'bg-white text-gray-500 shadow-sm border border-gray-100')}`}
|
||||
className={`px-8 py-4 rounded-2xl font-black text-xs 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-white text-gray-500 shadow-sm border border-gray-100')}`}
|
||||
>
|
||||
{cat}
|
||||
</button>
|
||||
@@ -444,7 +451,7 @@ export default function App() {
|
||||
|
||||
<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-8 text-white">
|
||||
<div className="grid grid-cols-2 gap-3">
|
||||
<button onClick={() => { setEditingItem(item); setImageUrlDraft(''); setView('edit'); }} className="py-4 bg-white text-indigo-600 rounded-2xl font-black text-[10px] uppercase flex items-center justify-center gap-2 hover:bg-indigo-50"><Edit2 size={16} /> {t('edit')}</button>
|
||||
<button onClick={() => { setEditingItem(item); setImageUrlDraft(''); setView('edit'); }} className="py-4 bg-white text-primary-600 rounded-2xl font-black text-[10px] uppercase flex items-center justify-center gap-2 hover:bg-primary-50"><Edit2 size={16} /> {t('edit')}</button>
|
||||
<button onClick={() => handleItemAction('laundry', item)} className="py-4 bg-blue-600 text-white rounded-2xl font-black text-[10px] uppercase flex items-center justify-center gap-2 hover:bg-blue-700"><Droplets size={16} /> {t('makeDirty')}</button>
|
||||
<button onClick={() => handleItemAction('trash', item)} className="py-4 bg-red-600/20 text-red-100 backdrop-blur-md rounded-2xl font-black text-[10px] uppercase hover:bg-red-600 transition-colors col-span-2">{t('moveToTrash')}</button>
|
||||
</div>
|
||||
@@ -507,8 +514,8 @@ export default function App() {
|
||||
<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-indigo-200" darkMode={darkMode}>
|
||||
<h3 className="text-2xl font-black tracking-tighter mb-6 flex items-center gap-3 text-inherit"><Sparkles className="text-indigo-600" /> {t('createNewLook')}</h3>
|
||||
<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" /> {t('createNewLook')}</h3>
|
||||
<form onSubmit={createLook} className="space-y-6">
|
||||
<input name="lookName" placeholder={t('lookName')} 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">
|
||||
@@ -518,7 +525,7 @@ export default function App() {
|
||||
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-indigo-500" alt="" />
|
||||
<img src={item?.imageUrl} className="w-12 h-12 rounded-lg object-cover border-2 border-primary-500" alt="" />
|
||||
<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>
|
||||
);
|
||||
@@ -526,7 +533,7 @@ export default function App() {
|
||||
{selectedForLook.length === 0 && <p className="text-xs text-gray-400 italic">{t('selectPieces')}</p>}
|
||||
</div>
|
||||
</div>
|
||||
<button disabled={selectedForLook.length < 2} className="w-full py-4 bg-indigo-600 text-white rounded-2xl font-black uppercase tracking-widest text-xs shadow-xl shadow-indigo-600/30 disabled:opacity-30 transition-all">
|
||||
<button disabled={selectedForLook.length < 2} className="w-full 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">
|
||||
{t('saveLook')}
|
||||
</button>
|
||||
</form>
|
||||
@@ -536,9 +543,9 @@ export default function App() {
|
||||
<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-indigo-600 scale-90' : 'border-transparent hover:border-indigo-200'}`}>
|
||||
<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-indigo-600/40 flex items-center justify-center text-white"><Check size={20} /></div>}
|
||||
{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>
|
||||
@@ -599,7 +606,7 @@ export default function App() {
|
||||
<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-indigo-500/10 font-bold ${darkMode ? 'bg-gray-700 text-white' : 'bg-gray-100'}`}>
|
||||
<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>
|
||||
@@ -609,7 +616,7 @@ export default function App() {
|
||||
|
||||
<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-indigo-600 text-white rounded-[2rem] font-black uppercase tracking-widest text-[10px] shadow-2xl shadow-indigo-600/40 hover:scale-[1.02] active:scale-95 transition-all">
|
||||
<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>
|
||||
@@ -622,9 +629,9 @@ export default function App() {
|
||||
{/* DEFINIÇÕES */}
|
||||
{view === 'settings' && (
|
||||
<div className="max-w-4xl mx-auto space-y-12 animate-in fade-in duration-700 pb-20">
|
||||
<Card className="p-10 border-indigo-100 relative overflow-hidden" darkMode={darkMode}>
|
||||
<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-indigo-600 flex items-center justify-center text-white text-4xl font-black shadow-2xl">
|
||||
<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">
|
||||
{user?.email?.[0]?.toUpperCase() || 'U'}
|
||||
</div>
|
||||
<div>
|
||||
@@ -637,23 +644,47 @@ export default function App() {
|
||||
{/* Preferências */}
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 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-indigo-600" /> {t('preferences')}</h3>
|
||||
<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={() => setDarkMode(!darkMode)} className={`w-14 h-8 rounded-full transition-colors relative ${darkMode ? 'bg-indigo-600' : 'bg-gray-200'}`}>
|
||||
<button onClick={() => setDarkMode(!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={() => setTheme(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={() => setNotificationsEnabled(!notificationsEnabled)} className={`w-14 h-8 rounded-full transition-colors relative ${notificationsEnabled ? 'bg-indigo-600' : 'bg-gray-200'}`}>
|
||||
<button onClick={() => setNotificationsEnabled(!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>
|
||||
@@ -662,7 +693,7 @@ export default function App() {
|
||||
<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={() => setWeatherAlerts(!weatherAlerts)} className={`w-14 h-8 rounded-full transition-colors relative ${weatherAlerts ? 'bg-indigo-600' : 'bg-gray-200'}`}>
|
||||
<button onClick={() => setWeatherAlerts(!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>
|
||||
@@ -670,11 +701,11 @@ export default function App() {
|
||||
</Card>
|
||||
|
||||
<Card className="p-8" darkMode={darkMode}>
|
||||
<h3 className="text-xl font-black mb-6 flex items-center gap-3 text-inherit"><Globe className="text-indigo-600" /> {t('systemAndData')}</h3>
|
||||
<h3 className="text-xl font-black mb-6 flex items-center gap-3 text-inherit"><Globe className="text-primary-600" /> {t('systemAndData')}</h3>
|
||||
<div className="space-y-6">
|
||||
<div className="space-y-2">
|
||||
<label className="text-[10px] font-black uppercase opacity-40 tracking-widest ml-1 text-inherit">{t('appLanguage')}</label>
|
||||
<select value={language} onChange={(e) => setLanguage(e.target.value)} className={`w-full p-4 rounded-xl border-none outline-none focus:ring-2 focus:ring-indigo-500 font-bold ${darkMode ? 'bg-gray-800 text-white' : 'bg-gray-50'}`}>
|
||||
<select value={language} onChange={(e) => setLanguage(e.target.value)} className={`w-full 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="PT">{t('portuguese')}</option>
|
||||
<option value="EN">{t('english')}</option>
|
||||
<option value="ES">{t('spanish')}</option>
|
||||
@@ -682,16 +713,6 @@ export default function App() {
|
||||
<option value="DE">{t('german')}</option>
|
||||
</select>
|
||||
</div>
|
||||
<div>
|
||||
<button onClick={() => alert(t('exportDataAlert'))} className="w-full py-4 rounded-xl font-black uppercase text-[10px] tracking-widest transition-all bg-indigo-50 text-indigo-600 hover:bg-indigo-100 dark:bg-indigo-900/30 dark:text-indigo-300 dark:hover:bg-indigo-900/50 flex items-center justify-center gap-2">
|
||||
<Download size={16} /> {t('exportData')}
|
||||
</button>
|
||||
</div>
|
||||
<div>
|
||||
<button className="w-full py-4 rounded-xl font-black uppercase text-[10px] tracking-widest transition-all bg-gray-100 text-gray-500 hover:bg-gray-200 dark:bg-gray-800 dark:text-gray-400 dark:hover:bg-gray-700 flex items-center justify-center gap-2">
|
||||
<ShieldAlert size={16} /> {t('privacyPolicy')}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</Card>
|
||||
</div>
|
||||
@@ -710,7 +731,7 @@ export default function App() {
|
||||
<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-indigo-600 hover:bg-indigo-50 rounded-2xl transition-all"><RotateCcw size={18} /></button>
|
||||
<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>
|
||||
|
||||
Reference in New Issue
Block a user