style: update better visibility pagination
This commit is contained in:
parent
67f2fccd33
commit
8204b15b4b
|
|
@ -20,7 +20,7 @@ export function BrandFilter() {
|
||||||
<button
|
<button
|
||||||
onClick={() => handleSelect(null)}
|
onClick={() => handleSelect(null)}
|
||||||
className={cn(
|
className={cn(
|
||||||
"rounded-lg border px-4 py-2 text-sm font-medium transition-all",
|
"rounded-lg border px-4 py-2 text-sm font-medium transition-all cursor-pointer",
|
||||||
selectedBrand === null
|
selectedBrand === null
|
||||||
? "border-primary bg-primary text-primary-foreground"
|
? "border-primary bg-primary text-primary-foreground"
|
||||||
: "border-border bg-card text-muted-foreground hover:border-primary/50 hover:text-foreground",
|
: "border-border bg-card text-muted-foreground hover:border-primary/50 hover:text-foreground",
|
||||||
|
|
@ -40,7 +40,7 @@ export function BrandFilter() {
|
||||||
key={brand.name}
|
key={brand.name}
|
||||||
onClick={() => handleSelect(brand.name)}
|
onClick={() => handleSelect(brand.name)}
|
||||||
className={cn(
|
className={cn(
|
||||||
"rounded-lg border px-4 py-2 text-sm font-medium transition-all",
|
"rounded-lg border px-4 py-2 text-sm font-medium transition-all cursor-pointer",
|
||||||
isActive
|
isActive
|
||||||
? "border-primary bg-primary text-primary-foreground"
|
? "border-primary bg-primary text-primary-foreground"
|
||||||
: "border-border bg-card text-muted-foreground hover:border-primary/50 hover:text-foreground",
|
: "border-border bg-card text-muted-foreground hover:border-primary/50 hover:text-foreground",
|
||||||
|
|
|
||||||
|
|
@ -9,24 +9,20 @@ import {
|
||||||
TableRow,
|
TableRow,
|
||||||
} from "../../components/ui/table";
|
} from "../../components/ui/table";
|
||||||
import { Badge } from "../../components/ui/badge";
|
import { Badge } from "../../components/ui/badge";
|
||||||
import { EllipsisVertical, Inbox, Loader2, Pencil, Trash } from "lucide-react";
|
import { Inbox, Loader2 } from "lucide-react";
|
||||||
import getSentimentBadge from "./SentimentBadge";
|
import getSentimentBadge from "./SentimentBadge";
|
||||||
import {
|
|
||||||
DropdownMenu,
|
|
||||||
DropdownMenuContent,
|
|
||||||
DropdownMenuItem,
|
|
||||||
DropdownMenuTrigger,
|
|
||||||
} from "../ui/dropdown-menu";
|
|
||||||
import { useReviewTable } from "@/src/hooks/useReviewTable";
|
import { useReviewTable } from "@/src/hooks/useReviewTable";
|
||||||
import {
|
import {
|
||||||
Pagination,
|
Pagination,
|
||||||
PaginationContent,
|
PaginationContent,
|
||||||
|
PaginationEllipsis,
|
||||||
PaginationItem,
|
PaginationItem,
|
||||||
PaginationLink,
|
PaginationLink,
|
||||||
PaginationNext,
|
PaginationNext,
|
||||||
PaginationPrevious,
|
PaginationPrevious,
|
||||||
} from "../ui/pagination";
|
} from "../ui/pagination";
|
||||||
import { useSearchParams } from "next/navigation";
|
import { useSearchParams } from "next/navigation";
|
||||||
|
import { getVisiblePages } from "@/src/utils/datas";
|
||||||
|
|
||||||
export function ReviewTable() {
|
export function ReviewTable() {
|
||||||
const searchParams = useSearchParams();
|
const searchParams = useSearchParams();
|
||||||
|
|
@ -36,6 +32,7 @@ export function ReviewTable() {
|
||||||
selectedBrand,
|
selectedBrand,
|
||||||
);
|
);
|
||||||
const { currentPage, totalPages, nextPage, prevPage, goToPage } = pagination;
|
const { currentPage, totalPages, nextPage, prevPage, goToPage } = pagination;
|
||||||
|
const visiblePage = getVisiblePages({ totalPages, currentPage });
|
||||||
|
|
||||||
if (isLoading) {
|
if (isLoading) {
|
||||||
return (
|
return (
|
||||||
|
|
@ -171,7 +168,7 @@ export function ReviewTable() {
|
||||||
</TableBody>
|
</TableBody>
|
||||||
</Table>
|
</Table>
|
||||||
|
|
||||||
{totalPages > 1 && (
|
{/* {totalPages > 1 && (
|
||||||
<div className="border-t bg-muted/20 px-6 py-4">
|
<div className="border-t bg-muted/20 px-6 py-4">
|
||||||
<Pagination className="justify-center sm:justify-end">
|
<Pagination className="justify-center sm:justify-end">
|
||||||
<PaginationContent>
|
<PaginationContent>
|
||||||
|
|
@ -222,6 +219,63 @@ export function ReviewTable() {
|
||||||
</PaginationContent>
|
</PaginationContent>
|
||||||
</Pagination>
|
</Pagination>
|
||||||
</div>
|
</div>
|
||||||
|
)} */}
|
||||||
|
|
||||||
|
{totalPages > 1 && (
|
||||||
|
<div className="border-t bg-muted/20 px-6 py-4">
|
||||||
|
<Pagination className="justify-center sm:justify-end">
|
||||||
|
<PaginationContent>
|
||||||
|
<PaginationItem>
|
||||||
|
<PaginationPrevious
|
||||||
|
href="#"
|
||||||
|
onClick={(e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
prevPage();
|
||||||
|
}}
|
||||||
|
className={
|
||||||
|
currentPage === 1
|
||||||
|
? "pointer-events-none opacity-50"
|
||||||
|
: "cursor-pointer hover:bg-[#F8FBFF] hover:text-primary"
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</PaginationItem>
|
||||||
|
|
||||||
|
{visiblePage.map((page, index) => (
|
||||||
|
<PaginationItem key={index}>
|
||||||
|
{page === "..." ? (
|
||||||
|
<PaginationEllipsis />
|
||||||
|
) : (
|
||||||
|
<PaginationLink
|
||||||
|
href="#"
|
||||||
|
onClick={(e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
goToPage(page as number);
|
||||||
|
}}
|
||||||
|
isActive={currentPage === page}
|
||||||
|
>
|
||||||
|
{page}
|
||||||
|
</PaginationLink>
|
||||||
|
)}
|
||||||
|
</PaginationItem>
|
||||||
|
))}
|
||||||
|
|
||||||
|
<PaginationItem>
|
||||||
|
<PaginationNext
|
||||||
|
href="#"
|
||||||
|
onClick={(e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
nextPage();
|
||||||
|
}}
|
||||||
|
className={
|
||||||
|
currentPage === totalPages
|
||||||
|
? "pointer-events-none opacity-50"
|
||||||
|
: "cursor-pointer hover:bg-primary hover:text-card"
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</PaginationItem>
|
||||||
|
</PaginationContent>
|
||||||
|
</Pagination>
|
||||||
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,7 @@ const buttonVariants = cva(
|
||||||
ghost:
|
ghost:
|
||||||
"hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50",
|
"hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50",
|
||||||
link: "text-primary underline-offset-4 hover:underline",
|
link: "text-primary underline-offset-4 hover:underline",
|
||||||
|
primary: "bg-primary text-card"
|
||||||
},
|
},
|
||||||
size: {
|
size: {
|
||||||
default: "h-9 px-4 py-2 has-[>svg]:px-3",
|
default: "h-9 px-4 py-2 has-[>svg]:px-3",
|
||||||
|
|
|
||||||
|
|
@ -55,7 +55,7 @@ function PaginationLink({
|
||||||
data-active={isActive}
|
data-active={isActive}
|
||||||
className={cn(
|
className={cn(
|
||||||
buttonVariants({
|
buttonVariants({
|
||||||
variant: isActive ? "outline" : "ghost",
|
variant: isActive ? "primary" : "ghost",
|
||||||
size,
|
size,
|
||||||
}),
|
}),
|
||||||
className,
|
className,
|
||||||
|
|
|
||||||
|
|
@ -285,3 +285,8 @@ export type AnalysisData = {
|
||||||
};
|
};
|
||||||
|
|
||||||
export type BodyData = (req: Request, body: any) => Promise<NextResponse>;
|
export type BodyData = (req: Request, body: any) => Promise<NextResponse>;
|
||||||
|
|
||||||
|
export interface VisiblePageProps {
|
||||||
|
totalPages: number;
|
||||||
|
currentPage: number;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,10 @@
|
||||||
import { ScrapeResult, WordCloudConfig, WordItem } from "../types";
|
import { useReviewTable } from "../hooks/useReviewTable";
|
||||||
|
import {
|
||||||
|
ScrapeResult,
|
||||||
|
VisiblePageProps,
|
||||||
|
WordCloudConfig,
|
||||||
|
WordItem,
|
||||||
|
} from "../types";
|
||||||
import { Brand } from "@prisma/client";
|
import { Brand } from "@prisma/client";
|
||||||
|
|
||||||
export const setWordCloud = ({ maxValue, minValue }: WordCloudConfig) => {
|
export const setWordCloud = ({ maxValue, minValue }: WordCloudConfig) => {
|
||||||
|
|
@ -24,7 +30,7 @@ export const setWordCloud = ({ maxValue, minValue }: WordCloudConfig) => {
|
||||||
return { getSize, getColor };
|
return { getSize, getColor };
|
||||||
};
|
};
|
||||||
|
|
||||||
export function getFallbackData(url: string): ScrapeResult {
|
export const getFallbackData = (url: string): ScrapeResult => {
|
||||||
return {
|
return {
|
||||||
name: "Produk (Data Sampel)",
|
name: "Produk (Data Sampel)",
|
||||||
url: url,
|
url: url,
|
||||||
|
|
@ -39,7 +45,7 @@ export function getFallbackData(url: string): ScrapeResult {
|
||||||
"Pengiriman cepat dan packing kayu sangat aman.",
|
"Pengiriman cepat dan packing kayu sangat aman.",
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
}
|
};
|
||||||
|
|
||||||
export const formatRupiah = (value: number | string) => {
|
export const formatRupiah = (value: number | string) => {
|
||||||
if (!value) return "Rp 0";
|
if (!value) return "Rp 0";
|
||||||
|
|
@ -63,10 +69,42 @@ export const brandFormat = ({
|
||||||
return { brands };
|
return { brands };
|
||||||
};
|
};
|
||||||
|
|
||||||
export function toTitleCase(str: string) {
|
export const toTitleCase = (str: string) => {
|
||||||
return str
|
return str
|
||||||
.toLowerCase()
|
.toLowerCase()
|
||||||
.split(/[\s-_]+/)
|
.split(/[\s-_]+/)
|
||||||
.map((word) => word.charAt(0).toUpperCase() + word.slice(1))
|
.map((word) => word.charAt(0).toUpperCase() + word.slice(1))
|
||||||
.join(" ");
|
.join(" ");
|
||||||
}
|
};
|
||||||
|
|
||||||
|
export const getVisiblePages = (data: VisiblePageProps) => {
|
||||||
|
if (data.totalPages <= 6) {
|
||||||
|
return Array.from({ length: data.totalPages }, (_, i) => i + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data.currentPage <= 3) {
|
||||||
|
return [1, 2, 3, 4, 5, "...", data.totalPages];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data.currentPage >= data.totalPages - 2) {
|
||||||
|
return [
|
||||||
|
1,
|
||||||
|
"...",
|
||||||
|
data.totalPages - 4,
|
||||||
|
data.totalPages - 3,
|
||||||
|
data.totalPages - 2,
|
||||||
|
data.totalPages - 1,
|
||||||
|
data.totalPages,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
return [
|
||||||
|
1,
|
||||||
|
"...",
|
||||||
|
data.currentPage - 1,
|
||||||
|
data.currentPage,
|
||||||
|
data.currentPage + 1,
|
||||||
|
"...",
|
||||||
|
data.totalPages,
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue