Initial commit from remix
This commit is contained in:
189
src/services/chatApi.ts
Normal file
189
src/services/chatApi.ts
Normal file
@@ -0,0 +1,189 @@
|
||||
// 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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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();
|
||||
Reference in New Issue
Block a user