Локализация
This commit is contained in:
@@ -29,7 +29,7 @@ interface UserProfileProps {
|
||||
type TabType = 'media' | 'gif' | 'files' | 'links';
|
||||
|
||||
export default function UserProfile({ userId, onClose, onMessage, isSelf: isSelfProp, chatId, onGoToMessage }: UserProfileProps) {
|
||||
const { lang } = useLang();
|
||||
const { t, lang } = useLang();
|
||||
const { user: currentUser } = useAuthStore();
|
||||
const { friends, friendRequests, sendRequest, removeFriend, loadFriends } = useFriendStore();
|
||||
|
||||
@@ -156,13 +156,13 @@ export default function UserProfile({ userId, onClose, onMessage, isSelf: isSelf
|
||||
|
||||
const availableTabs = useMemo(() => {
|
||||
const all: { id: TabType, icon: any, label: string }[] = [
|
||||
{ id: 'media', icon: ImageIcon, label: lang === 'ru' ? 'Медиа' : 'Media' },
|
||||
{ id: 'media', icon: ImageIcon, label: t('mediaTab') },
|
||||
{ id: 'gif', icon: Film, label: 'GIF' },
|
||||
{ id: 'files', icon: FileText, label: lang === 'ru' ? 'Файлы' : 'Files' },
|
||||
{ id: 'links', icon: LinkIcon, label: lang === 'ru' ? 'Ссылки' : 'Links' }
|
||||
{ id: 'files', icon: FileText, label: t('filesTab') },
|
||||
{ id: 'links', icon: LinkIcon, label: t('linksTab') }
|
||||
];
|
||||
return isMe ? all : all.filter(t => counts[t.id] > 0);
|
||||
}, [counts, lang, isMe]);
|
||||
}, [counts, lang, isMe, t]);
|
||||
|
||||
// Gallery items for Lightbox
|
||||
const galleryItems = useMemo(() => {
|
||||
@@ -214,7 +214,7 @@ export default function UserProfile({ userId, onClose, onMessage, isSelf: isSelf
|
||||
className="relative w-full max-w-[560px] h-[85vh] bg-[#0a0a0a] rounded-[3rem] border border-white/10 shadow-2xl overflow-hidden flex flex-col backdrop-blur-3xl"
|
||||
>
|
||||
<div className="flex items-center justify-between px-8 py-5 border-b border-white/5 bg-white/[0.01]">
|
||||
<span className="text-sm font-black uppercase tracking-[0.3em] text-white/50">{lang === 'ru' ? 'ПРОФИЛЬ ПОЛЬЗОВАТЕЛЯ' : 'USER PROFILE'}</span>
|
||||
<span className="text-sm font-black uppercase tracking-[0.3em] text-white/50">{t('userProfileUpper')}</span>
|
||||
<button onClick={onClose} className="p-3 rounded-full hover:bg-white/10 text-white/40 hover:text-white transition-all"><X size={24} /></button>
|
||||
</div>
|
||||
|
||||
@@ -240,19 +240,19 @@ export default function UserProfile({ userId, onClose, onMessage, isSelf: isSelf
|
||||
<div className="px-4 py-1.5 rounded-full bg-primary/15 border border-primary/25">
|
||||
<span className="text-xs font-black text-primary uppercase tracking-widest">@{user.username || 'user_' + userId.slice(0, 5)}</span>
|
||||
</div>
|
||||
<div className="flex items-center gap-2 text-xs text-white/40 font-black uppercase tracking-widest"><Calendar size={14} className="text-primary/50" /><span>{lang === 'ru' ? 'С нами с ' : 'Joined '} {formatRegistrationDate(user.createdAt)}</span></div>
|
||||
<div className="flex items-center gap-2 text-xs text-white/40 font-black uppercase tracking-widest"><Calendar size={14} className="text-primary/50" /><span>{t('joined')} {formatRegistrationDate(user.createdAt)}</span></div>
|
||||
</div>
|
||||
|
||||
{!isMe && (
|
||||
<div className="mt-10 w-full max-w-[320px]">
|
||||
{friend ? (
|
||||
<button onClick={handleFriendAction} className="w-full py-4 rounded-2xl bg-red-500/10 border border-red-500/20 text-red-500 text-[11px] font-black uppercase tracking-widest hover:bg-red-500 hover:text-white transition-all flex items-center justify-center gap-3"><UserMinus size={18} />{lang === 'ru' ? 'Удалить из контактов' : 'Remove Contact'}</button>
|
||||
<button onClick={handleFriendAction} className="w-full py-4 rounded-2xl bg-red-500/10 border border-red-500/20 text-red-500 text-[11px] font-black uppercase tracking-widest hover:bg-red-500 hover:text-white transition-all flex items-center justify-center gap-3"><UserMinus size={18} />{t('removeFriend')}</button>
|
||||
) : outgoingReq ? (
|
||||
<button className="w-full py-4 rounded-2xl bg-white/5 border border-white/10 text-white/40 text-[11px] font-black uppercase tracking-widest cursor-default flex items-center justify-center gap-3 opacity-60"><Loader2 size={16} className="animate-spin" />{lang === 'ru' ? 'Запрос отправлен' : 'Request Pending'}</button>
|
||||
<button className="w-full py-4 rounded-2xl bg-white/5 border border-white/10 text-white/40 text-[11px] font-black uppercase tracking-widest cursor-default flex items-center justify-center gap-3 opacity-60"><Loader2 size={16} className="animate-spin" />{t('requestSent')}</button>
|
||||
) : incomingReq ? (
|
||||
<button onClick={() => useFriendStore.getState().acceptRequest(incomingReq.id)} className="w-full py-4 rounded-2xl bg-green-500/15 border border-green-500/25 text-green-500 text-[11px] font-black uppercase tracking-widest hover:bg-green-500 hover:text-white transition-all flex items-center justify-center gap-3"><UserCheck size={18} />{lang === 'ru' ? 'Принять запрос' : 'Accept Request'}</button>
|
||||
<button onClick={() => useFriendStore.getState().acceptRequest(incomingReq.id)} className="w-full py-4 rounded-2xl bg-green-500/15 border border-green-500/25 text-green-500 text-[11px] font-black uppercase tracking-widest hover:bg-green-500 hover:text-white transition-all flex items-center justify-center gap-3"><UserCheck size={18} />{t('acceptRequest')}</button>
|
||||
) : (
|
||||
<button onClick={handleFriendAction} className="w-full py-4 rounded-2xl bg-primary text-white text-[11px] font-black uppercase tracking-widest hover:bg-primary-container transition-all flex items-center justify-center gap-3"><UserPlus size={18} />{lang === 'ru' ? 'Добавить в контакты' : 'Add to Contacts'}</button>
|
||||
<button onClick={handleFriendAction} className="w-full py-4 rounded-2xl bg-primary text-white text-[11px] font-black uppercase tracking-widest hover:bg-primary-container transition-all flex items-center justify-center gap-3"><UserPlus size={18} />{t('addFriend')}</button>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
@@ -260,8 +260,8 @@ export default function UserProfile({ userId, onClose, onMessage, isSelf: isSelf
|
||||
|
||||
{/* About Section */}
|
||||
<div className="p-8 rounded-[2.5rem] bg-white/[0.02] border border-white/5 mb-10 group relative transition-colors hover:bg-white/[0.04]">
|
||||
<div className="flex items-center gap-3 mb-4 text-primary"><Info size={16} /><span className="text-xs font-black uppercase tracking-[0.2em]">{lang === 'ru' ? 'О себе' : 'About me'}</span></div>
|
||||
<p className="text-base text-white/80 leading-relaxed font-medium">{user.about || (lang === 'ru' ? 'Информация отсутствует' : 'No information shared yet')}</p>
|
||||
<div className="flex items-center gap-3 mb-4 text-primary"><Info size={16} /><span className="text-xs font-black uppercase tracking-[0.2em]">{t('aboutMe')}</span></div>
|
||||
<p className="text-base text-white/80 leading-relaxed font-medium">{user.about || t('noBio')}</p>
|
||||
</div>
|
||||
|
||||
{/* Tabs Nav */}
|
||||
@@ -293,7 +293,7 @@ export default function UserProfile({ userId, onClose, onMessage, isSelf: isSelf
|
||||
{contentLoading ? (
|
||||
<motion.div key="loading" initial={{ opacity: 0 }} animate={{ opacity: 1 }} exit={{ opacity: 0 }} className="flex items-center justify-center py-20"><Loader2 className="w-10 h-10 text-primary/40 animate-spin" /></motion.div>
|
||||
) : tabData.length === 0 ? (
|
||||
<motion.div key="empty" initial={{ opacity: 0 }} animate={{ opacity: 1 }} exit={{ opacity: 0 }} className="flex flex-col items-center justify-center py-20 opacity-20"><Search size={48} className="mb-4" /><span className="text-sm font-black uppercase tracking-[0.3em]">{lang === 'ru' ? 'Пусто' : 'Empty'}</span></motion.div>
|
||||
<motion.div key="empty" initial={{ opacity: 0 }} animate={{ opacity: 1 }} exit={{ opacity: 0 }} className="flex flex-col items-center justify-center py-20 opacity-20"><Search size={48} className="mb-4" /><span className="text-sm font-black uppercase tracking-[0.3em]">{t('empty')}</span></motion.div>
|
||||
) : (
|
||||
<motion.div key="content" initial={{ opacity: 0, y: 10 }} animate={{ opacity: 1, y: 0 }} exit={{ opacity: 0, y: 10 }} className={activeTab === 'media' || activeTab === 'gif' ? "grid grid-cols-3 gap-3" : "flex flex-col gap-3"}>
|
||||
|
||||
@@ -336,7 +336,7 @@ export default function UserProfile({ userId, onClose, onMessage, isSelf: isSelf
|
||||
<button
|
||||
onClick={(e) => { e.stopPropagation(); onGoToMessage?.(item.id, item.createdAt); }}
|
||||
className="p-2.5 rounded-2xl bg-primary/95 text-white shadow-xl backdrop-blur-md hover:scale-110 active:scale-95 transition-all"
|
||||
title={lang === 'ru' ? 'Показать в чате' : 'Show in Chat'}
|
||||
title={t('showInChat')}
|
||||
>
|
||||
<Search size={16} strokeWidth={3} />
|
||||
</button>
|
||||
@@ -365,7 +365,7 @@ export default function UserProfile({ userId, onClose, onMessage, isSelf: isSelf
|
||||
<button
|
||||
onClick={() => onGoToMessage?.(item.id, item.createdAt)}
|
||||
className="p-3 rounded-2xl bg-white/5 opacity-0 group-hover/row:opacity-100 text-white/40 hover:text-white hover:bg-primary/20 transition-all"
|
||||
title={lang === 'ru' ? 'Показать в чате' : 'Show in Chat'}
|
||||
title={t('showInChat')}
|
||||
>
|
||||
<MessageSquare size={20} />
|
||||
</button>
|
||||
|
||||
Reference in New Issue
Block a user