uchill/front_material/api/chat.ts

168 lines
4.7 KiB
TypeScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* API модуль для чата
*/
import apiClient from '@/lib/api-client';
export interface Chat {
id: number;
uuid?: string;
participants?: number[];
participant_name?: string;
avatar_url?: string | null;
other_user_id?: number | null;
other_is_online?: boolean;
other_last_activity?: string | null;
last_message?: string;
last_message_time?: string;
unread_count?: number;
created_at?: string;
// расширенные поля из бэка (для удобного маппинга)
my_participant?: { unread_count?: number; is_muted?: boolean; is_pinned?: boolean };
other_participant?: {
full_name?: string;
first_name?: string;
last_name?: string;
avatar?: string | null;
avatar_url?: string | null;
role?: string;
};
last_message_obj?: any;
}
export interface Message {
id: number;
uuid?: string;
chat: number;
// у системных сообщений может быть строка/NULL
sender: any;
sender_id?: number | null;
sender_name?: string;
content: string;
file?: string;
file_type?: string;
created_at?: string;
is_read?: boolean;
}
export interface PaginatedResponse<T> {
count: number;
next: string | null;
previous: string | null;
results: T[];
}
/**
* Получить список чатов (conversations)
*/
export async function getConversations(params?: {
page?: number;
page_size?: number;
}): Promise<PaginatedResponse<Chat>> {
const response = await apiClient.get<Chat[] | PaginatedResponse<Chat>>('/chat/chats/', {
params,
});
const data: any = response.data;
if (Array.isArray(data)) {
return { count: data.length, next: null, previous: null, results: data };
}
return {
count: data?.count ?? (data?.results?.length ?? 0),
next: data?.next ?? null,
previous: data?.previous ?? null,
results: data?.results ?? [],
};
}
/**
* Получить чат по UUID (detail=true в DRF)
*/
export async function getChatById(uuid: string): Promise<Chat> {
const response = await apiClient.get<Chat>(`/chat/chats/${uuid}/`);
return response.data;
}
/**
* Создать чат
*/
export async function createChat(participantId: number): Promise<Chat> {
const response = await apiClient.post<Chat>('/chat/chats/', {
participants: [participantId],
});
return response.data;
}
/**
* Получить сообщения чата
*/
export async function getMessages(
chatId: number,
params?: { page?: number; page_size?: number }
): Promise<PaginatedResponse<Message>> {
// fallback: если нет uuid — используем общий endpoint
const response = await apiClient.get<PaginatedResponse<Message>>('/chat/messages/', {
params: { ...params, chat: chatId },
});
return response.data;
}
export async function getChatMessagesByUuid(
chatUuid: string,
params?: { page?: number; page_size?: number }
): Promise<PaginatedResponse<Message>> {
const response = await apiClient.get<PaginatedResponse<Message>>(
`/chat/chats/${chatUuid}/messages/`,
{ params }
);
return response.data;
}
/**
* Отправить сообщение
*/
export async function sendMessage(
chatId: number,
content: string,
file?: File
): Promise<Message> {
const formData = new FormData();
formData.append('chat', chatId.toString());
formData.append('content', content);
if (file) {
formData.append('file', file);
}
const response = await apiClient.post<any>('/chat/messages/', formData, {
headers: {
'Content-Type': 'multipart/form-data',
},
});
const data: any = response.data;
// backend может возвращать { success: true, data: {...} }
if (data && typeof data === 'object' && 'data' in data) {
return data.data as Message;
}
return data as Message;
}
/**
* Отметить сообщения как прочитанные
*/
export async function markMessagesAsRead(chatUuid: string, messageUuids?: string[]): Promise<void> {
await apiClient.post(`/chat/chats/${chatUuid}/mark_read/`, messageUuids ? { message_uuids: messageUuids } : {});
}
/**
* Получить или создать чат для урока
*/
export async function getOrCreateLessonChat(lessonId: number): Promise<Chat> {
const res = await apiClient.get<{ success: boolean; data: Chat } | Chat>(
`/chat/chats/lesson_chat/?lesson_id=${lessonId}`
);
const data = res.data;
if (data && typeof data === 'object' && 'success' in data && 'data' in data) {
return (data as { success: boolean; data: Chat }).data;
}
return data as Chat;
}