feat(phase2): bulk delete + audit log; update roadmap/parity docs

This commit is contained in:
2026-06-30 10:20:57 -04:00
parent d3b7f39b9e
commit d7c84647e5
12 changed files with 660 additions and 77 deletions
+51 -1
View File
@@ -27,9 +27,10 @@ export interface SearchResultMessage extends Message {
channel_name?: string;
}
interface MessageState {
export interface MessageState {
messagesByChannel: Record<string, Message[]>;
searchResultsByChannel: Record<string, SearchResultMessage[]>;
selectedMessageIds: Record<string, Set<string>>; // ponytail: per-channel bulk selection
isLoading: boolean;
error: string | null;
fetchMessages: (channelId: string, before?: string) => Promise<void>;
@@ -38,11 +39,15 @@ interface MessageState {
addMessage: (message: Message) => void;
updateMessage: (message: Message) => void;
removeMessage: (channelId: string, messageId: string) => void;
bulkDeleteMessages: (channelId: string, messageIds: string[]) => Promise<{ deleted: number }>;
toggleSelectedMessage: (channelId: string, messageId: string) => void;
clearSelectedMessages: (channelId: string) => void;
}
export const useMessageStore = create<MessageState>((set) => ({
messagesByChannel: {},
searchResultsByChannel: {},
selectedMessageIds: {},
isLoading: false,
error: null,
@@ -140,4 +145,49 @@ export const useMessageStore = create<MessageState>((set) => ({
},
};
}),
bulkDeleteMessages: async (channelId, messageIds) => {
const res = await api.post<{ deleted: number }>(
`/channels/${channelId}/messages/bulk-delete`,
{ messages: messageIds },
);
set((state) => {
const list = state.messagesByChannel[channelId] || [];
const ids = new Set(messageIds);
const selected = { ...state.selectedMessageIds };
delete selected[channelId];
return {
messagesByChannel: {
...state.messagesByChannel,
[channelId]: list.filter((m) => !ids.has(m.id)),
},
selectedMessageIds: selected,
};
});
return res;
},
toggleSelectedMessage: (channelId, messageId) =>
set((state) => {
const current = state.selectedMessageIds[channelId] || new Set<string>();
const next = new Set(current);
if (next.has(messageId)) {
next.delete(messageId);
} else {
next.add(messageId);
}
return {
selectedMessageIds: {
...state.selectedMessageIds,
[channelId]: next,
},
};
}),
clearSelectedMessages: (channelId) =>
set((state) => {
const next = { ...state.selectedMessageIds };
delete next[channelId];
return { selectedMessageIds: next };
}),
}));