Initial commit from remix

This commit is contained in:
gpt-engineer-app[bot]
2025-09-25 16:01:00 +00:00
commit 5ddc52658d
149 changed files with 32798 additions and 0 deletions

189
src/services/chatApi.ts Normal file
View 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();