Фронт

This commit is contained in:
Халимов Рустам
2026-03-27 16:04:46 +03:00
parent 28fb8c25de
commit 030ae1e4e4
19 changed files with 234 additions and 174 deletions

View File

@@ -2,9 +2,12 @@
export interface UserBasic {
id: string;
username: string;
userName: string;
displayName: string;
avatar: string | null;
avatarUrl: string | null;
// Fallbacks for compatibility
username?: string;
avatar?: string | null;
}
export interface UserPresence extends UserBasic {
@@ -48,14 +51,23 @@ export interface Reaction {
id: string;
emoji: string;
userId: string;
user: { id: string; username: string; displayName: string; avatar?: string | null };
user: {
id: string;
username: string;
userName?: string;
displayName: string;
avatar?: string | null;
avatarUrl?: string | null;
};
}
export interface MessageSender {
id: string;
username: string;
userName?: string;
displayName: string;
avatar?: string | null;
avatarUrl?: string | null;
}
export interface Message {
@@ -93,10 +105,11 @@ export interface Message {
export interface Chat {
id: string;
type: string;
type: 'personal' | 'group' | 'channel' | 'favorites';
name: string | null;
description?: string | null;
avatar: string | null;
avatarUrl?: string | null;
createdAt: string;
members: ChatMember[];
messages: Message[];
@@ -152,8 +165,6 @@ export interface StoryGroup {
hasUnviewed: boolean;
}
// ─── Utility types ─────────────────────────────────────────────────
// ─── Friend types ──────────────────────────────────────────────────
export interface FriendRequest {

View File

@@ -1,3 +1,4 @@
import { deepNormalize } from '../utils/normalize';
const API_BASE = '/api';
export class HttpClient {
@@ -44,7 +45,8 @@ export class HttpClient {
throw new Error(errorMessage);
}
return response.json();
const jsonData = await response.json();
return deepNormalize(jsonData);
}
}

View File

@@ -73,7 +73,7 @@ export default function Sidebar() {
return chat.members.some(
(m) =>
m.user.id !== user?.id &&
(m.user.username.toLowerCase().includes(q) ||
((m.user.username || m.user.userName || '').toLowerCase().includes(q) ||
m.user.displayName.toLowerCase().includes(q))
);
}).sort((a, b) => {
@@ -163,7 +163,8 @@ export default function Sidebar() {
</button>
{storyGroups.map((group, idx) => {
const avatarUrl = group.user.avatar ? `${API_URL}${group.user.avatar}` : null;
const avatar = group.user.avatarUrl || group.user.avatar;
const avatarUrl = avatar ? `${API_URL}${avatar}` : null;
const isMine = group.user.id === user?.id;
return (
<button
@@ -187,7 +188,7 @@ export default function Sidebar() {
</div>
</div>
<span className="text-[11px] text-zinc-400 truncate w-full text-center">
{isMine ? t('myStory') : (group.user.displayName || group.user.username).split(' ')[0]}
{isMine ? t('myStory') : (group.user.displayName || group.user.userName || group.user.username || '').split(' ')[0]}
</span>
</button>
);

View File

@@ -0,0 +1,67 @@
/**
* Глобальная нормализация данных пользователя.
* Приводит данные от разных модулей (Profiles, Auth, Message) к единому виду.
*
* ВАЖНО: Мы не импортируем здесь типы из types.ts, чтобы избежать круговых зависимостей.
*/
export function normalizeUser(user: any): any {
if (!user || typeof user !== 'object') return user;
const result = { ...user };
// 1. Приведение username (Auth -> userName, Profiles -> userName)
if (!result.userName && result.username) {
result.userName = result.username;
}
if (!result.username && result.userName) {
result.username = result.userName;
}
// 2. Приведение avatar (Auth -> avatar, Profiles -> avatarUrl)
if (!result.avatarUrl && result.avatar) {
result.avatarUrl = result.avatar;
}
if (!result.avatar && result.avatarUrl) {
result.avatar = result.avatarUrl;
}
return result;
}
/**
* Рекурсивная нормализация любого объекта/массива на наличие полей пользователя.
*/
export function deepNormalize(obj: any): any {
if (!obj || typeof obj !== 'object') {
return obj;
}
// Если это File, Blob или FormData - не трогаем
if (obj instanceof Blob || obj instanceof FormData) {
return obj;
}
if (Array.isArray(obj)) {
return obj.map(deepNormalize);
}
// Создаем копию для мутации
const result = { ...obj };
// Если это объект, похожий на пользователя (есть id и userName/username)
if (result.id && (result.userName || result.username)) {
const normalized = normalizeUser(result);
// Продолжаем рекурсию по остальным полям (например, если у пользователя есть вложенные объекты)
for (const key in normalized) {
normalized[key] = deepNormalize(normalized[key]);
}
return normalized;
}
// Рекурсивно проходим по всем полям
for (const key in result) {
result[key] = deepNormalize(result[key]);
}
return result;
}