Локализация

This commit is contained in:
Халимов Рустам
2026-04-05 00:34:25 +03:00
parent f41ad0bcf8
commit 53f193970c
10 changed files with 243 additions and 133 deletions
@@ -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>