fix:pagination shopw author name

This commit is contained in:
hamid zarghami
2025-10-13 14:22:20 +03:30
parent d3d63a922c
commit f49a8641fc
6 changed files with 94 additions and 24 deletions
+24 -16
View File
@@ -13,32 +13,40 @@ const Pagination: React.FC<PaginationProps> = ({
}) => { }) => {
const getPageNumbers = () => { const getPageNumbers = () => {
const pageNumbers: (number | string)[] = []; const pageNumbers: (number | string)[] = [];
const maxVisiblePages = 5; // تعداد حداکثری صفحات قابل مشاهده const maxVisiblePages = 5;
if (totalPages <= maxVisiblePages) { if (totalPages <= maxVisiblePages) {
// اگر تعداد صفحات کم است، همه را نشان بده
for (let i = 1; i <= totalPages; i++) { for (let i = 1; i <= totalPages; i++) {
pageNumbers.push(i); pageNumbers.push(i);
} }
} else { } else {
if (currentPage > 3) { // همیشه صفحه اول را نشان بده
pageNumbers.push(1); pageNumbers.push(1);
if (currentPage > 4) {
pageNumbers.push("...");
}
}
const start = Math.max(2, currentPage - 1); if (currentPage <= 3) {
const end = Math.min(totalPages - 1, currentPage + 1); // در صفحات اولیه (1, 2, 3)
for (let i = 2; i <= Math.min(4, totalPages - 1); i++) {
for (let i = start; i <= end; i++) {
pageNumbers.push(i); pageNumbers.push(i);
} }
if (totalPages > 5) {
if (currentPage < totalPages - 2) {
if (currentPage < totalPages - 3) {
pageNumbers.push("..."); pageNumbers.push("...");
} }
pageNumbers.push(totalPages); pageNumbers.push(totalPages);
} else if (currentPage >= totalPages - 2) {
// در صفحات آخر
pageNumbers.push("...");
for (let i = totalPages - 3; i <= totalPages; i++) {
pageNumbers.push(i);
}
} else {
// در صفحات وسط
pageNumbers.push("...");
for (let i = currentPage - 1; i <= currentPage + 1; i++) {
pageNumbers.push(i);
}
pageNumbers.push("...");
pageNumbers.push(totalPages);
} }
} }
@@ -48,7 +56,7 @@ const Pagination: React.FC<PaginationProps> = ({
const pageNumbers = getPageNumbers(); const pageNumbers = getPageNumbers();
return ( return (
<div className="flex gap-2 text-xs justify-center items-center space-x-2 mt-4"> <div className="flex gap-2 text-xs justify-center items-center mt-4">
{/* دکمه قبلی */} {/* دکمه قبلی */}
{/* <button {/* <button
className={`px-3 py-1 rounded-md ${currentPage === 1 className={`px-3 py-1 rounded-md ${currentPage === 1
@@ -65,7 +73,7 @@ const Pagination: React.FC<PaginationProps> = ({
{pageNumbers.map((page, index) => {pageNumbers.map((page, index) =>
typeof page === "number" ? ( typeof page === "number" ? (
<button <button
key={index} key={`page-${page}`}
className={`size-8 rounded-md ${currentPage === page className={`size-8 rounded-md ${currentPage === page
? "bg-primary text-white" ? "bg-primary text-white"
: "text-primary bg-[#EAECF5] hover:bg-gray-100" : "text-primary bg-[#EAECF5] hover:bg-gray-100"
@@ -75,7 +83,7 @@ const Pagination: React.FC<PaginationProps> = ({
{page} {page}
</button> </button>
) : ( ) : (
<span key={index} className="px-3 py-1 text-gray-500"> <span key={`ellipsis-${index}`} className="px-3 py-1 text-gray-500">
{page} {page}
</span> </span>
) )
+57 -4
View File
@@ -13,6 +13,7 @@ interface QuillEditorProps {
className?: string className?: string
minHeight?: string minHeight?: string
id?: string id?: string
defaultAltText?: string // عنوان مقاله یا متن پیش‌فرض برای alt
} }
const QuillEditor: FC<QuillEditorProps> = ({ const QuillEditor: FC<QuillEditorProps> = ({
@@ -21,7 +22,8 @@ const QuillEditor: FC<QuillEditorProps> = ({
placeholder = '', placeholder = '',
className = '', className = '',
minHeight = '200px', minHeight = '200px',
id = 'quill-editor' id = 'quill-editor',
defaultAltText = 'تصویر'
}) => { }) => {
const editorRef = useRef<HTMLDivElement>(null) const editorRef = useRef<HTMLDivElement>(null)
const quillRef = useRef<Quill | null>(null) const quillRef = useRef<Quill | null>(null)
@@ -29,10 +31,56 @@ const QuillEditor: FC<QuillEditorProps> = ({
useEffect(() => { useEffect(() => {
if (!editorRef.current) return if (!editorRef.current) return
// تابع سفارشی برای مدیریت آپلود تصویر
const imageHandler = () => {
const input = document.createElement('input')
input.setAttribute('type', 'file')
input.setAttribute('accept', 'image/*')
input.click()
input.onchange = async () => {
const file = input.files?.[0]
if (file && quillRef.current) {
// درخواست alt text از کاربر
const altText = prompt('متن جایگزین (Alt Text) تصویر را وارد کنید:', defaultAltText)
if (altText !== null) { // اگر کاربر Cancel نکرد
const reader = new FileReader()
reader.onload = (e) => {
const imageUrl = e.target?.result as string
const range = quillRef.current?.getSelection(true)
if (range && quillRef.current) {
// درج تصویر
quillRef.current.insertEmbed(range.index, 'image', imageUrl)
// اضافه کردن alt text به تصویر
setTimeout(() => {
const images = quillRef.current?.root.querySelectorAll('img')
if (images && images.length > 0) {
const lastImage = images[images.length - 1]
lastImage.setAttribute('alt', altText || defaultAltText)
}
// فراخوانی onChange برای ذخیره تغییرات
if (quillRef.current) {
onChange?.(quillRef.current.root.innerHTML)
}
}, 0)
quillRef.current.setSelection(range.index + 1)
}
}
reader.readAsDataURL(file)
}
}
}
}
// پیکربندی toolbar سفارشی // پیکربندی toolbar سفارشی
const toolbarOptions = [ const toolbarOptions = [
['bold', 'italic', 'underline'], ['bold', 'italic', 'underline'],
[{ 'header': 1 }, { 'header': 2 }], [{ 'header': 1 }, { 'header': 2 }, { 'header': 3 }],
[{ 'list': 'ordered' }, { 'list': 'bullet' }], [{ 'list': 'ordered' }, { 'list': 'bullet' }],
[{ 'direction': 'rtl' }], [{ 'direction': 'rtl' }],
[{ 'color': [] }, { 'background': [] }], [{ 'color': [] }, { 'background': [] }],
@@ -45,7 +93,12 @@ const QuillEditor: FC<QuillEditorProps> = ({
theme: 'snow', theme: 'snow',
placeholder, placeholder,
modules: { modules: {
toolbar: toolbarOptions toolbar: {
container: toolbarOptions,
handlers: {
image: imageHandler
}
}
} }
}) })
@@ -65,7 +118,7 @@ const QuillEditor: FC<QuillEditorProps> = ({
return () => { return () => {
quillRef.current = null quillRef.current = null
} }
}, [placeholder]) }, [placeholder, defaultAltText])
// بروزرسانی محتوا از خارج // بروزرسانی محتوا از خارج
useEffect(() => { useEffect(() => {
+2 -1
View File
@@ -443,7 +443,8 @@
"comments": "نظرات", "comments": "نظرات",
"user": "کاربر", "user": "کاربر",
"comment": "نظر", "comment": "نظر",
"picture": "تصویر" "picture": "تصویر",
"author": "نویسنده"
}, },
"receip": { "receip": {
"receips": "صورتحساب ها", "receips": "صورتحساب ها",
+4
View File
@@ -103,6 +103,7 @@ const BlogList: FC = () => {
<thead className='thead'> <thead className='thead'>
<tr> <tr>
<Td text={t('blog.picture')} /> <Td text={t('blog.picture')} />
<Td text={t('blog.author')} />
<Td text={t('blog.blog_title')} /> <Td text={t('blog.blog_title')} />
<Td text={t('blog.blog_summary')} /> <Td text={t('blog.blog_summary')} />
<Td text={t('blog.category')} /> <Td text={t('blog.category')} />
@@ -119,6 +120,9 @@ const BlogList: FC = () => {
<Td text={''}> <Td text={''}>
<img src={item.imageUrl} alt={item.title} className='w-20 rounded-lg' /> <img src={item.imageUrl} alt={item.title} className='w-20 rounded-lg' />
</Td> </Td>
<Td text={''}>
<p className='max-w-[150px] truncate'>{item.author.firstName} {item.author.lastName}</p>
</Td>
<Td text={''}> <Td text={''}>
<p className='max-w-[150px] truncate'>{item.title}</p> <p className='max-w-[150px] truncate'>{item.title}</p>
</Td> </Td>
+2
View File
@@ -147,6 +147,7 @@ const CreateBlog: FC = () => {
onChange={(content) => formik.setFieldValue('previewContent', content)} onChange={(content) => formik.setFieldValue('previewContent', content)}
placeholder={t('blog.enter_blog_summary')} placeholder={t('blog.enter_blog_summary')}
minHeight="120px" minHeight="120px"
defaultAltText={formik.values.title || 'تصویر'}
/> />
</div> </div>
@@ -164,6 +165,7 @@ const CreateBlog: FC = () => {
onChange={(content) => formik.setFieldValue('content', content)} onChange={(content) => formik.setFieldValue('content', content)}
placeholder={t('blog.enter_blog_content')} placeholder={t('blog.enter_blog_content')}
minHeight="200px" minHeight="200px"
defaultAltText={formik.values.title || 'تصویر'}
/> />
</div> </div>
+2
View File
@@ -155,6 +155,7 @@ const UpdateBlog: FC = () => {
onChange={(content) => formik.setFieldValue('previewContent', content)} onChange={(content) => formik.setFieldValue('previewContent', content)}
placeholder={t('blog.enter_blog_summary')} placeholder={t('blog.enter_blog_summary')}
minHeight="120px" minHeight="120px"
defaultAltText={formik.values.title || 'تصویر'}
/> />
</div> </div>
@@ -172,6 +173,7 @@ const UpdateBlog: FC = () => {
onChange={(content) => formik.setFieldValue('content', content)} onChange={(content) => formik.setFieldValue('content', content)}
placeholder={t('blog.enter_blog_content')} placeholder={t('blog.enter_blog_content')}
minHeight="200px" minHeight="200px"
defaultAltText={formik.values.title || 'تصویر'}
/> />
</div> </div>