"use client"; import { ArrowLeft, Check, Copy, Loader2, Search } from "lucide-react"; import { Suspense, useCallback, useEffect, useMemo, useState } from "react"; import { useRouter, useSearchParams } from "next/navigation"; import { ProtectedRoute } from "@/components/protected-route"; import { Button } from "@/components/ui/button"; import { useKnowledgeFilter } from "@/contexts/knowledge-filter-context"; import { useTask } from "@/contexts/task-context"; import { type ChunkResult, type File, useGetSearchQuery, } from "../../api/queries/useGetSearchQuery"; import { Label } from "@/components/ui/label"; import { Checkbox } from "@/components/ui/checkbox"; import { Input } from "@/components/ui/input"; const getFileTypeLabel = (mimetype: string) => { if (mimetype === "application/pdf") return "PDF"; if (mimetype === "text/plain") return "Text"; if (mimetype === "application/msword") return "Word Document"; return "Unknown"; }; function ChunksPageContent() { const router = useRouter(); const searchParams = useSearchParams(); const { isMenuOpen } = useTask(); const { parsedFilterData, isPanelOpen } = useKnowledgeFilter(); const filename = searchParams.get("filename"); const [chunks, setChunks] = useState([]); const [chunksFilteredByQuery, setChunksFilteredByQuery] = useState< ChunkResult[] >([]); const [selectedChunks, setSelectedChunks] = useState>(new Set()); const [activeCopiedChunkIndex, setActiveCopiedChunkIndex] = useState< number | null >(null); // Calculate average chunk length const averageChunkLength = useMemo( () => chunks.reduce((acc, chunk) => acc + chunk.text.length, 0) / chunks.length || 0, [chunks] ); const [selectAll, setSelectAll] = useState(false); const [queryInputText, setQueryInputText] = useState( parsedFilterData?.query ?? "" ); // Use the same search query as the knowledge page, but we'll filter for the specific file const { data = [], isFetching } = useGetSearchQuery("*", parsedFilterData); useEffect(() => { if (queryInputText === "") { setChunksFilteredByQuery(chunks); } else { setChunksFilteredByQuery( chunks.filter((chunk) => chunk.text.toLowerCase().includes(queryInputText.toLowerCase()) ) ); } }, [queryInputText, chunks]); const handleCopy = useCallback((text: string, index: number) => { // Trim whitespace and remove new lines/tabs for cleaner copy navigator.clipboard.writeText(text.trim().replace(/[\n\r\t]/gm, "")); setActiveCopiedChunkIndex(index); setTimeout(() => setActiveCopiedChunkIndex(null), 10 * 1000); // 10 seconds }, []); const fileData = (data as File[]).find( (file: File) => file.filename === filename ); // Extract chunks for the specific file useEffect(() => { if (!filename || !(data as File[]).length) { setChunks([]); return; } setChunks(fileData?.chunks || []); }, [data, filename]); // Set selected state for all checkboxes when selectAll changes useEffect(() => { if (selectAll) { setSelectedChunks(new Set(chunks.map((_, index) => index))); } else { setSelectedChunks(new Set()); } }, [selectAll, setSelectedChunks, chunks]); const handleBack = useCallback(() => { router.push("/knowledge"); }, [router]); const handleChunkCardCheckboxChange = useCallback( (index: number) => { setSelectedChunks((prevSelected) => { const newSelected = new Set(prevSelected); if (newSelected.has(index)) { newSelected.delete(index); } else { newSelected.add(index); } return newSelected; }); }, [setSelectedChunks] ); if (!filename) { return (

No file specified

Please select a file from the knowledge page

); } return (
{/* Header */}

{/* Removes file extension from filename */} {filename.replace(/\.[^/.]+$/, "")}

: null} id="search-query" type="text" defaultValue={parsedFilterData?.query} value={queryInputText} onChange={(e) => setQueryInputText(e.target.value)} placeholder="Search chunks..." />
setSelectAll(!!handleSelectAll) } />
{/* Content Area - matches knowledge page structure */}
{isFetching ? (

Loading chunks...

) : chunks.length === 0 ? (

No chunks found

This file may not have been indexed yet

) : (
{chunksFilteredByQuery.map((chunk, index) => (
handleChunkCardCheckboxChange(index) } />
Chunk {chunk.page} {chunk.text.length} chars
{/* TODO: Update to use active toggle */} {/* Active */}
{chunk.text}
))}
)}
{/* Right panel - Summary (TODO), Technical details, */}

Technical details

Total chunks
{chunks.length}
Avg length
{averageChunkLength.toFixed(0)} chars
{/* TODO: Uncomment after data is available */} {/*
Process time
Model
*/}

Original document

Name
{fileData?.filename}
Type
{fileData ? getFileTypeLabel(fileData.mimetype) : "Unknown"}
Size
{fileData?.size ? `${Math.round(fileData.size / 1024)} KB` : "Unknown"}
Uploaded
N/A
{/* TODO: Uncomment after data is available */} {/*
Source
*/}
Updated
N/A
); } function ChunksPage() { return (

Loading...

} >
); } export default function ProtectedChunksPage() { return ( ); }