import { create } from 'zustand'; import { Chat, Message, User } from '../types'; interface AppStore { user: User | null; chats: Chat[]; activeChat: Chat | null; messages: Record; onlineUsers: Set; typingUsers: Record; connected: boolean; chatReadAt: Record; // chatId → ISO timestamp others last read setUser: (user: User | null) => void; setChats: (chats: Chat[]) => void; updateChat: (chat: Partial & { id: string }) => void; setActiveChat: (chat: Chat | null) => void; setMessages: (chatId: string, messages: Message[]) => void; prependMessages: (chatId: string, messages: Message[]) => void; addMessage: (message: Message) => void; updateMessage: (message: Message) => void; removeMessage: (chatId: string, messageId: string) => void; setOnline: (userId: string, online: boolean) => void; setTyping: (chatId: string, userId: string, typing: boolean) => void; setConnected: (v: boolean) => void; markRead: (chatId: string) => void; markReadByOther: (chatId: string) => void; logout: () => void; } function loadUser(): User | null { try { const s = localStorage.getItem('jc_user'); return s ? JSON.parse(s) : null; } catch { return null; } } export const useStore = create((set, get) => ({ user: loadUser(), chats: [], activeChat: null, messages: {}, onlineUsers: new Set(), typingUsers: {}, connected: false, chatReadAt: {}, setUser: (user) => set({ user }), setChats: (chats) => set({ chats }), updateChat: (partial) => set(state => ({ chats: state.chats.map(c => c.id === partial.id ? { ...c, ...partial } : c), activeChat: state.activeChat?.id === partial.id ? { ...state.activeChat, ...partial } : state.activeChat, })), setActiveChat: (chat) => set({ activeChat: chat }), setMessages: (chatId, messages) => set(state => ({ messages: { ...state.messages, [chatId]: messages } })), prependMessages: (chatId, messages) => set(state => ({ messages: { ...state.messages, [chatId]: [...messages, ...(state.messages[chatId] || [])] } })), addMessage: (message) => set(state => { const existing = state.messages[message.chatId] || []; if (existing.find(m => m.id === message.id)) return state; const updated = [...existing, message]; // Update chat last message const chats = state.chats.map(c => c.id === message.chatId ? { ...c, lastMessage: message.content, lastMessageAt: message.createdAt, unreadCount: state.activeChat?.id === message.chatId ? 0 : c.unreadCount + 1 } : c ).sort((a, b) => { const ta = a.lastMessageAt || a.createdAt; const tb = b.lastMessageAt || b.createdAt; return new Date(tb).getTime() - new Date(ta).getTime(); }); return { messages: { ...state.messages, [message.chatId]: updated }, chats }; }), updateMessage: (message) => set(state => ({ messages: { ...state.messages, [message.chatId]: (state.messages[message.chatId] || []).map(m => m.id === message.id ? message : m ) } })), removeMessage: (chatId, messageId) => set(state => ({ messages: { ...state.messages, [chatId]: (state.messages[chatId] || []).map(m => m.id === messageId ? { ...m, isDeleted: true, content: 'Сообщение удалено' } : m ) } })), setOnline: (userId, online) => set(state => { const next = new Set(state.onlineUsers); online ? next.add(userId) : next.delete(userId); return { onlineUsers: next }; }), setTyping: (chatId, userId, typing) => set(state => { const current = state.typingUsers[chatId] || []; const next = typing ? [...new Set([...current, userId])] : current.filter(id => id !== userId); return { typingUsers: { ...state.typingUsers, [chatId]: next } }; }), setConnected: (v) => set({ connected: v }), markRead: (chatId) => set(state => ({ chats: state.chats.map(c => c.id === chatId ? { ...c, unreadCount: 0 } : c) })), markReadByOther: (chatId) => set(state => ({ chatReadAt: { ...state.chatReadAt, [chatId]: new Date().toISOString() } })), logout: () => { localStorage.removeItem('jc_token'); localStorage.removeItem('jc_user'); set({ user: null, chats: [], activeChat: null, messages: {}, connected: false, chatReadAt: {} }); }, }));