nexus/ui/src/hooks/useChatMessages.ts
Nexus Dev 2d7e1374ba feat(21-05): create chat API client and TanStack Query hooks
- Add ui/src/api/chat.ts with chatApi (7 methods: list/create/get/update/delete conversations + list/post messages)
- Add ui/src/hooks/useChatConversations.ts with useInfiniteQuery + placeholderData + CRUD mutations
- Add ui/src/hooks/useChatMessages.ts with useInfiniteQuery + sendMutation + flattened/reversed messages array
- Fix [Rule 3 - Blocking]: export ChatConversation, ChatMessage, ChatConversationListResponse, ChatMessageListResponse from packages/shared/src/index.ts (types existed in types/chat.ts but were not re-exported at package root)
2026-04-02 15:08:50 +00:00

33 lines
1.5 KiB
TypeScript

import { useInfiniteQuery, useMutation, useQueryClient } from "@tanstack/react-query";
import { chatApi } from "../api/chat";
import type { ChatMessage, ChatMessageListResponse } from "@paperclipai/shared";
export function useChatMessages(conversationId: string | null) {
const queryClient = useQueryClient();
const query = useInfiniteQuery({
queryKey: ["chat", "messages", conversationId],
queryFn: ({ pageParam }) =>
chatApi.listMessages(conversationId!, { cursor: pageParam as string | undefined }),
initialPageParam: undefined as string | undefined,
getNextPageParam: (lastPage: ChatMessageListResponse) =>
lastPage.hasMore ? lastPage.items.at(-1)?.createdAt : undefined,
enabled: !!conversationId,
});
const sendMutation = useMutation({
mutationFn: (data: { content: string }) =>
chatApi.postMessage(conversationId!, { role: "user", content: data.content }),
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ["chat", "messages", conversationId] });
// Also invalidate conversations to update lastMessagePreview and sort order
queryClient.invalidateQueries({ queryKey: ["chat", "conversations"] });
},
});
// Flatten pages into a single sorted array (oldest first for display)
// Messages come from API in desc(createdAt) order -- reversing gives chronological order
const messages: ChatMessage[] = query.data?.pages.flatMap((p) => p.items).reverse() ?? [];
return { ...query, messages, sendMutation };
}