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..." } };