pagination icon
deploy to danak / build_and_deploy (push) Has been cancelled

This commit is contained in:
hamid zarghami
2026-06-02 14:48:09 +03:30
parent 6ed440b14f
commit 42c5e68b29
2 changed files with 497 additions and 345 deletions
+433 -342
View File
File diff suppressed because it is too large Load Diff
+64 -3
View File
@@ -1,4 +1,4 @@
import { type FC, useState, useEffect } from 'react'
import { type FC, type UIEvent, useState, useEffect, useMemo, useRef } from 'react'
import DefaulModal from '@/components/DefaulModal'
import type { Icon, IconGroup } from '../types/Types'
import { TickCircle } from 'iconsax-react'
@@ -18,14 +18,64 @@ const IconSelectModal: FC<Props> = ({
onSelect,
selectedUrl
}) => {
const ICONS_PAGE_SIZE = 120
const [selectedIconUrl, setSelectedIconUrl] = useState<string | undefined>(
selectedUrl
)
const [visibleIconsCount, setVisibleIconsCount] = useState(ICONS_PAGE_SIZE)
const scrollContainerRef = useRef<HTMLDivElement>(null)
useEffect(() => {
setSelectedIconUrl(selectedUrl)
}, [selectedUrl, open])
useEffect(() => {
if (open) {
setVisibleIconsCount(ICONS_PAGE_SIZE)
if (scrollContainerRef.current) {
scrollContainerRef.current.scrollTop = 0
}
}
}, [open, icons])
const totalIcons = useMemo(
() => icons.reduce((total, group) => total + group.icons.length, 0),
[icons]
)
const hasMoreIcons = visibleIconsCount < totalIcons
const paginatedGroups = useMemo(() => {
let remainingIcons = visibleIconsCount
return icons
.map((group) => {
const visibleIcons = group.icons.slice(
0,
Math.max(0, Math.min(group.icons.length, remainingIcons))
)
remainingIcons -= visibleIcons.length
return {
...group,
icons: visibleIcons
}
})
.filter((group) => group.icons.length > 0)
}, [icons, visibleIconsCount])
const handleScroll = (event: UIEvent<HTMLDivElement>) => {
if (!hasMoreIcons) return
const target = event.currentTarget
const isNearBottom =
target.scrollTop + target.clientHeight >= target.scrollHeight - 200
if (isNearBottom) {
setVisibleIconsCount((prev) => Math.min(prev + ICONS_PAGE_SIZE, totalIcons))
}
}
const handleSelect = (url: string) => {
setSelectedIconUrl(url)
onSelect(url)
@@ -40,7 +90,11 @@ const IconSelectModal: FC<Props> = ({
title_header="انتخاب آیکون"
width={700}
>
<div className="max-h-[65vh] overflow-y-auto py-2">
<div
ref={scrollContainerRef}
onScroll={handleScroll}
className="max-h-[65vh] overflow-y-auto py-2"
>
{icons.length === 0 ? (
<div className="text-center py-12 text-gray-500">
<div className="text-base mb-2">آیکونی یافت نشد</div>
@@ -50,7 +104,7 @@ const IconSelectModal: FC<Props> = ({
</div>
) : (
<div className="space-y-8">
{icons.map((group) => (
{paginatedGroups.map((group) => (
<div key={group.id} className="border-b border-gray-100 last:border-0 pb-6 last:pb-0">
<div className="flex items-center gap-2 mb-4">
<h3 className="text-base font-semibold text-gray-800">
@@ -78,6 +132,8 @@ const IconSelectModal: FC<Props> = ({
<img
src={icon.url}
alt="icon"
loading="lazy"
decoding="async"
className="w-full h-full object-contain transition-opacity duration-200 max-w-full max-h-full"
style={{
imageRendering: 'auto',
@@ -106,6 +162,11 @@ const IconSelectModal: FC<Props> = ({
)}
</div>
))}
{hasMoreIcons && (
<div className="text-center text-sm text-gray-500 py-2">
در حال بارگذاری آیکون های بیشتر...
</div>
)}
</div>
)}
</div>