| import { ConfirmDeleteDialog } from '@/components/confirm-delete-dialog'; | |
| import ListFilterBar from '@/components/list-filter-bar'; | |
| import { Avatar, AvatarFallback, AvatarImage } from '@/components/ui/avatar'; | |
| import { Button } from '@/components/ui/button'; | |
| import { Card, CardContent } from '@/components/ui/card'; | |
| import { useInfiniteFetchKnowledgeList } from '@/hooks/knowledge-hooks'; | |
| import { useNavigatePage } from '@/hooks/logic-hooks/navigate-hooks'; | |
| import { IKnowledge } from '@/interfaces/database/knowledge'; | |
| import { formatDate } from '@/utils/date'; | |
| import { ChevronRight, Plus, Trash2 } from 'lucide-react'; | |
| import { useMemo } from 'react'; | |
| import { DatasetCreatingDialog } from './dataset-creating-dialog'; | |
| import { useSaveKnowledge } from './hooks'; | |
| export default function Datasets() { | |
| const { | |
| visible, | |
| hideModal, | |
| showModal, | |
| onCreateOk, | |
| loading: creatingLoading, | |
| } = useSaveKnowledge(); | |
| const { navigateToDataset } = useNavigatePage(); | |
| const { | |
| fetchNextPage, | |
| data, | |
| hasNextPage, | |
| searchString, | |
| handleInputChange, | |
| loading, | |
| } = useInfiniteFetchKnowledgeList(); | |
| const nextList: IKnowledge[] = useMemo(() => { | |
| const list = | |
| data?.pages?.flatMap((x) => (Array.isArray(x.kbs) ? x.kbs : [])) ?? []; | |
| return list; | |
| }, [data?.pages]); | |
| const total = useMemo(() => { | |
| return data?.pages.at(-1).total ?? 0; | |
| }, [data?.pages]); | |
| return ( | |
| <section className="p-8 text-foreground"> | |
| <ListFilterBar title="Datasets" showDialog={showModal}> | |
| <Plus className="mr-2 h-4 w-4" /> | |
| Create dataset | |
| </ListFilterBar> | |
| <div className="grid gap-6 sm:grid-cols-1 md:grid-cols-2 lg:grid-cols-4 xl:grid-cols-6 2xl:grid-cols-8"> | |
| {nextList.map((dataset) => ( | |
| <Card | |
| key={dataset.id} | |
| className="bg-colors-background-inverse-weak flex-1" | |
| > | |
| <CardContent className="p-4"> | |
| <div className="flex justify-between mb-4"> | |
| <Avatar className="w-[70px] h-[70px] rounded-lg"> | |
| <AvatarImage src={dataset.avatar} /> | |
| <AvatarFallback className="rounded-lg">CN</AvatarFallback> | |
| </Avatar> | |
| <ConfirmDeleteDialog> | |
| <Button variant="ghost" size="icon"> | |
| <Trash2 /> | |
| </Button> | |
| </ConfirmDeleteDialog> | |
| </div> | |
| <div className="flex justify-between items-end"> | |
| <div> | |
| <h3 className="text-lg font-semibold mb-2">{dataset.name}</h3> | |
| <p className="text-sm opacity-80">{dataset.doc_num} files</p> | |
| <p className="text-sm opacity-80"> | |
| Created {formatDate(dataset.update_time)} | |
| </p> | |
| </div> | |
| <Button | |
| variant="icon" | |
| size="icon" | |
| onClick={navigateToDataset(dataset.id)} | |
| > | |
| <ChevronRight className="h-6 w-6" /> | |
| </Button> | |
| </div> | |
| </CardContent> | |
| </Card> | |
| ))} | |
| </div> | |
| {visible && ( | |
| <DatasetCreatingDialog | |
| hideModal={hideModal} | |
| onOk={onCreateOk} | |
| loading={creatingLoading} | |
| ></DatasetCreatingDialog> | |
| )} | |
| </section> | |
| ); | |
| } | |