Refactor Search component to use Dialog for improved user experience; integrate Pagination component for better navigation of search results

This commit is contained in:
ecwu
2024-12-21 22:27:07 +08:00
parent de4aca9498
commit c6fbe5c031
3 changed files with 82 additions and 78 deletions

View File

@@ -1,8 +1,8 @@
import * as React from "react"
import { ChevronLeft, ChevronRight, MoreHorizontal } from "lucide-react"
import * as React from "react";
import { ChevronLeft, ChevronRight, MoreHorizontal } from "lucide-react";
import { cn } from "@/lib/utils"
import { ButtonProps, buttonVariants } from "@/components/ui/button"
import { cn } from "@/lib/utils";
import { ButtonProps, buttonVariants } from "@/components/ui/button";
const Pagination = ({ className, ...props }: React.ComponentProps<"nav">) => (
<nav
@@ -11,8 +11,8 @@ const Pagination = ({ className, ...props }: React.ComponentProps<"nav">) => (
className={cn("mx-auto flex w-full justify-center", className)}
{...props}
/>
)
Pagination.displayName = "Pagination"
);
Pagination.displayName = "Pagination";
const PaginationContent = React.forwardRef<
HTMLUListElement,
@@ -23,21 +23,21 @@ const PaginationContent = React.forwardRef<
className={cn("flex flex-row items-center gap-1", className)}
{...props}
/>
))
PaginationContent.displayName = "PaginationContent"
));
PaginationContent.displayName = "PaginationContent";
const PaginationItem = React.forwardRef<
HTMLLIElement,
React.ComponentProps<"li">
>(({ className, ...props }, ref) => (
<li ref={ref} className={cn("", className)} {...props} />
))
PaginationItem.displayName = "PaginationItem"
));
PaginationItem.displayName = "PaginationItem";
type PaginationLinkProps = {
isActive?: boolean
isActive?: boolean;
} & Pick<ButtonProps, "size"> &
React.ComponentProps<"a">
React.ComponentProps<"a">;
const PaginationLink = ({
className,
@@ -56,8 +56,8 @@ const PaginationLink = ({
)}
{...props}
/>
)
PaginationLink.displayName = "PaginationLink"
);
PaginationLink.displayName = "PaginationLink";
const PaginationPrevious = ({
className,
@@ -70,10 +70,10 @@ const PaginationPrevious = ({
{...props}
>
<ChevronLeft className="h-4 w-4" />
<span>Previous</span>
{/* <span>Previous</span> */}
</PaginationLink>
)
PaginationPrevious.displayName = "PaginationPrevious"
);
PaginationPrevious.displayName = "PaginationPrevious";
const PaginationNext = ({
className,
@@ -85,11 +85,11 @@ const PaginationNext = ({
className={cn("gap-1 pr-2.5", className)}
{...props}
>
<span>Next</span>
{/* <span>Next</span> */}
<ChevronRight className="h-4 w-4" />
</PaginationLink>
)
PaginationNext.displayName = "PaginationNext"
);
PaginationNext.displayName = "PaginationNext";
const PaginationEllipsis = ({
className,
@@ -103,8 +103,8 @@ const PaginationEllipsis = ({
<MoreHorizontal className="h-4 w-4" />
<span className="sr-only">More pages</span>
</span>
)
PaginationEllipsis.displayName = "PaginationEllipsis"
);
PaginationEllipsis.displayName = "PaginationEllipsis";
export {
Pagination,
@@ -114,4 +114,4 @@ export {
PaginationPrevious,
PaginationNext,
PaginationEllipsis,
}
};

View File

@@ -42,6 +42,7 @@ import WhisperButton from "@/components/WhisperButton";
import AddToolMsg from "./AddToolMsg";
import { Textarea } from "@/components/ui/textarea";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { ChatInput } from "@/components/ui/chat/chat-input";
import {
ChatBubble,
@@ -508,6 +509,7 @@ export default function ChatBOX(props: {
setSelectedChatIndex={props.setSelectedChatIndex}
db={props.db}
chatStore={chatStore}
show={showSearch}
setShow={setShowSearch}
/>
)}

View File

@@ -4,6 +4,27 @@ import { StateUpdater, useRef, useState, Dispatch } from "preact/hooks";
import { ChatStore } from "@/types/chatstore";
import { MessageDetail } from "./chatgpt";
import {
Dialog,
DialogContent,
DialogDescription,
DialogHeader,
DialogTitle,
DialogTrigger,
} from "@/components/ui/dialog";
import {
Pagination,
PaginationContent,
PaginationEllipsis,
PaginationItem,
PaginationLink,
PaginationNext,
PaginationPrevious,
} from "@/components/ui/pagination";
import { Input } from "./components/ui/input";
interface ChatStoreSearchResult {
key: IDBValidKey;
cs: ChatStore;
@@ -15,6 +36,7 @@ export default function Search(props: {
db: Promise<IDBPDatabase<ChatStore>>;
setSelectedChatIndex: Dispatch<StateUpdater<number>>;
chatStore: ChatStore;
show: boolean;
setShow: (show: boolean) => void;
}) {
const [searchResult, setSearchResult] = useState<ChatStoreSearchResult[]>([]);
@@ -24,29 +46,15 @@ export default function Search(props: {
const searchAbortRef = useRef<AbortController | null>(null);
return (
<div
onClick={() => props.setShow(false)}
className="left-0 top-0 overflow-scroll flex justify-center absolute w-screen h-full bg-black bg-opacity-50 z-10"
>
<div
onClick={(event: any) => {
event.stopPropagation();
}}
className="m-2 p-2 bg-base-300 rounded-lg h-fit w-2/3 z-20"
>
<div className="flex justify-between">
<span className="m-1 p-1 font-bold">Search</span>
<button
className="m-1 p-1 btn btn-sm btn-secondary"
onClick={() => props.setShow(false)}
>
Close
</button>
</div>
<Dialog open={props.show} onOpenChange={props.setShow}>
<DialogContent className="sm:max-w-[425px]">
<DialogHeader>
<DialogTitle>Search</DialogTitle>
<DialogDescription>Search messages by content.</DialogDescription>
</DialogHeader>
<div>
<input
<Input
autoFocus
className="input input-bordered w-full border"
type="text"
placeholder="Type Something..."
onInput={async (event: any) => {
@@ -160,40 +168,34 @@ export default function Search(props: {
})}
</div>
{searchResult.length > 0 && (
<div className="flex justify-center my-2">
<div className="join">
<button
className="join-item btn btn-sm"
disabled={pageIndex === 0}
<Pagination>
<PaginationContent>
<PaginationItem>
<PaginationPrevious
onClick={() => {
if (pageIndex === 0) {
return;
}
if (pageIndex === 0) return;
setPageIndex(pageIndex - 1);
}}
>
«
</button>
<button className="join-item btn btn-sm">
Page {pageIndex + 1} /{" "}
{Math.floor(searchResult.length / 10) + 1}
</button>
<button
className="join-item btn btn-sm"
disabled={pageIndex === Math.floor(searchResult.length / 10)}
disabled={pageIndex === 0}
/>
</PaginationItem>
<PaginationItem>
{pageIndex + 1} of {Math.floor(searchResult.length / 10) + 1}
</PaginationItem>
<PaginationItem>
<PaginationNext
onClick={() => {
if (pageIndex === Math.floor(searchResult.length / 10)) {
if (pageIndex === Math.floor(searchResult.length / 10))
return;
}
setPageIndex(pageIndex + 1);
}}
>
»
</button>
</div>
</div>
disabled={pageIndex === Math.floor(searchResult.length / 10)}
/>
</PaginationItem>
</PaginationContent>
</Pagination>
)}
</div>
</div>
</DialogContent>
</Dialog>
);
}