mirror of
https://github.com/rustmailer/bichon.git
synced 2026-08-03 07:48:34 +02:00
feat(ui): Add quick page navigation to the email list pagination #85
This commit is contained in:
@@ -20,6 +20,8 @@
|
||||
import {
|
||||
ChevronLeftIcon,
|
||||
ChevronRightIcon,
|
||||
DoubleArrowLeftIcon,
|
||||
DoubleArrowRightIcon,
|
||||
} from '@radix-ui/react-icons'
|
||||
import { Button } from '@/components/ui/button'
|
||||
import {
|
||||
@@ -30,6 +32,7 @@ import {
|
||||
SelectValue,
|
||||
} from '@/components/ui/select'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { showNumbers } from '@/lib/utils'
|
||||
|
||||
interface PaginationProps {
|
||||
totalItems: number
|
||||
@@ -66,6 +69,9 @@ export function EnvelopeListPagination({
|
||||
setPageIndex(newPageIndex)
|
||||
}
|
||||
|
||||
const currentPage = pageIndex + 1;
|
||||
const pageNumbers = showNumbers(currentPage, pageCount)
|
||||
|
||||
return (
|
||||
<div className='flex items-center justify-between space-x-2 overflow-auto px-2'>
|
||||
<div className='hidden flex-1 text-sm text-muted-foreground sm:block'>
|
||||
@@ -94,6 +100,14 @@ export function EnvelopeListPagination({
|
||||
{t("table.page")} {pageIndex + 1} {t("table.of")} {pageCount}
|
||||
</div>
|
||||
<div className='flex items-center space-x-2'>
|
||||
<Button
|
||||
variant='outline'
|
||||
className='size-8 p-0 @max-md/content:hidden'
|
||||
onClick={() => setPageIndex(0)}
|
||||
disabled={pageIndex === 0}
|
||||
>
|
||||
<DoubleArrowLeftIcon className='h-4 w-4' />
|
||||
</Button>
|
||||
<Button
|
||||
variant='outline'
|
||||
className='h-8 w-8 p-0'
|
||||
@@ -103,6 +117,22 @@ export function EnvelopeListPagination({
|
||||
<span className='sr-only'>{t("table.prevPage")}</span>
|
||||
<ChevronLeftIcon className='h-4 w-4' />
|
||||
</Button>
|
||||
|
||||
{pageNumbers.map((pageNumber, index) => (
|
||||
<div key={`${pageNumber}-${index}`} className='flex items-center'>
|
||||
{pageNumber === '...' ? (
|
||||
<span className='px-1 text-sm text-muted-foreground'>...</span>
|
||||
) : (
|
||||
<Button
|
||||
variant={currentPage === pageNumber ? 'default' : 'outline'}
|
||||
className='h-8 min-w-8 px-2'
|
||||
onClick={() => setPageIndex((pageNumber as number) - 1)}
|
||||
>
|
||||
{pageNumber}
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
))}
|
||||
<Button
|
||||
variant='outline'
|
||||
className='h-8 w-8 p-0'
|
||||
@@ -112,6 +142,14 @@ export function EnvelopeListPagination({
|
||||
<span className='sr-only'>{t("table.nextPage")}</span>
|
||||
<ChevronRightIcon className='h-4 w-4' />
|
||||
</Button>
|
||||
<Button
|
||||
variant='outline'
|
||||
className='size-8 p-0 @max-md/content:hidden'
|
||||
onClick={() => setPageIndex(pageCount - 1)}
|
||||
disabled={!hasNextPage()}
|
||||
>
|
||||
<DoubleArrowRightIcon className='h-4 w-4' />
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -142,7 +142,6 @@ export function MailList({
|
||||
/>
|
||||
<MailIcon className="h-3.5 w-3.5 text-muted-foreground shrink-0" />
|
||||
<div className="flex-1 min-w-0 grid grid-cols-1 sm:grid-cols-12 gap-1 sm:gap-0">
|
||||
{/* LEFT AREA: From + Subject + Tags */}
|
||||
<div className="col-span-1 sm:col-span-8 flex flex-col min-w-0 gap-1">
|
||||
<div className="flex items-center gap-1 min-w-0">
|
||||
<p className="text-sm font-medium truncate">{item.from}</p>
|
||||
@@ -154,7 +153,6 @@ export function MailList({
|
||||
{item.subject}
|
||||
</h3>
|
||||
|
||||
{/* TAGS BELOW SUBJECT */}
|
||||
<div className="flex flex-wrap gap-1 mt-0.25">
|
||||
{item.tags?.map((tag, i) => (
|
||||
<Badge
|
||||
@@ -167,7 +165,6 @@ export function MailList({
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* RIGHT AREA – actions & meta */}
|
||||
<div className="col-span-1 sm:col-span-4 flex items-center justify-end gap-1 text-xs text-muted-foreground">
|
||||
{hasAttachments && (
|
||||
<div className="flex items-center gap-1">
|
||||
|
||||
+33
-1
@@ -171,4 +171,36 @@ export const dateFnsLocaleMap: Record<string, Locale> = {
|
||||
'sv-se': sv,
|
||||
no: nb,
|
||||
'no-no': nb,
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
export function showNumbers(current: number, total: number) {
|
||||
const max = 5
|
||||
const result = []
|
||||
|
||||
if (total <= max) {
|
||||
for (let i = 1; i <= total; i++) {
|
||||
result.push(i)
|
||||
}
|
||||
} else {
|
||||
result.push(1)
|
||||
if (current <= 3) {
|
||||
for (let i = 2; i <= 4; i++) {
|
||||
result.push(i)
|
||||
}
|
||||
result.push('...', total)
|
||||
} else if (current >= total - 2) {
|
||||
result.push('...')
|
||||
for (let i = total - 3; i <= total; i++) {
|
||||
result.push(i)
|
||||
}
|
||||
} else {
|
||||
result.push('...')
|
||||
for (let i = current - 1; i <= current + 1; i++) {
|
||||
result.push(i)
|
||||
}
|
||||
result.push('...', total)
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
Reference in New Issue
Block a user