Files
dumpsterChat/web/src/stores/message.ts
T

111 lines
2.9 KiB
TypeScript

import { create } from "zustand";
import { api } from "../lib/api.ts";
export interface Message {
id: string;
channel_id: string;
author_id: string;
author_username: string;
author_display_name: string | null;
content: string;
created_at: string;
edited_at: string | null;
}
interface MessageState {
messagesByChannel: Record<string, Message[]>;
isLoading: boolean;
error: string | null;
fetchMessages: (channelId: string, before?: string) => Promise<void>;
sendMessage: (channelId: string, content: string) => Promise<Message>;
addMessage: (message: Message) => void;
updateMessage: (message: Message) => void;
removeMessage: (channelId: string, messageId: string) => void;
}
export const useMessageStore = create<MessageState>((set) => ({
messagesByChannel: {},
isLoading: false,
error: null,
fetchMessages: async (channelId, before) => {
set({ isLoading: true, error: null });
try {
const params = before ? `?before=${encodeURIComponent(before)}` : "";
const messages = await api.get<Message[]>(
`/channels/${channelId}/messages${params}`,
);
set((state) => ({
messagesByChannel: {
...state.messagesByChannel,
[channelId]: Array.isArray(messages) ? messages : [],
},
isLoading: false,
}));
} catch (error) {
set({
isLoading: false,
error:
error instanceof Error
? error.message
: "Failed to fetch messages",
});
}
},
sendMessage: async (channelId, content) => {
const message = await api.post<Message>(
`/channels/${channelId}/messages`,
{ content },
);
set((state) => {
const list = state.messagesByChannel[channelId] || [];
return {
messagesByChannel: {
...state.messagesByChannel,
[channelId]: [...list, message],
},
};
});
return message;
},
addMessage: (message) =>
set((state) => {
const list = state.messagesByChannel[message.channel_id] || [];
if (list.some((m) => m.id === message.id)) {
return state;
}
return {
messagesByChannel: {
...state.messagesByChannel,
[message.channel_id]: [...list, message],
},
};
}),
updateMessage: (message) =>
set((state) => {
const list = state.messagesByChannel[message.channel_id] || [];
return {
messagesByChannel: {
...state.messagesByChannel,
[message.channel_id]: list.map((m) =>
m.id === message.id ? message : m,
),
},
};
}),
removeMessage: (channelId, messageId) =>
set((state) => {
const list = state.messagesByChannel[channelId] || [];
return {
messagesByChannel: {
...state.messagesByChannel,
[channelId]: list.filter((m) => m.id !== messageId),
},
};
}),
}));