veza/apps/web/src/features/chat/components/chat-sidebar/useConversationActions.ts
senke e0f28a0e16 refactor(chat): decompose ChatSidebar into sub-components
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-05 20:07:09 +01:00

82 lines
3.1 KiB
TypeScript

import { useMutation, useQueryClient } from '@tanstack/react-query';
import { apiClient } from '@/services/api/client';
import { useToast } from '@/hooks/useToast';
import { useChatStore } from '../../store/chatStore';
export interface UseConversationActionsCallbacks {
onLeaveError?: (error: Error) => void;
onDeleteError?: (error: Error) => void;
onLeaveSuccess?: () => void;
onDeleteSuccess?: () => void;
}
export function useConversationActions(
userId: string | undefined,
callbacks?: UseConversationActionsCallbacks,
) {
const queryClient = useQueryClient();
const toast = useToast();
const setCurrentConversation = useChatStore((s) => s.setCurrentConversation);
const leaveRoomMutation = useMutation({
mutationFn: async (roomId: string) => {
await apiClient.delete(`/conversations/${roomId}/participants/${userId}`);
},
onMutate: async (roomId: string) => {
await queryClient.cancelQueries({ queryKey: ['chatConversations', userId] });
const previous = queryClient.getQueryData<unknown[]>(['chatConversations', userId]);
if (previous && Array.isArray(previous)) {
queryClient.setQueryData(
['chatConversations', userId],
previous.filter((c: { id: string }) => c.id !== roomId),
);
}
return { previous };
},
onError: (err, _roomId, context) => {
if (context?.previous) {
queryClient.setQueryData(['chatConversations', userId], context.previous);
}
const msg = (err as { response?: { data?: { error?: string } } })?.response?.data?.error ?? 'Failed to leave room';
callbacks?.onLeaveError?.(new Error(msg));
},
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ['chatConversations', userId] });
toast.success('Left room successfully');
setCurrentConversation(null);
callbacks?.onLeaveSuccess?.();
},
});
const deleteRoomMutation = useMutation({
mutationFn: async (roomId: string) => {
await apiClient.delete(`/conversations/${roomId}`);
},
onMutate: async (roomId: string) => {
await queryClient.cancelQueries({ queryKey: ['chatConversations', userId] });
const previous = queryClient.getQueryData<unknown[]>(['chatConversations', userId]);
if (previous && Array.isArray(previous)) {
queryClient.setQueryData(
['chatConversations', userId],
previous.filter((c: { id: string }) => c.id !== roomId),
);
}
return { previous };
},
onError: (err, _roomId, context) => {
if (context?.previous) {
queryClient.setQueryData(['chatConversations', userId], context.previous);
}
const msg = (err as { response?: { data?: { error?: string } } })?.response?.data?.error ?? 'Failed to delete room';
callbacks?.onDeleteError?.(new Error(msg));
},
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ['chatConversations', userId] });
toast.success('Room deleted successfully');
setCurrentConversation(null);
callbacks?.onDeleteSuccess?.();
},
});
return { leaveRoomMutation, deleteRoomMutation };
}