pagination
This commit is contained in:
@@ -6,8 +6,8 @@ VITE_DANAK_BASE_URL ='https://api.danakcorp.com'
|
|||||||
VITE_SOCKET_URL = 'wss://dmail-api.danakcorp.com/email'
|
VITE_SOCKET_URL = 'wss://dmail-api.danakcorp.com/email'
|
||||||
# VITE_SOCKET_URL = 'ws://192.168.1.118:4000/email'
|
# VITE_SOCKET_URL = 'ws://192.168.1.118:4000/email'
|
||||||
|
|
||||||
VITE_BASE_URL = 'https://dmail-api.danakcorp.com'
|
# VITE_BASE_URL = 'https://dmail-api.danakcorp.com'
|
||||||
# VITE_BASE_URL = 'http://192.168.1.101:4000'
|
VITE_BASE_URL = 'http://192.168.1.101:4000'
|
||||||
|
|
||||||
|
|
||||||
VITE_SERVICE_ID = 'e51afdc3-ea0b-49cf-8f49-2a6f131b024e'
|
VITE_SERVICE_ID = 'e51afdc3-ea0b-49cf-8f49-2a6f131b024e'
|
||||||
|
|||||||
@@ -51,6 +51,7 @@
|
|||||||
"tailwindcss": "^4.1.4",
|
"tailwindcss": "^4.1.4",
|
||||||
"three": "^0.177.0",
|
"three": "^0.177.0",
|
||||||
"uuid": "^11.1.0",
|
"uuid": "^11.1.0",
|
||||||
|
"vite-plugin-pwa": "^1.0.2",
|
||||||
"vite-tsconfig-paths": "^5.1.4",
|
"vite-tsconfig-paths": "^5.1.4",
|
||||||
"yup": "^1.6.1",
|
"yup": "^1.6.1",
|
||||||
"zustand": "^5.0.3"
|
"zustand": "^5.0.3"
|
||||||
|
|||||||
Generated
+1940
-11
File diff suppressed because it is too large
Load Diff
@@ -1,107 +1,41 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
|
import Button from "./Button";
|
||||||
|
|
||||||
interface PaginationProps {
|
interface PaginationProps {
|
||||||
currentPage: number;
|
hasNext: boolean;
|
||||||
totalPages: number;
|
nextCursor?: string;
|
||||||
onPageChange: (page: number) => void;
|
previousCursor?: string;
|
||||||
|
onNext: (cursor?: string) => void;
|
||||||
|
onPrevious: (cursor?: string) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
const Pagination: React.FC<PaginationProps> = ({
|
const Pagination: React.FC<PaginationProps> = ({
|
||||||
currentPage,
|
hasNext,
|
||||||
totalPages,
|
nextCursor,
|
||||||
onPageChange,
|
previousCursor,
|
||||||
|
onNext,
|
||||||
|
onPrevious,
|
||||||
}) => {
|
}) => {
|
||||||
// اگر فقط یک صفحه داریم، pagination نمایش داده نمیشود
|
// اگر hasNext فالس باشد، pagination نمایش داده نمیشود
|
||||||
if (totalPages <= 1) return null;
|
if (!hasNext && !previousCursor) return null;
|
||||||
|
|
||||||
const getPageNumbers = () => {
|
|
||||||
const pageNumbers: (number | string)[] = [];
|
|
||||||
const maxVisiblePages = window.innerWidth < 768 ? 3 : 5; // تعداد کمتر برای موبایل
|
|
||||||
|
|
||||||
if (totalPages <= maxVisiblePages) {
|
|
||||||
for (let i = 1; i <= totalPages; i++) {
|
|
||||||
pageNumbers.push(i);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// نمایش صفحه اول
|
|
||||||
pageNumbers.push(1);
|
|
||||||
|
|
||||||
if (currentPage > 3) {
|
|
||||||
pageNumbers.push("...");
|
|
||||||
}
|
|
||||||
|
|
||||||
// صفحات میانی
|
|
||||||
const start = Math.max(2, Math.min(currentPage - 1, totalPages - 3));
|
|
||||||
const end = Math.min(totalPages - 1, Math.max(currentPage + 1, 4));
|
|
||||||
|
|
||||||
for (let i = start; i <= end; i++) {
|
|
||||||
if (!pageNumbers.includes(i)) {
|
|
||||||
pageNumbers.push(i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (currentPage < totalPages - 2) {
|
|
||||||
pageNumbers.push("...");
|
|
||||||
}
|
|
||||||
|
|
||||||
// نمایش صفحه آخر
|
|
||||||
if (!pageNumbers.includes(totalPages)) {
|
|
||||||
pageNumbers.push(totalPages);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return pageNumbers;
|
|
||||||
};
|
|
||||||
|
|
||||||
const pageNumbers = getPageNumbers();
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex justify-center items-center gap-1 md:gap-2 py-4 md:py-6 mt-3 md:mt-4 border-t border-gray-100">
|
<div className="flex items-center justify-center gap-4 mt-6">
|
||||||
{/* دکمه صفحه قبل */}
|
<Button
|
||||||
<button
|
label="قبلی"
|
||||||
className={`px-2 md:px-3 py-2 text-xs md:text-sm rounded-lg transition-colors ${currentPage === 1
|
onClick={() => onPrevious(previousCursor)}
|
||||||
? "text-gray-400 cursor-not-allowed"
|
disabled={!previousCursor}
|
||||||
: "text-gray-600 hover:bg-gray-100 hover:text-gray-800"
|
className="w-fit"
|
||||||
}`}
|
/>
|
||||||
onClick={() => currentPage > 1 && onPageChange(currentPage - 1)}
|
|
||||||
disabled={currentPage === 1}
|
<Button
|
||||||
>
|
label="بعدی"
|
||||||
قبلی
|
onClick={() => onNext(nextCursor)}
|
||||||
</button>
|
disabled={!hasNext}
|
||||||
|
className="w-fit"
|
||||||
|
/>
|
||||||
|
|
||||||
{/* شماره صفحات */}
|
|
||||||
<div className="flex gap-1">
|
|
||||||
{pageNumbers.map((page, index) =>
|
|
||||||
typeof page === "number" ? (
|
|
||||||
<button
|
|
||||||
key={index}
|
|
||||||
className={`w-8 h-8 md:w-10 md:h-10 text-xs md:text-sm rounded-lg transition-colors ${currentPage === page
|
|
||||||
? "bg-primary text-white shadow-sm"
|
|
||||||
: "text-gray-600 hover:bg-gray-100 hover:text-gray-800"
|
|
||||||
}`}
|
|
||||||
onClick={() => onPageChange(page)}
|
|
||||||
>
|
|
||||||
{page}
|
|
||||||
</button>
|
|
||||||
) : (
|
|
||||||
<span key={index} className="flex items-center px-1 md:px-2 text-gray-400 text-xs md:text-sm">
|
|
||||||
{page}
|
|
||||||
</span>
|
|
||||||
)
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* دکمه صفحه بعد */}
|
|
||||||
<button
|
|
||||||
className={`px-2 md:px-3 py-2 text-xs md:text-sm rounded-lg transition-colors ${currentPage === totalPages
|
|
||||||
? "text-gray-400 cursor-not-allowed"
|
|
||||||
: "text-gray-600 hover:bg-gray-100 hover:text-gray-800"
|
|
||||||
}`}
|
|
||||||
onClick={() => currentPage < totalPages && onPageChange(currentPage + 1)}
|
|
||||||
disabled={currentPage === totalPages}
|
|
||||||
>
|
|
||||||
بعدی
|
|
||||||
</button>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
+17
-10
@@ -372,9 +372,11 @@ const Table = <T extends RowDataType>({
|
|||||||
|
|
||||||
{pagination && (
|
{pagination && (
|
||||||
<Pagination
|
<Pagination
|
||||||
currentPage={pagination.currentPage}
|
hasNext={!!pagination.nextCursor}
|
||||||
totalPages={pagination.totalPages}
|
nextCursor={pagination.nextCursor}
|
||||||
onPageChange={pagination.onPageChange}
|
previousCursor={pagination.previousCursor}
|
||||||
|
onNext={pagination.onNext}
|
||||||
|
onPrevious={pagination.onPrevious}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
@@ -403,13 +405,18 @@ const Table = <T extends RowDataType>({
|
|||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{pagination && (
|
{pagination && (() => {
|
||||||
<Pagination
|
console.log('Table component rendering pagination:', pagination);
|
||||||
currentPage={pagination.currentPage}
|
return (
|
||||||
totalPages={pagination.totalPages}
|
<Pagination
|
||||||
onPageChange={pagination.onPageChange}
|
hasNext={pagination.hasNext}
|
||||||
/>
|
nextCursor={pagination.nextCursor}
|
||||||
)}
|
previousCursor={pagination.previousCursor}
|
||||||
|
onNext={pagination.onNext}
|
||||||
|
onPrevious={pagination.onPrevious}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
})()}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -14,9 +14,11 @@ export interface ColumnType<T extends RowDataType = RowDataType> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface PaginationConfig {
|
export interface PaginationConfig {
|
||||||
currentPage: number;
|
hasNext: boolean;
|
||||||
totalPages: number;
|
nextCursor?: string;
|
||||||
onPageChange: (page: number) => void;
|
previousCursor?: string;
|
||||||
|
onNext: (cursor?: string) => void;
|
||||||
|
onPrevious: (cursor?: string) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface InlineActionItem {
|
export interface InlineActionItem {
|
||||||
|
|||||||
@@ -12,12 +12,14 @@ import { useEmailActions } from '@/hooks/useEmailActions';
|
|||||||
|
|
||||||
const List: FC = () => {
|
const List: FC = () => {
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const [currentPage, setCurrentPage] = useState(1);
|
const [nextCursor, setNextCursor] = useState<string | undefined>(undefined);
|
||||||
|
const [previousCursor, setPreviousCursor] = useState<string | undefined>(undefined);
|
||||||
const [filters, setFilters] = useState<FilterValues>({});
|
const [filters, setFilters] = useState<FilterValues>({});
|
||||||
const emailActions = useEmailActions();
|
const emailActions = useEmailActions();
|
||||||
|
|
||||||
const { data: trashData, isLoading, refetch, isFetching } = useGetTrashMessages({
|
const { data: trashData, isLoading, refetch, isFetching } = useGetTrashMessages({
|
||||||
page: currentPage,
|
next: nextCursor,
|
||||||
|
previous: previousCursor,
|
||||||
limit: 10,
|
limit: 10,
|
||||||
...filters
|
...filters
|
||||||
});
|
});
|
||||||
@@ -73,7 +75,8 @@ const List: FC = () => {
|
|||||||
|
|
||||||
const handleFilterChange = (newFilters: FilterValues) => {
|
const handleFilterChange = (newFilters: FilterValues) => {
|
||||||
setFilters(newFilters);
|
setFilters(newFilters);
|
||||||
setCurrentPage(1);
|
setNextCursor(undefined);
|
||||||
|
setPreviousCursor(undefined);
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleSelectionChange = (selectedRows: TrashMessage[]) => {
|
const handleSelectionChange = (selectedRows: TrashMessage[]) => {
|
||||||
@@ -107,8 +110,16 @@ const List: FC = () => {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
const handlePageChange = (page: number) => {
|
|
||||||
setCurrentPage(page);
|
|
||||||
|
const handleNext = (cursor?: string) => {
|
||||||
|
setNextCursor(cursor);
|
||||||
|
setPreviousCursor(undefined);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handlePrevious = (cursor?: string) => {
|
||||||
|
setPreviousCursor(cursor);
|
||||||
|
setNextCursor(undefined);
|
||||||
};
|
};
|
||||||
|
|
||||||
const messages = trashData?.data?.trashMails || [];
|
const messages = trashData?.data?.trashMails || [];
|
||||||
@@ -147,9 +158,11 @@ const List: FC = () => {
|
|||||||
selectable={true}
|
selectable={true}
|
||||||
rowActions={getRowActions}
|
rowActions={getRowActions}
|
||||||
pagination={pager ? {
|
pagination={pager ? {
|
||||||
totalPages: pager.totalPages,
|
hasNext: typeof pager.nextCursor === 'string',
|
||||||
currentPage: pager.page,
|
nextCursor: typeof pager.nextCursor === 'string' ? pager.nextCursor : undefined,
|
||||||
onPageChange: handlePageChange
|
previousCursor: typeof pager.previousCursor === 'string' ? pager.previousCursor : undefined,
|
||||||
|
onNext: handleNext,
|
||||||
|
onPrevious: handlePrevious
|
||||||
} : undefined}
|
} : undefined}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -35,7 +35,8 @@ export interface TrashMessage extends Record<string, unknown> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface MessageListQueryDto {
|
export interface MessageListQueryDto {
|
||||||
page?: number;
|
next?: string;
|
||||||
|
previous?: string;
|
||||||
limit?: number;
|
limit?: number;
|
||||||
search?: string;
|
search?: string;
|
||||||
from?: string;
|
from?: string;
|
||||||
@@ -43,6 +44,7 @@ export interface MessageListQueryDto {
|
|||||||
datestart?: string;
|
datestart?: string;
|
||||||
dateend?: string;
|
dateend?: string;
|
||||||
attachments?: boolean;
|
attachments?: boolean;
|
||||||
|
unseen?: boolean;
|
||||||
flagged?: boolean;
|
flagged?: boolean;
|
||||||
order?: "asc" | "desc";
|
order?: "asc" | "desc";
|
||||||
}
|
}
|
||||||
@@ -57,8 +59,17 @@ export interface TrashResponse {
|
|||||||
totalPages: number;
|
totalPages: number;
|
||||||
totalItems: number;
|
totalItems: number;
|
||||||
limit: number;
|
limit: number;
|
||||||
prevPage: boolean;
|
previousCursor: string | boolean;
|
||||||
nextPage: boolean;
|
nextCursor: string | boolean;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface Pager {
|
||||||
|
page: number;
|
||||||
|
limit: number;
|
||||||
|
totalItems: number;
|
||||||
|
totalPages: number;
|
||||||
|
previousCursor: string | boolean;
|
||||||
|
nextCursor: string | boolean;
|
||||||
|
}
|
||||||
|
|||||||
@@ -12,12 +12,14 @@ import { useEmailActions } from '@/hooks/useEmailActions';
|
|||||||
|
|
||||||
const List: FC = () => {
|
const List: FC = () => {
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const [currentPage, setCurrentPage] = useState(1);
|
const [nextCursor, setNextCursor] = useState<string | undefined>(undefined);
|
||||||
|
const [previousCursor, setPreviousCursor] = useState<string | undefined>(undefined);
|
||||||
const [filters, setFilters] = useState<FilterValues>({});
|
const [filters, setFilters] = useState<FilterValues>({});
|
||||||
const emailActions = useEmailActions();
|
const emailActions = useEmailActions();
|
||||||
|
|
||||||
const { data: archiveData, isLoading, refetch, isFetching } = useGetArchiveMessages({
|
const { data: archiveData, isLoading, refetch, isFetching } = useGetArchiveMessages({
|
||||||
page: currentPage,
|
next: nextCursor,
|
||||||
|
previous: previousCursor,
|
||||||
limit: 10,
|
limit: 10,
|
||||||
...filters
|
...filters
|
||||||
});
|
});
|
||||||
@@ -73,7 +75,8 @@ const List: FC = () => {
|
|||||||
|
|
||||||
const handleFilterChange = (newFilters: FilterValues) => {
|
const handleFilterChange = (newFilters: FilterValues) => {
|
||||||
setFilters(newFilters);
|
setFilters(newFilters);
|
||||||
setCurrentPage(1);
|
setNextCursor(undefined);
|
||||||
|
setPreviousCursor(undefined);
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleSelectionChange = (selectedRows: ArchiveMessage[]) => {
|
const handleSelectionChange = (selectedRows: ArchiveMessage[]) => {
|
||||||
@@ -105,8 +108,16 @@ const List: FC = () => {
|
|||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
const handlePageChange = (page: number) => {
|
|
||||||
setCurrentPage(page);
|
|
||||||
|
const handleNext = (cursor?: string) => {
|
||||||
|
setNextCursor(cursor);
|
||||||
|
setPreviousCursor(undefined);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handlePrevious = (cursor?: string) => {
|
||||||
|
setPreviousCursor(cursor);
|
||||||
|
setNextCursor(undefined);
|
||||||
};
|
};
|
||||||
|
|
||||||
const messages = archiveData?.data?.archiveMails || [];
|
const messages = archiveData?.data?.archiveMails || [];
|
||||||
@@ -145,9 +156,11 @@ const List: FC = () => {
|
|||||||
selectable={true}
|
selectable={true}
|
||||||
rowActions={getRowActions}
|
rowActions={getRowActions}
|
||||||
pagination={pager ? {
|
pagination={pager ? {
|
||||||
totalPages: pager.totalPages,
|
hasNext: typeof pager.nextCursor === 'string',
|
||||||
currentPage: pager.page,
|
nextCursor: typeof pager.nextCursor === 'string' ? pager.nextCursor : undefined,
|
||||||
onPageChange: handlePageChange
|
previousCursor: typeof pager.previousCursor === 'string' ? pager.previousCursor : undefined,
|
||||||
|
onNext: handleNext,
|
||||||
|
onPrevious: handlePrevious
|
||||||
} : undefined}
|
} : undefined}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -35,7 +35,8 @@ export interface ArchiveMessage extends Record<string, unknown> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface MessageListQueryDto {
|
export interface MessageListQueryDto {
|
||||||
page?: number;
|
next?: string;
|
||||||
|
previous?: string;
|
||||||
limit?: number;
|
limit?: number;
|
||||||
search?: string;
|
search?: string;
|
||||||
from?: string;
|
from?: string;
|
||||||
@@ -43,6 +44,7 @@ export interface MessageListQueryDto {
|
|||||||
datestart?: string;
|
datestart?: string;
|
||||||
dateend?: string;
|
dateend?: string;
|
||||||
attachments?: boolean;
|
attachments?: boolean;
|
||||||
|
unseen?: boolean;
|
||||||
flagged?: boolean;
|
flagged?: boolean;
|
||||||
order?: "asc" | "desc";
|
order?: "asc" | "desc";
|
||||||
}
|
}
|
||||||
@@ -57,8 +59,17 @@ export interface ArchiveResponse {
|
|||||||
totalPages: number;
|
totalPages: number;
|
||||||
totalItems: number;
|
totalItems: number;
|
||||||
limit: number;
|
limit: number;
|
||||||
prevPage: boolean;
|
previousCursor: string | boolean;
|
||||||
nextPage: boolean;
|
nextCursor: string | boolean;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface Pager {
|
||||||
|
page: number;
|
||||||
|
limit: number;
|
||||||
|
totalItems: number;
|
||||||
|
totalPages: number;
|
||||||
|
previousCursor: string | boolean;
|
||||||
|
nextCursor: string | boolean;
|
||||||
|
}
|
||||||
|
|||||||
@@ -15,13 +15,15 @@ import { useSharedStore } from '@/shared/store/sharedStore';
|
|||||||
const List: FC = () => {
|
const List: FC = () => {
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const [currentPage, setCurrentPage] = useState(1);
|
const [nextCursor, setNextCursor] = useState<string | undefined>(undefined);
|
||||||
|
const [previousCursor, setPreviousCursor] = useState<string | undefined>(undefined);
|
||||||
const [filters, setFilters] = useState<FilterValues>({});
|
const [filters, setFilters] = useState<FilterValues>({});
|
||||||
const emailActions = useEmailActions();
|
const emailActions = useEmailActions();
|
||||||
const { setDraftData, setOpenNewMessage, setEditingDraftId } = useSharedStore();
|
const { setDraftData, setOpenNewMessage, setEditingDraftId } = useSharedStore();
|
||||||
|
|
||||||
const { data: draftData, isLoading, refetch, isFetching } = useGetDrafts({
|
const { data: draftData, isLoading, refetch, isFetching } = useGetDrafts({
|
||||||
page: currentPage,
|
next: nextCursor,
|
||||||
|
previous: previousCursor,
|
||||||
limit: 10,
|
limit: 10,
|
||||||
...filters
|
...filters
|
||||||
});
|
});
|
||||||
@@ -106,7 +108,8 @@ const List: FC = () => {
|
|||||||
|
|
||||||
const handleFilterChange = (newFilters: FilterValues) => {
|
const handleFilterChange = (newFilters: FilterValues) => {
|
||||||
setFilters(newFilters);
|
setFilters(newFilters);
|
||||||
setCurrentPage(1);
|
setNextCursor(undefined);
|
||||||
|
setPreviousCursor(undefined);
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleSelectionChange = (selectedRows: DraftMessage[]) => {
|
const handleSelectionChange = (selectedRows: DraftMessage[]) => {
|
||||||
@@ -171,11 +174,19 @@ const List: FC = () => {
|
|||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
const handlePageChange = (page: number) => {
|
|
||||||
setCurrentPage(page);
|
|
||||||
|
const handleNext = (cursor?: string) => {
|
||||||
|
setNextCursor(cursor);
|
||||||
|
setPreviousCursor(undefined);
|
||||||
};
|
};
|
||||||
|
|
||||||
const messages = draftData?.data?.draftsMail || [];
|
const handlePrevious = (cursor?: string) => {
|
||||||
|
setPreviousCursor(cursor);
|
||||||
|
setNextCursor(undefined);
|
||||||
|
};
|
||||||
|
|
||||||
|
const messages = draftData?.data?.draftMails || [];
|
||||||
const pager = draftData?.data?.pager;
|
const pager = draftData?.data?.pager;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -211,9 +222,11 @@ const List: FC = () => {
|
|||||||
selectable={true}
|
selectable={true}
|
||||||
rowActions={getRowActions}
|
rowActions={getRowActions}
|
||||||
pagination={pager ? {
|
pagination={pager ? {
|
||||||
totalPages: pager.totalPages,
|
hasNext: typeof pager.nextCursor === 'string',
|
||||||
currentPage: pager.page,
|
nextCursor: typeof pager.nextCursor === 'string' ? pager.nextCursor : undefined,
|
||||||
onPageChange: handlePageChange
|
previousCursor: typeof pager.previousCursor === 'string' ? pager.previousCursor : undefined,
|
||||||
|
onNext: handleNext,
|
||||||
|
onPrevious: handlePrevious
|
||||||
} : undefined}
|
} : undefined}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -19,7 +19,8 @@ export interface EmailAttachmentDto {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface MessageListQueryDto {
|
export interface MessageListQueryDto {
|
||||||
page?: number;
|
next?: string;
|
||||||
|
previous?: string;
|
||||||
limit?: number;
|
limit?: number;
|
||||||
search?: string;
|
search?: string;
|
||||||
from?: string;
|
from?: string;
|
||||||
@@ -27,6 +28,7 @@ export interface MessageListQueryDto {
|
|||||||
datestart?: string;
|
datestart?: string;
|
||||||
dateend?: string;
|
dateend?: string;
|
||||||
attachments?: boolean;
|
attachments?: boolean;
|
||||||
|
unseen?: boolean;
|
||||||
flagged?: boolean;
|
flagged?: boolean;
|
||||||
order?: "asc" | "desc";
|
order?: "asc" | "desc";
|
||||||
}
|
}
|
||||||
@@ -76,21 +78,21 @@ export interface DraftMessage extends Record<string, unknown> {
|
|||||||
|
|
||||||
export type InboxMessage = DraftMessage;
|
export type InboxMessage = DraftMessage;
|
||||||
|
|
||||||
export interface InboxPager {
|
export interface Pager {
|
||||||
page: number;
|
page: number;
|
||||||
limit: number;
|
limit: number;
|
||||||
totalItems: number;
|
totalItems: number;
|
||||||
totalPages: number;
|
totalPages: number;
|
||||||
prevPage: boolean;
|
previousCursor: string | boolean;
|
||||||
nextPage: boolean;
|
nextCursor: string | boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface InboxResponse {
|
export interface InboxResponse {
|
||||||
statusCode: number;
|
statusCode: number;
|
||||||
success: boolean;
|
success: boolean;
|
||||||
data: {
|
data: {
|
||||||
pager: InboxPager;
|
pager: Pager;
|
||||||
draftsMail: DraftMessage[];
|
draftMails: DraftMessage[];
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -13,12 +13,14 @@ import Favorite from '../received/Components/Favorite';
|
|||||||
|
|
||||||
const List: FC = () => {
|
const List: FC = () => {
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const [currentPage, setCurrentPage] = useState(1);
|
const [nextCursor, setNextCursor] = useState<string | undefined>(undefined);
|
||||||
|
const [previousCursor, setPreviousCursor] = useState<string | undefined>(undefined);
|
||||||
const [filters, setFilters] = useState<FilterValues>({});
|
const [filters, setFilters] = useState<FilterValues>({});
|
||||||
const emailActions = useEmailActions();
|
const emailActions = useEmailActions();
|
||||||
|
|
||||||
const { data: favoriteData, isLoading, refetch, isFetching } = useGetFavoriteMessages({
|
const { data: favoriteData, isLoading, refetch, isFetching } = useGetFavoriteMessages({
|
||||||
page: currentPage,
|
next: nextCursor,
|
||||||
|
previous: previousCursor,
|
||||||
limit: 10,
|
limit: 10,
|
||||||
...filters
|
...filters
|
||||||
});
|
});
|
||||||
@@ -75,7 +77,8 @@ const List: FC = () => {
|
|||||||
|
|
||||||
const handleFilterChange = (newFilters: FilterValues) => {
|
const handleFilterChange = (newFilters: FilterValues) => {
|
||||||
setFilters(newFilters);
|
setFilters(newFilters);
|
||||||
setCurrentPage(1);
|
setNextCursor(undefined);
|
||||||
|
setPreviousCursor(undefined);
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleSelectionChange = (selectedRows: FavoriteMessage[]) => {
|
const handleSelectionChange = (selectedRows: FavoriteMessage[]) => {
|
||||||
@@ -125,8 +128,14 @@ const List: FC = () => {
|
|||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
const handlePageChange = (page: number) => {
|
const handleNext = (cursor?: string) => {
|
||||||
setCurrentPage(page);
|
setNextCursor(cursor);
|
||||||
|
setPreviousCursor(undefined);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handlePrevious = (cursor?: string) => {
|
||||||
|
setPreviousCursor(cursor);
|
||||||
|
setNextCursor(undefined);
|
||||||
};
|
};
|
||||||
|
|
||||||
const messages = favoriteData?.data?.favoriteMails || [];
|
const messages = favoriteData?.data?.favoriteMails || [];
|
||||||
@@ -165,9 +174,11 @@ const List: FC = () => {
|
|||||||
selectable={true}
|
selectable={true}
|
||||||
rowActions={getRowActions}
|
rowActions={getRowActions}
|
||||||
pagination={pager ? {
|
pagination={pager ? {
|
||||||
totalPages: pager.totalPages,
|
hasNext: typeof pager.nextCursor === 'string',
|
||||||
currentPage: pager.page,
|
nextCursor: typeof pager.nextCursor === 'string' ? pager.nextCursor : undefined,
|
||||||
onPageChange: handlePageChange
|
previousCursor: typeof pager.previousCursor === 'string' ? pager.previousCursor : undefined,
|
||||||
|
onNext: handleNext,
|
||||||
|
onPrevious: handlePrevious
|
||||||
} : undefined}
|
} : undefined}
|
||||||
inlineActions={getInlineActions}
|
inlineActions={getInlineActions}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -35,7 +35,8 @@ export interface FavoriteMessage extends Record<string, unknown> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface MessageListQueryDto {
|
export interface MessageListQueryDto {
|
||||||
page?: number;
|
next?: string;
|
||||||
|
previous?: string;
|
||||||
limit?: number;
|
limit?: number;
|
||||||
search?: string;
|
search?: string;
|
||||||
from?: string;
|
from?: string;
|
||||||
@@ -43,6 +44,7 @@ export interface MessageListQueryDto {
|
|||||||
datestart?: string;
|
datestart?: string;
|
||||||
dateend?: string;
|
dateend?: string;
|
||||||
attachments?: boolean;
|
attachments?: boolean;
|
||||||
|
unseen?: boolean;
|
||||||
flagged?: boolean;
|
flagged?: boolean;
|
||||||
order?: "asc" | "desc";
|
order?: "asc" | "desc";
|
||||||
}
|
}
|
||||||
@@ -57,8 +59,17 @@ export interface FavoriteResponse {
|
|||||||
totalPages: number;
|
totalPages: number;
|
||||||
totalItems: number;
|
totalItems: number;
|
||||||
limit: number;
|
limit: number;
|
||||||
prevPage: boolean;
|
previousCursor: string | boolean;
|
||||||
nextPage: boolean;
|
nextCursor: string | boolean;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface Pager {
|
||||||
|
page: number;
|
||||||
|
limit: number;
|
||||||
|
totalItems: number;
|
||||||
|
totalPages: number;
|
||||||
|
previousCursor: string | boolean;
|
||||||
|
nextCursor: string | boolean;
|
||||||
|
}
|
||||||
|
|||||||
@@ -20,14 +20,16 @@ const List: FC = () => {
|
|||||||
|
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const [currentPage, setCurrentPage] = useState(1);
|
const [nextCursor, setNextCursor] = useState<string | undefined>(undefined);
|
||||||
|
const [previousCursor, setPreviousCursor] = useState<string | undefined>(undefined);
|
||||||
const [filters, setFilters] = useState<FilterValues>({});
|
const [filters, setFilters] = useState<FilterValues>({});
|
||||||
const emailActions = useEmailActions();
|
const emailActions = useEmailActions();
|
||||||
const [openSummarizeModal, setOpenSummarizeModal] = useState(false);
|
const [openSummarizeModal, setOpenSummarizeModal] = useState(false);
|
||||||
const { mutate: summarizeEmail, isPending: isSummarizing, data: summarizeData } = useSummarizeEmail();
|
const { mutate: summarizeEmail, isPending: isSummarizing, data: summarizeData } = useSummarizeEmail();
|
||||||
|
|
||||||
const { data: inboxData, isLoading, refetch, isFetching } = useGetInbox({
|
const { data: inboxData, isLoading, refetch, isFetching } = useGetInbox({
|
||||||
page: currentPage,
|
next: nextCursor,
|
||||||
|
previous: previousCursor,
|
||||||
limit: 10,
|
limit: 10,
|
||||||
...filters
|
...filters
|
||||||
});
|
});
|
||||||
@@ -113,7 +115,8 @@ const List: FC = () => {
|
|||||||
|
|
||||||
const handleFilterChange = (newFilters: FilterValues) => {
|
const handleFilterChange = (newFilters: FilterValues) => {
|
||||||
setFilters(newFilters);
|
setFilters(newFilters);
|
||||||
setCurrentPage(1);
|
setNextCursor(undefined);
|
||||||
|
setPreviousCursor(undefined);
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleSelectionChange = (selectedRows: InboxMessage[]) => {
|
const handleSelectionChange = (selectedRows: InboxMessage[]) => {
|
||||||
@@ -189,12 +192,34 @@ const List: FC = () => {
|
|||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
const handlePageChange = (page: number) => {
|
const handleNext = (cursor?: string) => {
|
||||||
setCurrentPage(page);
|
setNextCursor(cursor);
|
||||||
|
setPreviousCursor(undefined);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handlePrevious = (cursor?: string) => {
|
||||||
|
setPreviousCursor(cursor);
|
||||||
|
setNextCursor(undefined);
|
||||||
};
|
};
|
||||||
|
|
||||||
const messages = inboxData?.data?.results || [];
|
const messages = inboxData?.data?.results || [];
|
||||||
const pager = inboxData?.data?.pager;
|
const pager = inboxData?.data?.pager;
|
||||||
|
const rootData = inboxData?.data as unknown as Record<string, unknown>;
|
||||||
|
|
||||||
|
// Debug pagination data
|
||||||
|
console.log('Full response data:', inboxData?.data);
|
||||||
|
console.log('Pager data:', pager);
|
||||||
|
console.log('Root nextCursor:', rootData?.nextCursor);
|
||||||
|
console.log('Root previousCursor:', rootData?.previousCursor);
|
||||||
|
|
||||||
|
// Get cursors from response
|
||||||
|
const responseNextCursor = (typeof rootData?.nextCursor === 'string' && rootData.nextCursor !== '') ? rootData.nextCursor as string : undefined;
|
||||||
|
const responsePreviousCursor = (typeof rootData?.previousCursor === 'string' && rootData.previousCursor !== '') ? rootData.previousCursor as string : undefined;
|
||||||
|
|
||||||
|
// Debug pagination values
|
||||||
|
console.log('responseNextCursor:', responseNextCursor);
|
||||||
|
console.log('responsePreviousCursor:', responsePreviousCursor);
|
||||||
|
console.log('Will render pagination?', !!(responseNextCursor || responsePreviousCursor));
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='mt-2 md:mt-4 px-2 md:px-0'>
|
<div className='mt-2 md:mt-4 px-2 md:px-0'>
|
||||||
@@ -239,10 +264,12 @@ const List: FC = () => {
|
|||||||
selectable={true}
|
selectable={true}
|
||||||
inlineActions={getInlineActions}
|
inlineActions={getInlineActions}
|
||||||
rowActions={getRowActions}
|
rowActions={getRowActions}
|
||||||
pagination={pager ? {
|
pagination={(responseNextCursor || responsePreviousCursor) ? {
|
||||||
totalPages: pager.totalPages,
|
hasNext: !!responseNextCursor,
|
||||||
currentPage: pager.page,
|
nextCursor: responseNextCursor,
|
||||||
onPageChange: handlePageChange
|
previousCursor: responsePreviousCursor,
|
||||||
|
onNext: handleNext,
|
||||||
|
onPrevious: handlePrevious
|
||||||
} : undefined}
|
} : undefined}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
|||||||
@@ -54,7 +54,8 @@ export interface SendEmailDto {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface MessageListQueryDto {
|
export interface MessageListQueryDto {
|
||||||
page?: number;
|
next?: string;
|
||||||
|
previous?: string;
|
||||||
limit?: number;
|
limit?: number;
|
||||||
search?: string;
|
search?: string;
|
||||||
from?: string;
|
from?: string;
|
||||||
@@ -111,20 +112,20 @@ export interface InboxMessage extends Record<string, unknown> {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface InboxPager {
|
export interface Pager {
|
||||||
page: number;
|
page: number;
|
||||||
limit: number;
|
limit: number;
|
||||||
totalItems: number;
|
totalItems: number;
|
||||||
totalPages: number;
|
totalPages: number;
|
||||||
prevPage: boolean;
|
previousCursor: string | boolean;
|
||||||
nextPage: boolean;
|
nextCursor: string | boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface InboxResponse {
|
export interface InboxResponse {
|
||||||
statusCode: number;
|
statusCode: number;
|
||||||
success: boolean;
|
success: boolean;
|
||||||
data: {
|
data: {
|
||||||
pager: InboxPager;
|
pager: Pager;
|
||||||
message: string;
|
message: string;
|
||||||
results: InboxMessage[];
|
results: InboxMessage[];
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -12,12 +12,14 @@ import { useEmailActions } from '@/hooks/useEmailActions';
|
|||||||
|
|
||||||
const List: FC = () => {
|
const List: FC = () => {
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const [currentPage, setCurrentPage] = useState(1);
|
const [nextCursor, setNextCursor] = useState<string | undefined>(undefined);
|
||||||
|
const [previousCursor, setPreviousCursor] = useState<string | undefined>(undefined);
|
||||||
const [filters, setFilters] = useState<FilterValues>({});
|
const [filters, setFilters] = useState<FilterValues>({});
|
||||||
const emailActions = useEmailActions();
|
const emailActions = useEmailActions();
|
||||||
|
|
||||||
const { data: searchData, isLoading, refetch, isFetching } = useSearchMessages({
|
const { data: searchData, isLoading, refetch, isFetching } = useSearchMessages({
|
||||||
page: currentPage,
|
next: nextCursor,
|
||||||
|
previous: previousCursor,
|
||||||
limit: 10,
|
limit: 10,
|
||||||
...filters
|
...filters
|
||||||
});
|
});
|
||||||
@@ -81,7 +83,8 @@ const List: FC = () => {
|
|||||||
|
|
||||||
const handleFilterChange = (newFilters: FilterValues) => {
|
const handleFilterChange = (newFilters: FilterValues) => {
|
||||||
setFilters(newFilters);
|
setFilters(newFilters);
|
||||||
setCurrentPage(1);
|
setNextCursor(undefined);
|
||||||
|
setPreviousCursor(undefined);
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleSelectionChange = (selectedRows: SearchMessage[]) => {
|
const handleSelectionChange = (selectedRows: SearchMessage[]) => {
|
||||||
@@ -124,8 +127,14 @@ const List: FC = () => {
|
|||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
const handlePageChange = (page: number) => {
|
const handleNext = (cursor?: string) => {
|
||||||
setCurrentPage(page);
|
setNextCursor(cursor);
|
||||||
|
setPreviousCursor(undefined);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handlePrevious = (cursor?: string) => {
|
||||||
|
setPreviousCursor(cursor);
|
||||||
|
setNextCursor(undefined);
|
||||||
};
|
};
|
||||||
|
|
||||||
const messages = searchData?.data?.results || [];
|
const messages = searchData?.data?.results || [];
|
||||||
@@ -180,9 +189,11 @@ const List: FC = () => {
|
|||||||
selectable={true}
|
selectable={true}
|
||||||
rowActions={getRowActions}
|
rowActions={getRowActions}
|
||||||
pagination={pager ? {
|
pagination={pager ? {
|
||||||
totalPages: pager.totalPages,
|
hasNext: typeof pager.nextCursor === 'string',
|
||||||
currentPage: pager.page,
|
nextCursor: typeof pager.nextCursor === 'string' ? pager.nextCursor : undefined,
|
||||||
onPageChange: handlePageChange
|
previousCursor: typeof pager.previousCursor === 'string' ? pager.previousCursor : undefined,
|
||||||
|
onNext: handleNext,
|
||||||
|
onPrevious: handlePrevious
|
||||||
} : undefined}
|
} : undefined}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -34,8 +34,24 @@ export interface SearchMessage extends Record<string, unknown> {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface MessageListQueryDto {
|
||||||
|
next?: string;
|
||||||
|
previous?: string;
|
||||||
|
limit?: number;
|
||||||
|
search?: string;
|
||||||
|
from?: string;
|
||||||
|
subject?: string;
|
||||||
|
datestart?: string;
|
||||||
|
dateend?: string;
|
||||||
|
attachments?: boolean;
|
||||||
|
unseen?: boolean;
|
||||||
|
flagged?: boolean;
|
||||||
|
order?: "asc" | "desc";
|
||||||
|
}
|
||||||
|
|
||||||
export interface SearchQueryDto {
|
export interface SearchQueryDto {
|
||||||
page?: number;
|
next?: string;
|
||||||
|
previous?: string;
|
||||||
limit?: number;
|
limit?: number;
|
||||||
q?: string;
|
q?: string;
|
||||||
dateFrom?: string;
|
dateFrom?: string;
|
||||||
@@ -52,8 +68,8 @@ export interface SearchResponse {
|
|||||||
totalPages: number;
|
totalPages: number;
|
||||||
totalItems: number;
|
totalItems: number;
|
||||||
limit: number;
|
limit: number;
|
||||||
prevPage: boolean;
|
previousCursor: string | boolean;
|
||||||
nextPage: boolean;
|
nextCursor: string | boolean;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
+19
-8
@@ -13,12 +13,14 @@ import { formatDate } from '@/config/func';
|
|||||||
|
|
||||||
const List: FC = () => {
|
const List: FC = () => {
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const [currentPage, setCurrentPage] = useState(1);
|
const [nextCursor, setNextCursor] = useState<string | undefined>(undefined);
|
||||||
|
const [previousCursor, setPreviousCursor] = useState<string | undefined>(undefined);
|
||||||
const [filters, setFilters] = useState<FilterValues>({});
|
const [filters, setFilters] = useState<FilterValues>({});
|
||||||
const emailActions = useEmailActions();
|
const emailActions = useEmailActions();
|
||||||
|
|
||||||
const { data: sentData, isLoading, refetch, isFetching } = useGetSentMessages({
|
const { data: sentData, isLoading, refetch, isFetching } = useGetSentMessages({
|
||||||
page: currentPage,
|
next: nextCursor,
|
||||||
|
previous: previousCursor,
|
||||||
limit: 10,
|
limit: 10,
|
||||||
...filters
|
...filters
|
||||||
});
|
});
|
||||||
@@ -91,7 +93,8 @@ const List: FC = () => {
|
|||||||
|
|
||||||
const handleFilterChange = (newFilters: FilterValues) => {
|
const handleFilterChange = (newFilters: FilterValues) => {
|
||||||
setFilters(newFilters);
|
setFilters(newFilters);
|
||||||
setCurrentPage(1);
|
setNextCursor(undefined);
|
||||||
|
setPreviousCursor(undefined);
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleRowClick = (id: number, item: InboxMessage) => {
|
const handleRowClick = (id: number, item: InboxMessage) => {
|
||||||
@@ -138,8 +141,14 @@ const List: FC = () => {
|
|||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
const handlePageChange = (page: number) => {
|
const handleNext = (cursor?: string) => {
|
||||||
setCurrentPage(page);
|
setNextCursor(cursor);
|
||||||
|
setPreviousCursor(undefined);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handlePrevious = (cursor?: string) => {
|
||||||
|
setPreviousCursor(cursor);
|
||||||
|
setNextCursor(undefined);
|
||||||
};
|
};
|
||||||
|
|
||||||
const messages = sentData?.data?.sentMails || [];
|
const messages = sentData?.data?.sentMails || [];
|
||||||
@@ -178,9 +187,11 @@ const List: FC = () => {
|
|||||||
selectable={true}
|
selectable={true}
|
||||||
rowActions={getRowActions}
|
rowActions={getRowActions}
|
||||||
pagination={pager ? {
|
pagination={pager ? {
|
||||||
totalPages: pager.totalPages,
|
hasNext: typeof pager.nextCursor === 'string',
|
||||||
currentPage: pager.page,
|
nextCursor: typeof pager.nextCursor === 'string' ? pager.nextCursor : undefined,
|
||||||
onPageChange: handlePageChange
|
previousCursor: typeof pager.previousCursor === 'string' ? pager.previousCursor : undefined,
|
||||||
|
onNext: handleNext,
|
||||||
|
onPrevious: handlePrevious
|
||||||
} : undefined}
|
} : undefined}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
export interface MessageListQueryDto {
|
export interface MessageListQueryDto {
|
||||||
page?: number;
|
next?: string;
|
||||||
|
previous?: string;
|
||||||
limit?: number;
|
limit?: number;
|
||||||
search?: string;
|
search?: string;
|
||||||
from?: string;
|
from?: string;
|
||||||
@@ -7,6 +8,7 @@ export interface MessageListQueryDto {
|
|||||||
datestart?: string;
|
datestart?: string;
|
||||||
dateend?: string;
|
dateend?: string;
|
||||||
attachments?: boolean;
|
attachments?: boolean;
|
||||||
|
unseen?: boolean;
|
||||||
flagged?: boolean;
|
flagged?: boolean;
|
||||||
order?: "asc" | "desc";
|
order?: "asc" | "desc";
|
||||||
}
|
}
|
||||||
@@ -54,8 +56,8 @@ export interface Pager {
|
|||||||
limit: number;
|
limit: number;
|
||||||
totalItems: number;
|
totalItems: number;
|
||||||
totalPages: number;
|
totalPages: number;
|
||||||
prevPage: boolean;
|
previousCursor: string | boolean;
|
||||||
nextPage: boolean;
|
nextCursor: string | boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface InboxResponse {
|
export interface InboxResponse {
|
||||||
|
|||||||
+19
-8
@@ -12,12 +12,14 @@ import { useEmailActions } from '@/hooks/useEmailActions';
|
|||||||
|
|
||||||
const List: FC = () => {
|
const List: FC = () => {
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const [currentPage, setCurrentPage] = useState(1);
|
const [nextCursor, setNextCursor] = useState<string | undefined>(undefined);
|
||||||
|
const [previousCursor, setPreviousCursor] = useState<string | undefined>(undefined);
|
||||||
const [filters, setFilters] = useState<FilterValues>({});
|
const [filters, setFilters] = useState<FilterValues>({});
|
||||||
const emailActions = useEmailActions();
|
const emailActions = useEmailActions();
|
||||||
|
|
||||||
const { data: spamData, isLoading, refetch, isFetching } = useGetSpamMessages({
|
const { data: spamData, isLoading, refetch, isFetching } = useGetSpamMessages({
|
||||||
page: currentPage,
|
next: nextCursor,
|
||||||
|
previous: previousCursor,
|
||||||
limit: 10,
|
limit: 10,
|
||||||
...filters
|
...filters
|
||||||
});
|
});
|
||||||
@@ -72,7 +74,8 @@ const List: FC = () => {
|
|||||||
|
|
||||||
const handleFilterChange = (newFilters: FilterValues) => {
|
const handleFilterChange = (newFilters: FilterValues) => {
|
||||||
setFilters(newFilters);
|
setFilters(newFilters);
|
||||||
setCurrentPage(1);
|
setNextCursor(undefined);
|
||||||
|
setPreviousCursor(undefined);
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleSelectionChange = (selectedRows: SpamMessage[]) => {
|
const handleSelectionChange = (selectedRows: SpamMessage[]) => {
|
||||||
@@ -104,8 +107,14 @@ const List: FC = () => {
|
|||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
const handlePageChange = (page: number) => {
|
const handleNext = (cursor?: string) => {
|
||||||
setCurrentPage(page);
|
setNextCursor(cursor);
|
||||||
|
setPreviousCursor(undefined);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handlePrevious = (cursor?: string) => {
|
||||||
|
setPreviousCursor(cursor);
|
||||||
|
setNextCursor(undefined);
|
||||||
};
|
};
|
||||||
|
|
||||||
const messages = spamData?.data?.junkMails || [];
|
const messages = spamData?.data?.junkMails || [];
|
||||||
@@ -144,9 +153,11 @@ const List: FC = () => {
|
|||||||
selectable={true}
|
selectable={true}
|
||||||
rowActions={getRowActions}
|
rowActions={getRowActions}
|
||||||
pagination={pager ? {
|
pagination={pager ? {
|
||||||
totalPages: pager.totalPages,
|
hasNext: typeof pager.nextCursor === 'string',
|
||||||
currentPage: pager.page,
|
nextCursor: typeof pager.nextCursor === 'string' ? pager.nextCursor : undefined,
|
||||||
onPageChange: handlePageChange
|
previousCursor: typeof pager.previousCursor === 'string' ? pager.previousCursor : undefined,
|
||||||
|
onNext: handleNext,
|
||||||
|
onPrevious: handlePrevious
|
||||||
} : undefined}
|
} : undefined}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -35,7 +35,8 @@ export interface SpamMessage extends Record<string, unknown> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface MessageListQueryDto {
|
export interface MessageListQueryDto {
|
||||||
page?: number;
|
next?: string;
|
||||||
|
previous?: string;
|
||||||
limit?: number;
|
limit?: number;
|
||||||
search?: string;
|
search?: string;
|
||||||
from?: string;
|
from?: string;
|
||||||
@@ -43,6 +44,7 @@ export interface MessageListQueryDto {
|
|||||||
datestart?: string;
|
datestart?: string;
|
||||||
dateend?: string;
|
dateend?: string;
|
||||||
attachments?: boolean;
|
attachments?: boolean;
|
||||||
|
unseen?: boolean;
|
||||||
flagged?: boolean;
|
flagged?: boolean;
|
||||||
order?: "asc" | "desc";
|
order?: "asc" | "desc";
|
||||||
}
|
}
|
||||||
@@ -56,8 +58,17 @@ export interface SpamResponse {
|
|||||||
totalPages: number;
|
totalPages: number;
|
||||||
totalItems: number;
|
totalItems: number;
|
||||||
limit: number;
|
limit: number;
|
||||||
prevPage: boolean;
|
previousCursor: string | boolean;
|
||||||
nextPage: boolean;
|
nextCursor: string | boolean;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface Pager {
|
||||||
|
page: number;
|
||||||
|
limit: number;
|
||||||
|
totalItems: number;
|
||||||
|
totalPages: number;
|
||||||
|
previousCursor: string | boolean;
|
||||||
|
nextCursor: string | boolean;
|
||||||
|
}
|
||||||
|
|||||||
+50
-1
@@ -2,8 +2,57 @@ import { defineConfig } from "vite";
|
|||||||
import react from "@vitejs/plugin-react";
|
import react from "@vitejs/plugin-react";
|
||||||
import tailwindcss from "@tailwindcss/vite";
|
import tailwindcss from "@tailwindcss/vite";
|
||||||
import tsconfigPaths from "vite-tsconfig-paths";
|
import tsconfigPaths from "vite-tsconfig-paths";
|
||||||
|
import { VitePWA } from "vite-plugin-pwa";
|
||||||
|
|
||||||
// https://vite.dev/config/
|
// https://vite.dev/config/
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
plugins: [react(), tailwindcss(), tsconfigPaths()],
|
plugins: [
|
||||||
|
react(),
|
||||||
|
tailwindcss(),
|
||||||
|
tsconfigPaths(),
|
||||||
|
VitePWA({
|
||||||
|
registerType: "autoUpdate",
|
||||||
|
devOptions: {
|
||||||
|
enabled: false, // در حالت توسعه هم کار کند
|
||||||
|
},
|
||||||
|
manifest: {
|
||||||
|
name: "Danak Mail",
|
||||||
|
short_name: "Danak Mail",
|
||||||
|
description: "Danak Mail",
|
||||||
|
theme_color: "#ffffff",
|
||||||
|
background_color: "#ffffff",
|
||||||
|
display: "standalone",
|
||||||
|
start_url: "/received", // صفحه اصلی PWA
|
||||||
|
icons: [
|
||||||
|
{
|
||||||
|
src: "/icon-192x192.png",
|
||||||
|
sizes: "192x192",
|
||||||
|
type: "image/png",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
src: "/icon-512x512.png",
|
||||||
|
sizes: "512x512",
|
||||||
|
type: "image/png",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
// workbox: {
|
||||||
|
// maximumFileSizeToCacheInBytes: 4 * 1024 * 1024, // افزایش به 4MB
|
||||||
|
// runtimeCaching: [
|
||||||
|
// {
|
||||||
|
// urlPattern: /^https:\/\/admin-panel\.danakcorp\.com\//,
|
||||||
|
// handler: "NetworkFirst",
|
||||||
|
// options: {
|
||||||
|
// cacheName: "api-cache",
|
||||||
|
// expiration: {
|
||||||
|
// maxEntries: 50,
|
||||||
|
// maxAgeSeconds: 60 * 60 * 24,
|
||||||
|
// },
|
||||||
|
// networkTimeoutSeconds: 10,
|
||||||
|
// },
|
||||||
|
// },
|
||||||
|
// ],
|
||||||
|
// },
|
||||||
|
}),
|
||||||
|
],
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user