save
This commit is contained in:
159
src/App.jsx
159
src/App.jsx
@@ -7,7 +7,7 @@ import {
|
|||||||
PanelLeftClose, PanelLeftOpen, Sparkles, CloudSun,
|
PanelLeftClose, PanelLeftOpen, Sparkles, CloudSun,
|
||||||
ArrowRight, Droplets, CheckCircle2, PieChart, History,
|
ArrowRight, Droplets, CheckCircle2, PieChart, History,
|
||||||
X, Download, Bell, Globe, Filter, ShoppingBag, Share2,
|
X, Download, Bell, Globe, Filter, ShoppingBag, Share2,
|
||||||
FolderOpen, Tag, Link, Calendar, ChevronLeft, ChevronRight, Users
|
FolderOpen, Tag, Link, Calendar, ChevronLeft, ChevronRight, ChevronDown, Users, MapPin, Copy
|
||||||
} from 'lucide-react';
|
} from 'lucide-react';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
@@ -69,8 +69,11 @@ export default function App() {
|
|||||||
|
|
||||||
// Estado da Comunidade
|
// Estado da Comunidade
|
||||||
const [communitySearchTerm, setCommunitySearchTerm] = useState('');
|
const [communitySearchTerm, setCommunitySearchTerm] = useState('');
|
||||||
|
const [showRecommended, setShowRecommended] = useState(false);
|
||||||
const [communityUsers, setCommunityUsers] = useState([]);
|
const [communityUsers, setCommunityUsers] = useState([]);
|
||||||
const [selectedCommunityUser, setSelectedCommunityUser] = useState(null);
|
const [selectedCommunityUser, setSelectedCommunityUser] = useState(null);
|
||||||
|
const [selectedUserProfile, setSelectedUserProfile] = useState(null);
|
||||||
|
const [showInspectModal, setShowInspectModal] = useState(false);
|
||||||
const [selectedUserClothes, setSelectedUserClothes] = useState([]);
|
const [selectedUserClothes, setSelectedUserClothes] = useState([]);
|
||||||
const [selectedUserLooks, setSelectedUserLooks] = useState([]);
|
const [selectedUserLooks, setSelectedUserLooks] = useState([]);
|
||||||
|
|
||||||
@@ -433,7 +436,8 @@ export default function App() {
|
|||||||
username: userProfile.username || '',
|
username: userProfile.username || '',
|
||||||
fullName: userProfile.fullName || '',
|
fullName: userProfile.fullName || '',
|
||||||
avatar: userProfile.avatar || null,
|
avatar: userProfile.avatar || null,
|
||||||
isPrivate: userProfile.settings?.isPrivate || false
|
isPrivate: userProfile.settings?.isPrivate || false,
|
||||||
|
location: userProfile.location || ''
|
||||||
}, { merge: true }).catch(err => {
|
}, { merge: true }).catch(err => {
|
||||||
console.error("Erro ao sincronizar perfil público:", err);
|
console.error("Erro ao sincronizar perfil público:", err);
|
||||||
if (err.code === 'permission-denied') {
|
if (err.code === 'permission-denied') {
|
||||||
@@ -441,7 +445,7 @@ export default function App() {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}, [user, userProfile?.username, userProfile?.fullName, userProfile?.avatar, userProfile?.settings?.isPrivate]);
|
}, [user, userProfile?.username, userProfile?.fullName, userProfile?.avatar, userProfile?.settings?.isPrivate, userProfile?.location]);
|
||||||
|
|
||||||
// Fetch utilizadores da comunidade
|
// Fetch utilizadores da comunidade
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -452,16 +456,25 @@ export default function App() {
|
|||||||
const snap = await getDocs(profilesRef);
|
const snap = await getDocs(profilesRef);
|
||||||
const users = snap.docs.map(d => d.data()).filter(u => u.uid !== user?.uid);
|
const users = snap.docs.map(d => d.data()).filter(u => u.uid !== user?.uid);
|
||||||
|
|
||||||
if (communitySearchTerm.trim()) {
|
if (showRecommended) {
|
||||||
|
const normalizeLoc = (str) => str ? str.normalize("NFD").replace(/[\u0300-\u036f]/g, "").toLowerCase().trim() : "";
|
||||||
|
const myLocation = normalizeLoc(userProfile?.location);
|
||||||
|
if (myLocation) {
|
||||||
|
setCommunityUsers(users.filter(u =>
|
||||||
|
normalizeLoc(u.location) === myLocation
|
||||||
|
));
|
||||||
|
} else {
|
||||||
|
setCommunityUsers([]);
|
||||||
|
}
|
||||||
|
} else if (communitySearchTerm.trim()) {
|
||||||
let term = communitySearchTerm.trim().toLowerCase();
|
let term = communitySearchTerm.trim().toLowerCase();
|
||||||
if (term.startsWith('@')) term = term.substring(1);
|
if (term.startsWith('@')) term = term.substring(1);
|
||||||
setCommunityUsers(users.filter(u => {
|
setCommunityUsers(users.filter(u => {
|
||||||
const uname = u.username ? u.username.toLowerCase() : '';
|
const uname = u.username ? u.username.toLowerCase() : '';
|
||||||
const fname = u.fullName ? u.fullName.toLowerCase() : '';
|
return uname.includes(term);
|
||||||
return uname.includes(term) || fname.includes(term);
|
|
||||||
}));
|
}));
|
||||||
} else {
|
} else {
|
||||||
setCommunityUsers(users);
|
setCommunityUsers([]);
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error("Erro ao buscar comunidade", err);
|
console.error("Erro ao buscar comunidade", err);
|
||||||
@@ -469,13 +482,14 @@ export default function App() {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
fetchUsers();
|
fetchUsers();
|
||||||
}, [view, communitySearchTerm, user?.uid]);
|
}, [view, communitySearchTerm, showRecommended, user?.uid, userProfile?.location]);
|
||||||
|
|
||||||
const viewCommunityUser = async (targetUser) => {
|
const viewCommunityUser = async (targetUser) => {
|
||||||
setSelectedCommunityUser(targetUser);
|
setSelectedCommunityUser(targetUser);
|
||||||
if (targetUser.isPrivate) {
|
if (targetUser.isPrivate) {
|
||||||
setSelectedUserClothes([]);
|
setSelectedUserClothes([]);
|
||||||
setSelectedUserLooks([]);
|
setSelectedUserLooks([]);
|
||||||
|
setSelectedUserProfile(null);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -489,6 +503,15 @@ export default function App() {
|
|||||||
const looksCol = collection(db, 'artifacts', appId, 'users', targetUser.uid, 'looks');
|
const looksCol = collection(db, 'artifacts', appId, 'users', targetUser.uid, 'looks');
|
||||||
const snapLooks = await getDocs(looksCol);
|
const snapLooks = await getDocs(looksCol);
|
||||||
setSelectedUserLooks(snapLooks.docs.map(d => ({id: d.id, ...d.data()})));
|
setSelectedUserLooks(snapLooks.docs.map(d => ({id: d.id, ...d.data()})));
|
||||||
|
|
||||||
|
// Profile
|
||||||
|
const profileDocRef = doc(db, 'artifacts', appId, 'users', targetUser.uid, 'profile', 'data');
|
||||||
|
const snapProfile = await getDoc(profileDocRef);
|
||||||
|
if (snapProfile.exists()) {
|
||||||
|
setSelectedUserProfile(snapProfile.data());
|
||||||
|
} else {
|
||||||
|
setSelectedUserProfile({});
|
||||||
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error("Erro ao carregar perfil do utilizador", err);
|
console.error("Erro ao carregar perfil do utilizador", err);
|
||||||
}
|
}
|
||||||
@@ -1094,7 +1117,8 @@ export default function App() {
|
|||||||
fullName: fd.get('fullName') || '',
|
fullName: fd.get('fullName') || '',
|
||||||
dob: dob,
|
dob: dob,
|
||||||
bio: fd.get('bio') || '',
|
bio: fd.get('bio') || '',
|
||||||
location: fd.get('location') || ''
|
location: fd.get('location') || '',
|
||||||
|
createdAt: userProfile?.createdAt || new Date().getTime()
|
||||||
}, { merge: true }).catch(err => {
|
}, { merge: true }).catch(err => {
|
||||||
console.error(err);
|
console.error(err);
|
||||||
});
|
});
|
||||||
@@ -2126,7 +2150,21 @@ export default function App() {
|
|||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<h3 className="text-3xl font-black tracking-tighter">{userProfile?.fullName || t('yourAccount')}</h3>
|
<h3 className="text-3xl font-black tracking-tighter">{userProfile?.fullName || t('yourAccount')}</h3>
|
||||||
|
<div className="flex items-center gap-2 mt-1">
|
||||||
<p className="opacity-60 font-bold text-sm">@{userProfile?.username || user?.email?.split('@')[0] || t('papMode')}</p>
|
<p className="opacity-60 font-bold text-sm">@{userProfile?.username || user?.email?.split('@')[0] || t('papMode')}</p>
|
||||||
|
<button
|
||||||
|
onClick={(e) => {
|
||||||
|
e.stopPropagation();
|
||||||
|
navigator.clipboard.writeText(`@${userProfile?.username || user?.email?.split('@')[0] || t('papMode')}`);
|
||||||
|
setToastMessage('Username copiado!' || t('copied'));
|
||||||
|
setTimeout(() => setToastMessage(null), 2000);
|
||||||
|
}}
|
||||||
|
className="text-blue-500 hover:text-blue-600 bg-blue-500/10 p-1.5 rounded-md transition-colors"
|
||||||
|
title="Copiar Username"
|
||||||
|
>
|
||||||
|
<Copy size={14} />
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</Card>
|
</Card>
|
||||||
@@ -2146,18 +2184,27 @@ export default function App() {
|
|||||||
<div className="space-y-2">
|
<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>
|
<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">
|
<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'}`}>
|
<div className="relative flex-1">
|
||||||
|
<select name="dobDay" defaultValue={userProfile?.dob?.split('-')[2] || ''} className={`w-full appearance-none p-4 pr-10 rounded-xl border-none outline-none focus:ring-2 focus:ring-primary-500/40 font-bold transition-all cursor-pointer ${darkMode ? 'bg-gray-800 text-white hover:bg-gray-700' : 'bg-gray-100 text-gray-900 hover:bg-gray-200'}`}>
|
||||||
<option value="">DD</option>
|
<option value="">DD</option>
|
||||||
{Array.from({ length: 31 }, (_, i) => String(i + 1).padStart(2, '0')).map(d => <option key={d} value={d}>{d}</option>)}
|
{Array.from({ length: 31 }, (_, i) => String(i + 1).padStart(2, '0')).map(d => <option key={d} value={d}>{d}</option>)}
|
||||||
</select>
|
</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'}`}>
|
<ChevronDown size={14} className="absolute right-3 top-1/2 -translate-y-1/2 opacity-40 pointer-events-none" />
|
||||||
|
</div>
|
||||||
|
<div className="relative flex-1">
|
||||||
|
<select name="dobMonth" defaultValue={userProfile?.dob?.split('-')[1] || ''} className={`w-full appearance-none p-4 pr-10 rounded-xl border-none outline-none focus:ring-2 focus:ring-primary-500/40 font-bold transition-all cursor-pointer ${darkMode ? 'bg-gray-800 text-white hover:bg-gray-700' : 'bg-gray-100 text-gray-900 hover:bg-gray-200'}`}>
|
||||||
<option value="">MM</option>
|
<option value="">MM</option>
|
||||||
{Array.from({ length: 12 }, (_, i) => String(i + 1).padStart(2, '0')).map(m => <option key={m} value={m}>{m}</option>)}
|
{Array.from({ length: 12 }, (_, i) => String(i + 1).padStart(2, '0')).map(m => <option key={m} value={m}>{m}</option>)}
|
||||||
</select>
|
</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'}`}>
|
<ChevronDown size={14} className="absolute right-3 top-1/2 -translate-y-1/2 opacity-40 pointer-events-none" />
|
||||||
|
</div>
|
||||||
|
<div className="relative flex-[1.5]">
|
||||||
|
<select name="dobYear" defaultValue={userProfile?.dob?.split('-')[0] || ''} className={`w-full appearance-none p-4 pr-10 rounded-xl border-none outline-none focus:ring-2 focus:ring-primary-500/40 font-bold transition-all cursor-pointer ${darkMode ? 'bg-gray-800 text-white hover:bg-gray-700' : 'bg-gray-100 text-gray-900 hover:bg-gray-200'}`}>
|
||||||
<option value="">YYYY</option>
|
<option value="">YYYY</option>
|
||||||
{Array.from({ length: 100 }, (_, i) => new Date().getFullYear() - i).map(y => <option key={y} value={y}>{y}</option>)}
|
{Array.from({ length: 100 }, (_, i) => new Date().getFullYear() - i).map(y => <option key={y} value={y}>{y}</option>)}
|
||||||
</select>
|
</select>
|
||||||
|
<ChevronDown size={14} className="absolute right-3 top-1/2 -translate-y-1/2 opacity-40 pointer-events-none" />
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<Input label={`${t('bio')} ${t('optional')}`} name="bio" defaultValue={userProfile?.bio || ''} placeholder="..." />
|
<Input label={`${t('bio')} ${t('optional')}`} name="bio" defaultValue={userProfile?.bio || ''} placeholder="..." />
|
||||||
@@ -2176,16 +2223,31 @@ export default function App() {
|
|||||||
<div className="max-w-7xl mx-auto space-y-12 animate-in fade-in duration-700 pb-20">
|
<div className="max-w-7xl mx-auto space-y-12 animate-in fade-in duration-700 pb-20">
|
||||||
{!selectedCommunityUser ? (
|
{!selectedCommunityUser ? (
|
||||||
<>
|
<>
|
||||||
<div className="relative mb-8">
|
<div className="relative mb-8 flex gap-4">
|
||||||
|
<div className="relative flex-1">
|
||||||
<Search className="absolute left-6 top-1/2 -translate-y-1/2 opacity-40 text-inherit" size={24} />
|
<Search className="absolute left-6 top-1/2 -translate-y-1/2 opacity-40 text-inherit" size={24} />
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
placeholder={t('searchUsers')}
|
placeholder={t('searchUsers')}
|
||||||
value={communitySearchTerm}
|
value={communitySearchTerm}
|
||||||
onChange={(e) => setCommunitySearchTerm(e.target.value)}
|
onChange={(e) => {
|
||||||
|
setCommunitySearchTerm(e.target.value);
|
||||||
|
if (e.target.value) setShowRecommended(false);
|
||||||
|
}}
|
||||||
className={`w-full p-6 pl-16 rounded-3xl font-black text-lg outline-none focus:ring-4 focus:ring-primary-500/20 transition-all shadow-xl shadow-black/5 text-inherit ${darkMode ? 'bg-gray-800' : 'bg-white'}`}
|
className={`w-full p-6 pl-16 rounded-3xl font-black text-lg outline-none focus:ring-4 focus:ring-primary-500/20 transition-all shadow-xl shadow-black/5 text-inherit ${darkMode ? 'bg-gray-800' : 'bg-white'}`}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
<button
|
||||||
|
onClick={() => {
|
||||||
|
setShowRecommended(!showRecommended);
|
||||||
|
if (!showRecommended) setCommunitySearchTerm('');
|
||||||
|
}}
|
||||||
|
className={`px-8 rounded-3xl font-black transition-all shadow-xl shadow-black/5 flex items-center justify-center gap-2 whitespace-nowrap ${showRecommended ? 'bg-primary-600 text-white' : (darkMode ? 'bg-gray-800 text-inherit hover:bg-gray-700' : 'bg-white text-inherit hover:bg-gray-50')}`}
|
||||||
|
>
|
||||||
|
<MapPin size={20} />
|
||||||
|
<span className="hidden sm:inline">{t('recommended') || 'Recomendados'}</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
|
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
|
||||||
{communityUsers.length === 0 ? (
|
{communityUsers.length === 0 ? (
|
||||||
<div className="col-span-full text-center py-12 opacity-50 text-inherit font-black text-xl">
|
<div className="col-span-full text-center py-12 opacity-50 text-inherit font-black text-xl">
|
||||||
@@ -2210,7 +2272,7 @@ export default function App() {
|
|||||||
</>
|
</>
|
||||||
) : (
|
) : (
|
||||||
<div className="space-y-8">
|
<div className="space-y-8">
|
||||||
<button onClick={() => setSelectedCommunityUser(null)} className="flex items-center gap-2 opacity-60 hover:opacity-100 transition-opacity font-black text-inherit uppercase text-xs tracking-widest">
|
<button onClick={() => { setSelectedCommunityUser(null); setShowInspectModal(false); }} className="flex items-center gap-2 opacity-60 hover:opacity-100 transition-opacity font-black text-inherit uppercase text-xs tracking-widest">
|
||||||
<ChevronLeft size={16} /> Voltar
|
<ChevronLeft size={16} /> Voltar
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
@@ -2219,13 +2281,80 @@ export default function App() {
|
|||||||
<div className="w-24 h-24 rounded-[2.5rem] bg-primary-600 text-white flex items-center justify-center font-black text-4xl overflow-hidden">
|
<div className="w-24 h-24 rounded-[2.5rem] bg-primary-600 text-white flex items-center justify-center font-black text-4xl overflow-hidden">
|
||||||
{selectedCommunityUser.avatar ? <img src={selectedCommunityUser.avatar} className="w-full h-full object-cover" alt="Avatar"/> : <span>{(selectedCommunityUser.fullName?.[0] || selectedCommunityUser.username?.[0] || 'U').toUpperCase()}</span>}
|
{selectedCommunityUser.avatar ? <img src={selectedCommunityUser.avatar} className="w-full h-full object-cover" alt="Avatar"/> : <span>{(selectedCommunityUser.fullName?.[0] || selectedCommunityUser.username?.[0] || 'U').toUpperCase()}</span>}
|
||||||
</div>
|
</div>
|
||||||
|
<div className="flex-1 flex justify-between items-start sm:items-center flex-col sm:flex-row gap-4">
|
||||||
<div>
|
<div>
|
||||||
<h3 className="text-3xl font-black tracking-tighter">{selectedCommunityUser.fullName || t('userTitle')}</h3>
|
<h3 className="text-3xl font-black tracking-tighter">{selectedCommunityUser.fullName || t('userTitle')}</h3>
|
||||||
|
<div className="flex items-center gap-2 mt-1">
|
||||||
<p className="opacity-60 font-bold text-sm">@{selectedCommunityUser.username || 'user'}</p>
|
<p className="opacity-60 font-bold text-sm">@{selectedCommunityUser.username || 'user'}</p>
|
||||||
|
<button
|
||||||
|
onClick={(e) => {
|
||||||
|
e.stopPropagation();
|
||||||
|
navigator.clipboard.writeText(`@${selectedCommunityUser.username || 'user'}`);
|
||||||
|
setToastMessage('Username copiado!' || t('copied'));
|
||||||
|
setTimeout(() => setToastMessage(null), 2000);
|
||||||
|
}}
|
||||||
|
className="text-blue-500 hover:text-blue-600 bg-blue-500/10 p-1.5 rounded-md transition-colors"
|
||||||
|
title="Copiar Username"
|
||||||
|
>
|
||||||
|
<Copy size={14} />
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<button onClick={() => setShowInspectModal(true)} className="px-5 py-3 bg-primary-100 text-primary-700 dark:bg-primary-900/50 dark:text-primary-300 rounded-2xl font-black text-sm transition-all hover:scale-105 flex items-center gap-2">
|
||||||
|
<Search size={16} /> Inspecionar
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</Card>
|
</Card>
|
||||||
|
|
||||||
|
{showInspectModal && (
|
||||||
|
<div className="fixed inset-0 z-[200] flex items-center justify-center bg-black/60 backdrop-blur-sm p-6" onClick={() => setShowInspectModal(false)}>
|
||||||
|
<Card className="w-full max-w-lg p-8 animate-in zoom-in-95 relative" darkMode={darkMode} onClick={e => e.stopPropagation()}>
|
||||||
|
<button onClick={() => setShowInspectModal(false)} className="absolute top-6 right-6 opacity-50 hover:opacity-100 text-inherit">
|
||||||
|
<X size={24} />
|
||||||
|
</button>
|
||||||
|
<div className="flex items-center gap-6 mb-8 text-inherit">
|
||||||
|
<div className="w-20 h-20 rounded-[2rem] bg-primary-600 text-white flex items-center justify-center font-black text-3xl overflow-hidden">
|
||||||
|
{selectedCommunityUser.avatar ? <img src={selectedCommunityUser.avatar} className="w-full h-full object-cover" alt="Avatar"/> : <span>{(selectedCommunityUser.fullName?.[0] || selectedCommunityUser.username?.[0] || 'U').toUpperCase()}</span>}
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<h3 className="text-2xl font-black">{selectedCommunityUser.fullName || t('userTitle')}</h3>
|
||||||
|
<p className="opacity-60 font-bold">@{selectedCommunityUser.username || 'user'}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="space-y-6 text-inherit bg-gray-50 dark:bg-gray-800/50 p-6 rounded-3xl">
|
||||||
|
<div>
|
||||||
|
<p className="text-xs font-black uppercase tracking-widest opacity-50 mb-1">Data de Nascimento</p>
|
||||||
|
<p className="font-bold">{selectedUserProfile?.dob ? new Date(selectedUserProfile.dob).toLocaleDateString() : 'Não especificada'}</p>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<p className="text-xs font-black uppercase tracking-widest opacity-50 mb-1">Localidade</p>
|
||||||
|
<p className="font-bold">{selectedUserProfile?.location || selectedCommunityUser.location || 'Não especificada'}</p>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<p className="text-xs font-black uppercase tracking-widest opacity-50 mb-1">Bio</p>
|
||||||
|
<p className="font-bold opacity-80">{selectedUserProfile?.bio || 'Sem biografia'}</p>
|
||||||
|
</div>
|
||||||
|
<div className="grid grid-cols-2 gap-4 pt-4 border-t border-gray-200 dark:border-gray-700">
|
||||||
|
<div>
|
||||||
|
<p className="text-xs font-black uppercase tracking-widest opacity-50 mb-1">Peças Registadas</p>
|
||||||
|
<p className="text-2xl font-black">{selectedUserClothes.length}</p>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<p className="text-xs font-black uppercase tracking-widest opacity-50 mb-1">Outfits Criados</p>
|
||||||
|
<p className="text-2xl font-black">{selectedUserLooks.length}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="pt-4 border-t border-gray-200 dark:border-gray-700">
|
||||||
|
<p className="text-xs font-black uppercase tracking-widest opacity-50 mb-1">Data de Registo da Conta</p>
|
||||||
|
<p className="font-bold">{selectedUserProfile?.createdAt ? new Date(selectedUserProfile.createdAt).toLocaleDateString() : 'Desconhecida'}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Card>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
{selectedCommunityUser.isPrivate ? (
|
{selectedCommunityUser.isPrivate ? (
|
||||||
<div className="text-center py-20 opacity-50 font-black text-2xl text-inherit">
|
<div className="text-center py-20 opacity-50 font-black text-2xl text-inherit">
|
||||||
<ShieldAlert className="w-16 h-16 mx-auto mb-4 opacity-50" />
|
<ShieldAlert className="w-16 h-16 mx-auto mb-4 opacity-50" />
|
||||||
|
|||||||
Reference in New Issue
Block a user