From 2d015444d367f92f72b283820414b7c8e39227c5 Mon Sep 17 00:00:00 2001
From: 230419 <230419@epvc.pt>
Date: Tue, 14 Apr 2026 16:59:17 +0100
Subject: [PATCH] =?UTF-8?q?defini=C3=A7=C3=B5es?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/App.jsx | 123 +++++++++++++++++++++++++++++++++++++++---------
src/lib/i18n.js | 45 ++++++++++++++++--
2 files changed, 140 insertions(+), 28 deletions(-)
diff --git a/src/App.jsx b/src/App.jsx
index a95d0fd..363a5b0 100644
--- a/src/App.jsx
+++ b/src/App.jsx
@@ -15,7 +15,7 @@ import {
} from 'firebase/auth';
import {
collection, doc, onSnapshot, addDoc, updateDoc,
- deleteDoc, writeBatch
+ deleteDoc, writeBatch, setDoc
} from 'firebase/firestore';
import { auth, db, appId } from './lib/firebase';
@@ -42,10 +42,15 @@ export default function App() {
// Estado para criação de Looks
const [selectedForLook, setSelectedForLook] = useState([]);
+ // 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 t = (key) => translations[language]?.[key] || translations['PT'][key] || key;
@@ -89,7 +94,14 @@ export default function App() {
setLooks(snap.docs.map(d => ({ id: d.id, ...d.data() })));
}, (err) => console.error(err));
- return () => { unsubClothes(); unsubLooks(); };
+ // Profile
+ const profileDoc = doc(db, 'artifacts', appId, 'users', user.uid, 'profile', 'data');
+ const unsubProfile = onSnapshot(profileDoc, (snap) => {
+ if (snap.exists()) setUserProfile(snap.data());
+ else setUserProfile({});
+ }, (err) => console.error(err));
+
+ return () => { unsubClothes(); unsubLooks(); unsubProfile(); };
}, [user]);
// --- Lógicas de Negócio ---
@@ -231,6 +243,25 @@ export default function App() {
finally { setLoading(false); }
};
+ 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');
+ await setDoc(profileDoc, {
+ username: fd.get('username') || '',
+ fullName: fd.get('fullName') || '',
+ dob: fd.get('dob') || '',
+ bio: fd.get('bio') || ''
+ }, { merge: true });
+ } catch (err) {
+ console.error(err);
+ } finally {
+ setSavingProfile(false);
+ }
+ };
+
if (loading && !user) return
;
if (view === 'auth') {
@@ -304,10 +335,10 @@ export default function App() {
- {user?.email?.[0]?.toUpperCase() || 'U'}
+ {(userProfile?.fullName?.[0] || userProfile?.username?.[0] || user?.email?.[0] || 'U').toUpperCase()}
-
{user?.email?.split('@')[0] || t('userTitle')}
+
{userProfile?.username || userProfile?.fullName || user?.email?.split('@')[0] || t('userTitle')}
{t('online')}
@@ -632,17 +663,32 @@ export default function App() {
- {user?.email?.[0]?.toUpperCase() || 'U'}
+ {(userProfile?.fullName?.[0] || userProfile?.username?.[0] || user?.email?.[0] || 'U').toUpperCase()}
-
{t('yourAccount')}
-
{user?.email || t('papMode')}
+
{userProfile?.fullName || t('yourAccount')}
+
@{userProfile?.username || user?.email?.split('@')[0] || t('papMode')}
+
+ {t('profileInfo')}
+
+
+
{/* Preferências */}
-
+
{t('preferences')}
@@ -697,24 +743,25 @@ export default function App() {
-
-
-
-
- {t('systemAndData')}
-
-
-
-
+
+
+
{t('appLanguage')}
+
+ {language === 'PT' ? '🇵🇹 ' + t('portuguese') :
+ language === 'EN' ? '🇬🇧 ' + t('english') :
+ language === 'ES' ? '🇪🇸 ' + t('spanish') :
+ language === 'FR' ? '🇫🇷 ' + t('french') :
+ language === 'DE' ? '🇩🇪 ' + t('german') : language}
+
+
+
+
+
@@ -753,6 +800,36 @@ export default function App() {
+
+ {/* Modal de Idioma */}
+ {showLangModal && (
+ setShowLangModal(false)}>
+
e.stopPropagation()}>
+ {t('appLanguage')}
+
+ {[
+ { 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 => (
+
+ ))}
+
+
+
+
+ )}
);
}
diff --git a/src/lib/i18n.js b/src/lib/i18n.js
index e70a230..57a5562 100644
--- a/src/lib/i18n.js
+++ b/src/lib/i18n.js
@@ -92,7 +92,14 @@ export const translations = {
colorBlue: "Azul",
userTitle: "Utilizador",
themeColor: "Cor do Tema",
- personalizeColor: "Personalizar a cor"
+ personalizeColor: "Personalizar a cor",
+ profileInfo: "Informações da Conta",
+ username: "Nome de Utilizador",
+ fullName: "Nome Completo",
+ dob: "Data de Nascimento",
+ bio: "Bio / Sobre mim",
+ optional: "(Opcional)",
+ saving: "A guardar..."
},
EN: {
loginModeIntro: "The Future of Your Style",
@@ -187,7 +194,14 @@ export const translations = {
colorBlue: "Blue",
userTitle: "User",
themeColor: "Theme Color",
- personalizeColor: "Personalize the color"
+ personalizeColor: "Personalize the color",
+ profileInfo: "Account Information",
+ username: "Username",
+ fullName: "Full Name",
+ dob: "Date of Birth",
+ bio: "Bio / About me",
+ optional: "(Optional)",
+ saving: "Saving..."
},
ES: {
loginModeIntro: "El Futuro de Tu Estilo",
@@ -282,7 +296,14 @@ export const translations = {
colorBlue: "Azul",
userTitle: "Usuario",
themeColor: "Color del Tema",
- personalizeColor: "Personaliza el color"
+ personalizeColor: "Personaliza el color",
+ profileInfo: "Información de la Cuenta",
+ username: "Nombre de Usuario",
+ fullName: "Nombre Completo",
+ dob: "Fecha de Nacimiento",
+ bio: "Bio / Sobre mí",
+ optional: "(Opcional)",
+ saving: "Guardando..."
},
FR: {
loginModeIntro: "Le Futur de Ton Style",
@@ -377,7 +398,14 @@ export const translations = {
colorBlue: "Bleu",
userTitle: "Utilisateur",
themeColor: "Couleur du Thème",
- personalizeColor: "Personnaliser la couleur"
+ personalizeColor: "Personnaliser la couleur",
+ profileInfo: "Informations du Compte",
+ username: "Nom d'utilisateur",
+ fullName: "Nom Complet",
+ dob: "Date de Naissance",
+ bio: "Bio / À propos",
+ optional: "(Optionnel)",
+ saving: "Enregistrement..."
},
DE: {
loginModeIntro: "Die Zukunft deines Stils",
@@ -472,6 +500,13 @@ export const translations = {
colorBlue: "Blau",
userTitle: "Benutzer",
themeColor: "Themenfarbe",
- personalizeColor: "Farbe anpassen"
+ personalizeColor: "Farbe anpassen",
+ profileInfo: "Kontoinformationen",
+ username: "Benutzername",
+ fullName: "Vollständiger Name",
+ dob: "Geburtsdatum",
+ bio: "Biografie / Über mich",
+ optional: "(Optional)",
+ saving: "Speichern..."
}
};