- Unify API: lib/api.ts uses /api/v1, inbox uses /api/inbox (rewrites) - Remove localhost refs: openapi, inbox page - Add rewrites: /api/inbox|tmc -> inbox-server, /api/v1 -> FastAPI - Add stub routes: knowledge/insights, recommendations, search, log-error - Transfer from PAPA: prompts (inspection, tmc), scripts, supabase, data/tmc-requests - Fix inbox-server: ORDER BY created_at, package.json - Remove redundant app/api/inbox/files route (rewrites handle it) - knowledge/ in gitignore (large PDFs) Co-authored-by: Cursor <cursoragent@cursor.com>
92 lines
1.7 KiB
TypeScript
92 lines
1.7 KiB
TypeScript
/**
|
|
* Хук для пагинации данных
|
|
*/
|
|
'use client';
|
|
|
|
import { useMemo, useState } from 'react';
|
|
|
|
export interface PaginationOptions {
|
|
page: number;
|
|
limit: number;
|
|
total: number;
|
|
}
|
|
|
|
export interface PaginationResult<T> {
|
|
data: T[];
|
|
pagination: {
|
|
page: number;
|
|
limit: number;
|
|
total: number;
|
|
totalPages: number;
|
|
hasNext: boolean;
|
|
hasPrev: boolean;
|
|
};
|
|
}
|
|
|
|
export function usePagination<T>(
|
|
data: T[],
|
|
options: PaginationOptions
|
|
): PaginationResult<T> {
|
|
const { page, limit, total } = options;
|
|
|
|
const paginatedData = useMemo(() => {
|
|
const startIndex = (page - 1) * limit;
|
|
const endIndex = startIndex + limit;
|
|
return data.slice(startIndex, endIndex);
|
|
}, [data, page, limit]);
|
|
|
|
const totalPages = Math.ceil(total / limit);
|
|
const hasNext = page < totalPages;
|
|
const hasPrev = page > 1;
|
|
|
|
return {
|
|
data: paginatedData,
|
|
pagination: {
|
|
page,
|
|
limit,
|
|
total,
|
|
totalPages,
|
|
hasNext,
|
|
hasPrev,
|
|
},
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Хук для бесконечной прокрутки
|
|
*/
|
|
export function useInfiniteScroll<T>(
|
|
data: T[],
|
|
pageSize: number = 20
|
|
): {
|
|
visibleData: T[];
|
|
loadMore: () => void;
|
|
hasMore: boolean;
|
|
reset: () => void;
|
|
} {
|
|
const [visibleCount, setVisibleCount] = useState(pageSize);
|
|
|
|
const visibleData = useMemo(() => {
|
|
return data.slice(0, visibleCount);
|
|
}, [data, visibleCount]);
|
|
|
|
const hasMore = visibleCount < data.length;
|
|
|
|
const loadMore = () => {
|
|
if (hasMore) {
|
|
setVisibleCount((prev) => Math.min(prev + pageSize, data.length));
|
|
}
|
|
};
|
|
|
|
const reset = () => {
|
|
setVisibleCount(pageSize);
|
|
};
|
|
|
|
return {
|
|
visibleData,
|
|
loadMore,
|
|
hasMore,
|
|
reset,
|
|
};
|
|
}
|