feat(24-02): API client methods and React Query hooks for search, bookmarks, branches
- Add searchMessages, toggleBookmark, getBookmarks, branchConversation, listBranches, exportConversation to chatApi - Create useChatSearch hook with debounced FTS, placeholderData, 30s staleTime - Create useChatBookmarks and useToggleBookmark with cache invalidation for bookmarks and search queries
This commit is contained in:
parent
d78bdad0a9
commit
1b80631b66
3 changed files with 90 additions and 0 deletions
|
|
@ -4,6 +4,9 @@ import type {
|
|||
ChatConversationListResponse,
|
||||
ChatMessage,
|
||||
ChatMessageListResponse,
|
||||
ChatMessageSearchResponse,
|
||||
ChatBookmarkToggleResponse,
|
||||
ChatBookmarkListResponse,
|
||||
} from "@paperclipai/shared";
|
||||
|
||||
export const chatApi = {
|
||||
|
|
@ -166,4 +169,46 @@ export const chatApi = {
|
|||
) {
|
||||
return api.post<{ id: string }>(`/conversations/${conversationId}/status-update`, data);
|
||||
},
|
||||
|
||||
searchMessages(companyId: string, q: string, limit?: number) {
|
||||
const params = new URLSearchParams({ q });
|
||||
if (limit) params.set("limit", String(limit));
|
||||
return api.get<ChatMessageSearchResponse>(
|
||||
`/companies/${companyId}/messages/search?${params}`,
|
||||
);
|
||||
},
|
||||
|
||||
toggleBookmark(conversationId: string, messageId: string) {
|
||||
return api.post<ChatBookmarkToggleResponse>(
|
||||
`/conversations/${conversationId}/bookmarks`,
|
||||
{ messageId },
|
||||
);
|
||||
},
|
||||
|
||||
getBookmarks(companyId: string, conversationId?: string) {
|
||||
const params = new URLSearchParams();
|
||||
if (conversationId) params.set("conversationId", conversationId);
|
||||
const qs = params.toString();
|
||||
return api.get<ChatBookmarkListResponse>(
|
||||
`/companies/${companyId}/bookmarks${qs ? `?${qs}` : ""}`,
|
||||
);
|
||||
},
|
||||
|
||||
branchConversation(conversationId: string, branchFromMessageId: string) {
|
||||
return api.post<ChatConversation>(
|
||||
`/conversations/${conversationId}/branch`,
|
||||
{ branchFromMessageId },
|
||||
);
|
||||
},
|
||||
|
||||
listBranches(conversationId: string) {
|
||||
return api.get<{ items: ChatConversation[] }>(
|
||||
`/conversations/${conversationId}/branches`,
|
||||
);
|
||||
},
|
||||
|
||||
exportConversation(conversationId: string, format: "markdown" | "json") {
|
||||
// Returns a download URL — use window.location.href to trigger
|
||||
return `/api/conversations/${conversationId}/export?format=${format}`;
|
||||
},
|
||||
};
|
||||
|
|
|
|||
33
ui/src/hooks/useChatBookmarks.ts
Normal file
33
ui/src/hooks/useChatBookmarks.ts
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
|
||||
import { chatApi } from "../api/chat";
|
||||
|
||||
export function useChatBookmarks(companyId: string | null, conversationId?: string) {
|
||||
const query = useQuery({
|
||||
queryKey: ["chat", "bookmarks", companyId, conversationId],
|
||||
queryFn: () => chatApi.getBookmarks(companyId!, conversationId),
|
||||
enabled: !!companyId,
|
||||
});
|
||||
|
||||
return {
|
||||
data: query.data,
|
||||
isLoading: query.isLoading,
|
||||
};
|
||||
}
|
||||
|
||||
export function useToggleBookmark() {
|
||||
const queryClient = useQueryClient();
|
||||
|
||||
const mutation = useMutation({
|
||||
mutationFn: ({ conversationId, messageId }: { conversationId: string; messageId: string }) =>
|
||||
chatApi.toggleBookmark(conversationId, messageId),
|
||||
onSuccess: () => {
|
||||
void queryClient.invalidateQueries({ queryKey: ["chat", "bookmarks"] });
|
||||
void queryClient.invalidateQueries({ queryKey: ["chat", "search"] });
|
||||
},
|
||||
});
|
||||
|
||||
return {
|
||||
toggleBookmark: mutation.mutate,
|
||||
isPending: mutation.isPending,
|
||||
};
|
||||
}
|
||||
12
ui/src/hooks/useChatSearch.ts
Normal file
12
ui/src/hooks/useChatSearch.ts
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
import { useQuery } from "@tanstack/react-query";
|
||||
import { chatApi } from "../api/chat";
|
||||
|
||||
export function useChatSearch(companyId: string | null, query: string) {
|
||||
return useQuery({
|
||||
queryKey: ["chat", "search", companyId, query],
|
||||
queryFn: () => chatApi.searchMessages(companyId!, query),
|
||||
enabled: !!companyId && query.trim().length >= 2,
|
||||
placeholderData: (prev) => prev,
|
||||
staleTime: 30_000,
|
||||
});
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue