191 lines
5.2 KiB
TypeScript
191 lines
5.2 KiB
TypeScript
// Chat API Service with configurable endpoints
|
|
import { mockChatData } from './mockChatData';
|
|
|
|
export interface User {
|
|
id: string;
|
|
name: string;
|
|
email: string;
|
|
avatar: string;
|
|
online: boolean;
|
|
lastSeen?: string;
|
|
serviceType?: 'taxi' | 'restaurant' | 'hotel' | 'guide' | 'politur' | 'support';
|
|
}
|
|
|
|
export interface Message {
|
|
id: string;
|
|
chatId: string;
|
|
senderId: string;
|
|
senderName: string;
|
|
senderAvatar: string;
|
|
content: string;
|
|
timestamp: string;
|
|
isOwn: boolean;
|
|
status: 'sent' | 'delivered' | 'read';
|
|
}
|
|
|
|
export interface Chat {
|
|
id: string;
|
|
name: string;
|
|
type: 'direct' | 'group';
|
|
participants: User[];
|
|
lastMessage?: Message;
|
|
unreadCount: number;
|
|
avatar?: string;
|
|
online?: boolean;
|
|
lastActivity: string;
|
|
serviceType?: 'taxi' | 'restaurant' | 'hotel' | 'guide' | 'politur' | 'support';
|
|
}
|
|
|
|
class ChatApiService {
|
|
private baseUrl: string;
|
|
private apiKey: string;
|
|
private useMockData: boolean;
|
|
|
|
constructor() {
|
|
// In a real environment, these would come from environment variables
|
|
this.baseUrl = import.meta.env.VITE_CHAT_API_URL || 'http://localhost:3001/api';
|
|
this.apiKey = import.meta.env.VITE_CHAT_API_KEY || '';
|
|
this.useMockData = !this.apiKey || import.meta.env.DEV;
|
|
}
|
|
|
|
private async apiCall<T>(endpoint: string, options: RequestInit = {}): Promise<T> {
|
|
if (this.useMockData) {
|
|
// Return mock data
|
|
return this.getMockData(endpoint) as T;
|
|
}
|
|
|
|
const response = await fetch(`${this.baseUrl}${endpoint}`, {
|
|
...options,
|
|
headers: {
|
|
'Content-Type': 'application/json',
|
|
'Authorization': `Bearer ${this.apiKey}`,
|
|
...options.headers,
|
|
},
|
|
});
|
|
|
|
if (!response.ok) {
|
|
throw new Error(`API call failed: ${response.statusText}`);
|
|
}
|
|
|
|
return response.json();
|
|
}
|
|
|
|
private getMockData(endpoint: string): any {
|
|
// Simulate API responses with mock data
|
|
const delay = () => new Promise(resolve => setTimeout(resolve, 100 + Math.random() * 500));
|
|
|
|
return new Promise(async (resolve) => {
|
|
await delay();
|
|
|
|
if (endpoint.includes('/chats')) {
|
|
resolve(mockChatData.chats);
|
|
} else if (endpoint.includes('/users')) {
|
|
resolve(mockChatData.users);
|
|
} else if (endpoint.includes('/messages')) {
|
|
const chatId = endpoint.split('/')[2];
|
|
resolve(mockChatData.messages.filter(m => m.chatId === chatId));
|
|
} else if (endpoint.includes('/search')) {
|
|
resolve(mockChatData.users);
|
|
} else {
|
|
resolve([]);
|
|
}
|
|
});
|
|
}
|
|
|
|
// Get all chats for current user
|
|
async getChats(): Promise<Chat[]> {
|
|
return this.apiCall<Chat[]>('/chats');
|
|
}
|
|
|
|
// Get messages for a specific chat
|
|
async getMessages(chatId: string): Promise<Message[]> {
|
|
return this.apiCall<Message[]>(`/chats/${chatId}/messages`);
|
|
}
|
|
|
|
// Send a message
|
|
async sendMessage(chatId: string, content: string): Promise<Message> {
|
|
if (this.useMockData) {
|
|
const newMessage: Message = {
|
|
id: Date.now().toString(),
|
|
chatId,
|
|
senderId: 'current-user',
|
|
senderName: 'You',
|
|
senderAvatar: '/api/placeholder/40/40',
|
|
content,
|
|
timestamp: new Date().toLocaleTimeString(),
|
|
isOwn: true,
|
|
status: 'sent'
|
|
};
|
|
mockChatData.messages.push(newMessage);
|
|
return newMessage;
|
|
}
|
|
|
|
return this.apiCall<Message>(`/chats/${chatId}/messages`, {
|
|
method: 'POST',
|
|
body: JSON.stringify({ content }),
|
|
});
|
|
}
|
|
|
|
// Search users
|
|
async searchUsers(query: string): Promise<User[]> {
|
|
if (this.useMockData) {
|
|
await new Promise(resolve => setTimeout(resolve, 300));
|
|
return mockChatData.users.filter(user =>
|
|
user.name.toLowerCase().includes(query.toLowerCase()) ||
|
|
user.email.toLowerCase().includes(query.toLowerCase())
|
|
);
|
|
}
|
|
|
|
return this.apiCall<User[]>(`/users/search?q=${encodeURIComponent(query)}`);
|
|
}
|
|
|
|
// Create a new chat
|
|
async createChat(participantIds: string[]): Promise<Chat> {
|
|
if (this.useMockData) {
|
|
const participants = mockChatData.users.filter(user =>
|
|
participantIds.includes(user.id)
|
|
);
|
|
|
|
const newChat: Chat = {
|
|
id: Date.now().toString(),
|
|
name: participants.length === 1 ? participants[0].name : `Group Chat`,
|
|
type: participants.length === 1 ? 'direct' : 'group',
|
|
participants,
|
|
unreadCount: 0,
|
|
lastActivity: new Date().toISOString(),
|
|
avatar: participants[0]?.avatar,
|
|
online: participants[0]?.online
|
|
};
|
|
|
|
mockChatData.chats.push(newChat);
|
|
return newChat;
|
|
}
|
|
|
|
return this.apiCall<Chat>('/chats', {
|
|
method: 'POST',
|
|
body: JSON.stringify({ participantIds }),
|
|
});
|
|
}
|
|
|
|
// Get online users
|
|
async getOnlineUsers(): Promise<User[]> {
|
|
const users = await this.apiCall<User[]>('/users/online');
|
|
return users.filter(user => user.online);
|
|
}
|
|
|
|
// Mark messages as read
|
|
async markAsRead(chatId: string): Promise<void> {
|
|
if (this.useMockData) {
|
|
// Update mock data
|
|
const chat = mockChatData.chats.find(c => c.id === chatId);
|
|
if (chat) {
|
|
chat.unreadCount = 0;
|
|
}
|
|
return;
|
|
}
|
|
|
|
await this.apiCall(`/chats/${chatId}/read`, { method: 'POST' });
|
|
}
|
|
}
|
|
|
|
export const chatApi = new ChatApiService(); |