роутинг пагинации
This commit is contained in:
@@ -118,6 +118,14 @@ export interface IRequestsTableViewProps {
|
||||
/** Фильтр по статусу заявки; только для view='own:created'. '' — все статусы. */
|
||||
statusFilter?: string;
|
||||
onStatusFilterChange?: (status: string) => void;
|
||||
/**
|
||||
* Текущая страница (1-based) и её смена. Страница живёт в маршруте, а не
|
||||
* внутри компонента: так она попадает в адрес (ссылку можно передать),
|
||||
* переживает открытие/закрытие заявки и запоминается для этой таблицы
|
||||
* (см. persistPage в shared/routing.ts).
|
||||
*/
|
||||
page: number;
|
||||
onPageChange: (page: number) => void;
|
||||
/** Клик по строке — открыть заявку (в выезжающей панели). */
|
||||
onOpen: (request: IMyRequest) => void;
|
||||
}
|
||||
@@ -230,12 +238,13 @@ export const RequestsTableView: React.FC<IRequestsTableViewProps> = ({
|
||||
view,
|
||||
statusFilter = '',
|
||||
onStatusFilterChange,
|
||||
page,
|
||||
onPageChange,
|
||||
onOpen,
|
||||
}) => {
|
||||
const [types, setTypes] = React.useState<IRequestType[] | undefined>(undefined);
|
||||
const [rows, setRows] = React.useState<IMyRequest[] | undefined>(undefined);
|
||||
const [totalRows, setTotalRows] = React.useState<number>(0);
|
||||
const [page, setPage] = React.useState<number>(1);
|
||||
const [query, setQuery] = usePersistedQuery(view);
|
||||
const [error, setError] = React.useState<string>('');
|
||||
// query — то, что в поле ввода (меняется сразу); debouncedQuery — то, что
|
||||
@@ -243,7 +252,18 @@ export const RequestsTableView: React.FC<IRequestsTableViewProps> = ({
|
||||
// иначе поиск бил бы запросом по каждой набранной букве.
|
||||
const debouncedQuery = useDebouncedQuery(query);
|
||||
|
||||
React.useEffect(() => setPage(1), [debouncedQuery, view, statusFilter]);
|
||||
// Смена ЗАПРОСА сбрасывает страницу: набор результатов другой, и «страница 3»
|
||||
// от прошлого запроса к нему отношения не имеет. Смену вкладки/фильтра здесь
|
||||
// НЕ обрабатываем — там страница приходит уже правильной из маршрута
|
||||
// (см. RequestPortal: gotoOwnTab/setOwnStatus). Сравниваем с предыдущим
|
||||
// значением, а не просто вешаемся на изменение: иначе эффект сбрасывал бы
|
||||
// страницу и на первом рендере, затирая ту, что пришла из адреса.
|
||||
const prevQuery = React.useRef<string>(debouncedQuery);
|
||||
React.useEffect(() => {
|
||||
if (prevQuery.current === debouncedQuery) return;
|
||||
prevQuery.current = debouncedQuery;
|
||||
if (page !== 1) onPageChange(1);
|
||||
}, [debouncedQuery, page, onPageChange]);
|
||||
|
||||
React.useEffect(() => {
|
||||
let cancelled = false;
|
||||
@@ -348,6 +368,14 @@ export const RequestsTableView: React.FC<IRequestsTableViewProps> = ({
|
||||
const visible = rows || [];
|
||||
const totalPages = Math.max(1, Math.ceil(total / PAGE_SIZE));
|
||||
|
||||
// Страница может оказаться за пределами набора: пришла из старой ссылки или
|
||||
// из запомненной, а заявок с тех пор стало меньше (часть согласовали, и они
|
||||
// ушли из этой очереди). Показывать пустую таблицу с непустым счётчиком —
|
||||
// выглядит как поломка, поэтому возвращаемся на последнюю существующую.
|
||||
React.useEffect(() => {
|
||||
if (rows && page > totalPages) onPageChange(totalPages);
|
||||
}, [rows, page, totalPages, onPageChange]);
|
||||
|
||||
return (
|
||||
<section className={styles.view}>
|
||||
<div className={styles.head}>
|
||||
@@ -392,7 +420,7 @@ export const RequestsTableView: React.FC<IRequestsTableViewProps> = ({
|
||||
{!error && rows && total > 0 && (
|
||||
<>
|
||||
<Table rows={visible} view={view} onOpen={onOpen} />
|
||||
<Pager page={page} totalPages={totalPages} onChange={setPage} />
|
||||
<Pager page={page} totalPages={totalPages} onChange={onPageChange} />
|
||||
</>
|
||||
)}
|
||||
</section>
|
||||
|
||||
Reference in New Issue
Block a user