+
+ {state === "running" && }
+ {state === "done" && (
+
+
+
+ )}
+ {state === "error" && (
+
+
+
+ )}
+
+ {t(key, values)}
+
+
+
+ {state === "error" && part.errorText && (
+
+ {part.errorText}
+
+ )}
+
+ {citations.length > 0 && (
+
+ {citations.map((c) => (
+
+ {c.title || t("Open page")}
+
+ ))}
+
+ )}
+
+ );
+}
diff --git a/apps/client/src/features/ai-chat/queries/ai-chat-query.ts b/apps/client/src/features/ai-chat/queries/ai-chat-query.ts
new file mode 100644
index 00000000..e46f025c
--- /dev/null
+++ b/apps/client/src/features/ai-chat/queries/ai-chat-query.ts
@@ -0,0 +1,116 @@
+import {
+ useInfiniteQuery,
+ useMutation,
+ useQuery,
+ useQueryClient,
+} from "@tanstack/react-query";
+import { useMemo } from "react";
+import { useTranslation } from "react-i18next";
+import { notifications } from "@mantine/notifications";
+import {
+ deleteAiChat,
+ getAiChatMessages,
+ getAiChats,
+ renameAiChat,
+} from "@/features/ai-chat/services/ai-chat-service.ts";
+import {
+ IAiChat,
+ IAiChatMessageRow,
+} from "@/features/ai-chat/types/ai-chat.types.ts";
+import { IPagination } from "@/lib/types.ts";
+
+export const AI_CHATS_RQ_KEY = ["ai-chats"];
+export const AI_CHAT_MESSAGES_RQ_KEY = (chatId: string) => [
+ "ai-chat-messages",
+ chatId,
+];
+
+/** Paginated list of the current user's chats (auto-loads further pages). */
+export function useAiChatsQuery() {
+ const query = useInfiniteQuery({
+ queryKey: AI_CHATS_RQ_KEY,
+ queryFn: ({ pageParam }) =>
+ getAiChats({ cursor: pageParam, limit: 50 }),
+ initialPageParam: undefined as string | undefined,
+ getNextPageParam: (lastPage) =>
+ lastPage.meta.hasNextPage ? (lastPage.meta.nextCursor ?? undefined) : undefined,
+ });
+
+ const data = useMemo