core/apps/webapp/app/hooks/use-logs.tsx
Harshith Mullapudi bcc0560cf0
Feat: Space (#93)
* Feat: change space assignment from statement to episode

* feat: add default spaces and improve integration, space tools discovery in MCP

* feat: change spaces to episode based

* Feat: take multiple spaceIds while ingesting

* Feat: modify mcp tool descriptions, add spaceId in mcp url

* feat: add copy

* bump: new version 0.1.24

---------

Co-authored-by: Manoj <saimanoj58@gmail.com>
2025-10-09 12:38:42 +05:30

126 lines
3.1 KiB
TypeScript

import { useEffect, useState, useCallback } from "react";
import { useFetcher } from "@remix-run/react";
export interface LogItem {
id: string;
source: string;
ingestText: string;
time: string;
processedAt?: string;
status: "PENDING" | "PROCESSING" | "COMPLETED" | "FAILED" | "CANCELLED";
error?: string;
sourceURL?: string;
type?: string;
integrationSlug?: string;
activityId?: string;
episodeUUID?: string;
data?: any;
spaceIds?: string[];
episodeDetails?: any;
}
export interface LogsResponse {
logs: LogItem[];
totalCount: number;
page: number;
limit: number;
hasMore: boolean;
availableSources: Array<{ name: string; slug: string }>;
}
export interface UseLogsOptions {
endpoint: string; // '/api/v1/logs/all' or '/api/v1/logs/activity'
source?: string;
status?: string;
type?: string;
}
export function useLogs({ endpoint, source, status, type }: UseLogsOptions) {
const fetcher = useFetcher<LogsResponse>();
const [logs, setLogs] = useState<LogItem[]>([]);
const [page, setPage] = useState(1);
const [hasMore, setHasMore] = useState(true);
const [availableSources, setAvailableSources] = useState<
Array<{ name: string; slug: string }>
>([]);
const [isInitialLoad, setIsInitialLoad] = useState(true);
const buildUrl = useCallback(
(pageNum: number) => {
const params = new URLSearchParams();
params.set("page", pageNum.toString());
params.set("limit", "50");
if (source) params.set("source", source);
if (status) params.set("status", status);
if (type) params.set("type", type);
return `${endpoint}?${params.toString()}`;
},
[endpoint, source, status, type],
);
const loadMore = useCallback(() => {
if (fetcher.state === "idle" && hasMore) {
fetcher.load(buildUrl(page + 1));
}
}, [hasMore, page, buildUrl]);
const reset = useCallback(() => {
setLogs([]);
setPage(1);
setHasMore(true);
setIsInitialLoad(true);
fetcher.load(buildUrl(1));
}, [buildUrl]);
// Effect to handle fetcher data
useEffect(() => {
if (fetcher.data) {
const {
logs: newLogs,
hasMore: newHasMore,
page: currentPage,
availableSources: sources,
} = fetcher.data;
if (currentPage === 1) {
// First page or reset
setLogs(newLogs);
setIsInitialLoad(false);
} else {
// Append to existing logs
setLogs((prev) => [...prev, ...newLogs]);
}
setHasMore(newHasMore);
setPage(currentPage);
setAvailableSources(sources);
}
}, [fetcher.data]);
// Effect to reset when filters change
useEffect(() => {
setLogs([]);
setPage(1);
setHasMore(true);
setIsInitialLoad(true);
fetcher.load(buildUrl(1));
}, [source, status, type, buildUrl]); // Inline reset logic to avoid dependency issues
// Initial load
useEffect(() => {
if (isInitialLoad) {
fetcher.load(buildUrl(1));
}
}, [isInitialLoad, buildUrl]);
return {
logs,
hasMore,
loadMore,
reset,
availableSources,
isLoading: fetcher.state === "loading",
isInitialLoad,
};
}