Refactor Search component to use Dialog for improved user experience; integrate Pagination component for better navigation of search results
This commit is contained in:
@@ -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,
|
||||
}
|
||||
};
|
||||
|
||||
@@ -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}
|
||||
/>
|
||||
)}
|
||||
|
||||
112
src/search.tsx
112
src/search.tsx
@@ -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}
|
||||
onClick={() => {
|
||||
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)}
|
||||
onClick={() => {
|
||||
if (pageIndex === Math.floor(searchResult.length / 10)) {
|
||||
return;
|
||||
}
|
||||
setPageIndex(pageIndex + 1);
|
||||
}}
|
||||
>
|
||||
»
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<Pagination>
|
||||
<PaginationContent>
|
||||
<PaginationItem>
|
||||
<PaginationPrevious
|
||||
onClick={() => {
|
||||
if (pageIndex === 0) return;
|
||||
setPageIndex(pageIndex - 1);
|
||||
}}
|
||||
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))
|
||||
return;
|
||||
setPageIndex(pageIndex + 1);
|
||||
}}
|
||||
disabled={pageIndex === Math.floor(searchResult.length / 10)}
|
||||
/>
|
||||
</PaginationItem>
|
||||
</PaginationContent>
|
||||
</Pagination>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user