Improve product cards/pagination, Farsi locale fonts, and super-admin migrate UI.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Alireza Hassani
2026-07-29 16:10:43 +03:30
co-authored by Cursor
parent 2e40d5eb4c
commit f5b2193ba1
108 changed files with 2421 additions and 812 deletions
@@ -1,11 +1,31 @@
import { ChevronLeft, ChevronRight } from 'lucide-react'
import { ChevronLeft, ChevronRight, ChevronsLeft, ChevronsRight } from 'lucide-react'
import styles from './Pagination.module.css'
interface PaginationProps {
export interface PaginationProps {
currentPage: number
totalPages: number
onPageChange: (page: number) => void
ariaLabel?: string
/** Pages on each side of current. Default 3 → e.g. 1 2 3 [4] 5 6 7 */
siblingCount?: number
disabled?: boolean
/** `inline` for table footers (no top margin). */
variant?: 'default' | 'inline'
className?: string
}
function buildPageWindow(
currentPage: number,
totalPages: number,
siblingCount: number,
): number[] {
const start = Math.max(1, currentPage - siblingCount)
const end = Math.min(totalPages, currentPage + siblingCount)
const pages: number[] = []
for (let page = start; page <= end; page += 1) {
pages.push(page)
}
return pages
}
export function Pagination({
@@ -13,18 +33,39 @@ export function Pagination({
totalPages,
onPageChange,
ariaLabel = 'Pagination',
siblingCount = 3,
disabled = false,
variant = 'default',
className,
}: PaginationProps) {
if (totalPages <= 1) return null
const pages = Array.from({ length: totalPages }, (_, i) => i + 1)
const pages = buildPageWindow(currentPage, totalPages, siblingCount)
const rootClass = [
styles.pagination,
variant === 'inline' ? styles.paginationInline : '',
className ?? '',
]
.filter(Boolean)
.join(' ')
return (
<nav className={styles.pagination} aria-label={ariaLabel}>
<nav className={rootClass} aria-label={ariaLabel}>
<button
type="button"
className={styles.navBtn}
onClick={() => onPageChange(1)}
disabled={disabled || currentPage === 1}
aria-label="First page"
>
<ChevronsLeft size={18} />
</button>
<button
type="button"
className={styles.navBtn}
onClick={() => onPageChange(currentPage - 1)}
disabled={currentPage === 1}
disabled={disabled || currentPage === 1}
aria-label="Previous page"
>
<ChevronLeft size={18} />
@@ -37,6 +78,7 @@ export function Pagination({
type="button"
className={`${styles.pageBtn} ${page === currentPage ? styles.active : ''}`}
onClick={() => onPageChange(page)}
disabled={disabled}
aria-label={`Page ${page}`}
aria-current={page === currentPage ? 'page' : undefined}
>
@@ -49,11 +91,21 @@ export function Pagination({
type="button"
className={styles.navBtn}
onClick={() => onPageChange(currentPage + 1)}
disabled={currentPage === totalPages}
disabled={disabled || currentPage === totalPages}
aria-label="Next page"
>
<ChevronRight size={18} />
</button>
<button
type="button"
className={styles.navBtn}
onClick={() => onPageChange(totalPages)}
disabled={disabled || currentPage === totalPages}
aria-label="Last page"
>
<ChevronsRight size={18} />
</button>
</nav>
)
}