1+ <script setup lang="ts">
2+ import { Link } from ' @inertiajs/vue3' ;
3+ import { Button } from ' @/components/ui/button' ;
4+ import { ChevronLeft , ChevronRight , ChevronsLeft , ChevronsRight } from ' lucide-vue-next' ;
5+ import { PaginationData , PaginationLink } from ' @/types' ;
6+
7+ interface Props {
8+ pagination: PaginationData ;
9+ showInfo? : boolean ;
10+ }
11+
12+ const props = withDefaults (defineProps <Props >(), {
13+ showInfo: true ,
14+ });
15+
16+ const getPageNumber = (label : string ): number | null => {
17+ const num = parseInt (label );
18+ return isNaN (num ) ? null : num ;
19+ }
20+
21+ // Remove query parameters from URL
22+ const removeQueryParams = (url : string | null ): string | null => {
23+ if (! url ) return null ;
24+ return url .split (' ?' )[0 ];
25+ }
26+
27+ // Get first page URL (without query params)
28+ const getFirstPageUrl = (): string | null => {
29+ const firstPageLink = props .pagination .links .find (link => getPageNumber (link .label ) === 1 );
30+ return firstPageLink ?.url ? removeQueryParams (firstPageLink .url ) : null ;
31+ }
32+
33+ // Get last page URL
34+ const getLastPageUrl = (): string | null => {
35+ const lastPageLink = props .pagination .links .find (link => getPageNumber (link .label ) === props .pagination .last_page );
36+ return lastPageLink ?.url || null ;
37+ }
38+
39+ // Get previous page URL (first link in array)
40+ const getPreviousPageUrl = (): string | null => {
41+ return props .pagination .links [0 ]?.url || null ;
42+ }
43+
44+ // Get next page URL (last link in array)
45+ const getNextPageUrl = (): string | null => {
46+ return props .pagination .links [props .pagination .links .length - 1 ]?.url || null ;
47+ }
48+
49+ // Get page URL, remove query params if it's page 1
50+ const getPageUrl = (link : PaginationLink ): string | null => {
51+ if (! link .url ) return null ;
52+ const pageNum = getPageNumber (link .label );
53+ return pageNum === 1 ? removeQueryParams (link .url ) : link .url ;
54+ }
55+ </script >
56+
57+ <template >
58+ <div class =" flex items-center justify-between px-2 py-4" >
59+ <!-- Pagination Info -->
60+ <div v-if =" showInfo" class =" text-sm text-muted-foreground" >
61+ Showing <span class =" font-medium" >{{ pagination.from }}</span > to
62+ <span class =" font-medium" >{{ pagination.to }}</span > of
63+ <span class =" font-medium" >{{ pagination.total }}</span > results
64+ </div >
65+ <div v-else ></div >
66+
67+ <!-- Pagination Controls -->
68+ <div class =" flex items-center gap-2" >
69+ <!-- First Page -->
70+ <Button :as =" Link" :href =" getFirstPageUrl() || '#'" :disabled =" pagination.current_page === 1"
71+ variant =" outline" size =" icon" class =" h-8 w-8"
72+ :class =" { 'pointer-events-none opacity-50': pagination.current_page === 1 }" >
73+ <ChevronsLeft :size =" 16" />
74+ </Button >
75+
76+ <!-- Previous Page -->
77+ <Button :as =" Link" :href =" getPreviousPageUrl() || '#'" :disabled =" pagination.current_page === 1"
78+ variant =" outline" size =" icon" class =" h-8 w-8"
79+ :class =" { 'pointer-events-none opacity-50': pagination.current_page === 1 }" >
80+ <ChevronLeft :size =" 16" />
81+ </Button >
82+
83+ <!-- Page Numbers -->
84+ <template v-for =" (link , index ) in pagination .links " :key =" index " >
85+ <Button v-if =" getPageNumber(link.label) !== null" :as =" Link" :href =" getPageUrl(link) || '#'"
86+ :variant =" link.active ? 'default' : 'outline'" size =" icon" class =" h-8 w-8"
87+ :class =" { 'pointer-events-none': !link.url }" >
88+ {{ link.label }}
89+ </Button >
90+ </template >
91+
92+ <!-- Next Page -->
93+ <Button :as =" Link" :href =" getNextPageUrl() || '#'"
94+ :disabled =" pagination.current_page === pagination.last_page" variant =" outline" size =" icon"
95+ class =" h-8 w-8"
96+ :class =" { 'pointer-events-none opacity-50': pagination.current_page === pagination.last_page }" >
97+ <ChevronRight :size =" 16" />
98+ </Button >
99+
100+ <!-- Last Page -->
101+ <Button :as =" Link" :href =" getLastPageUrl() || '#'"
102+ :disabled =" pagination.current_page === pagination.last_page" variant =" outline" size =" icon"
103+ class =" h-8 w-8"
104+ :class =" { 'pointer-events-none opacity-50': pagination.current_page === pagination.last_page }" >
105+ <ChevronsRight :size =" 16" />
106+ </Button >
107+ </div >
108+ </div >
109+ </template >
0 commit comments