-
- {filteredResults.length > 0 ? (
- filteredResults.map((item: SearchCardProps) =>
)
- ) : (
-
- По выбранным фильтрам ничего не найдено. Попробуйте изменить параметры поиска.
+ {isLoading ? (
+
+ ) : (
+ <>
+
+ {filteredResults.map(result => (
+
+ ))}
- )}
-
- >
+
+
+
+ {filteredResults.length === 0 && (
+
Результаты не найдены
+ )}
+ >
+ )}
+
)
}
diff --git a/frontend/app/(urls)/search/components/Pagination.tsx b/frontend/app/(urls)/search/components/Pagination.tsx
new file mode 100644
index 0000000..895c4b3
--- /dev/null
+++ b/frontend/app/(urls)/search/components/Pagination.tsx
@@ -0,0 +1,91 @@
+'use client'
+
+import React from 'react'
+
+interface PaginationProps {
+ currentPage: number
+ totalPages: number
+ hasNext: boolean
+ hasPrevious: boolean
+ isLoading: boolean
+ onPageChange: (page: number) => void
+}
+
+export default function Pagination({
+ currentPage,
+ totalPages,
+ isLoading,
+ onPageChange,
+}: PaginationProps) {
+ if (totalPages <= 1) return null
+
+ const renderPageNumbers = () => {
+ const pages = []
+ const maxVisiblePages = 5 // максимальное количество видимых страниц
+
+ // создаем кнопки страницы
+ const createPageButton = (pageNum: number) => (
+
+ )
+
+ // всегда показываем первую страницу
+ pages.push(createPageButton(1))
+
+ if (totalPages <= maxVisiblePages) {
+ // если страниц мало, показываем все
+ for (let i = 2; i <= totalPages; i++) {
+ pages.push(createPageButton(i))
+ }
+ } else {
+ // если страниц много, показываем с многоточием
+ if (currentPage > 3) {
+ pages.push(
+
+ ...
+
+ )
+ }
+
+ // показываем страницы вокруг текущей
+ for (
+ let i = Math.max(2, currentPage - 1);
+ i <= Math.min(totalPages - 1, currentPage + 1);
+ i++
+ ) {
+ pages.push(createPageButton(i))
+ }
+
+ if (currentPage < totalPages - 2) {
+ pages.push(
+
+ ...
+
+ )
+ }
+
+ // всегда показываем последнюю страницу
+ if (totalPages > 1) {
+ pages.push(createPageButton(totalPages))
+ }
+ }
+
+ return pages
+ }
+
+ return (
+
+
{renderPageNumbers()}
+
+ )
+}
diff --git a/frontend/app/types/index.ts b/frontend/app/types/index.ts
index b3f94b6..47686ea 100644
--- a/frontend/app/types/index.ts
+++ b/frontend/app/types/index.ts
@@ -235,6 +235,8 @@ export interface PricingCardProps {
export interface SearchResponse {
count: number
results: SearchCardProps[]
+ next: string | null
+ previous: string | null
}
export interface SearchPageProps {
diff --git a/frontend/components/forms/RouteForm.tsx b/frontend/components/forms/RouteForm.tsx
index 18b212c..0f6c733 100644
--- a/frontend/components/forms/RouteForm.tsx
+++ b/frontend/components/forms/RouteForm.tsx
@@ -80,7 +80,7 @@ const RouteForm: React.FC
= ({
arrival: '',
phone_number: user?.phone_number || '',
comment: '',
- email_notification: false,
+ email_notification: true,
}
const cargoOptions: SelectOption[] = cargo_types.map((type, index) => ({
diff --git a/frontend/lib/search/fetchRoutes.ts b/frontend/lib/search/fetchRoutes.ts
index 903f60e..eedca21 100644
--- a/frontend/lib/search/fetchRoutes.ts
+++ b/frontend/lib/search/fetchRoutes.ts
@@ -1,10 +1,15 @@
import { SearchResponse } from '@/app/types'
// получаем все предложения по выбранному owner_type
-export async function fetchRoutes(category: string, query: string = ''): Promise {
+export async function fetchRoutes(
+ category: string,
+ query: string = '',
+ page: number = 1
+): Promise {
try {
+ const pageParam = page > 1 ? `${query ? '&' : '?'}page=${page}` : ''
const response = await fetch(
- `${process.env.NEXT_PUBLIC_API_URL}/search/${category}/${query ? `?${query}` : ''}`,
+ `${process.env.NEXT_PUBLIC_API_URL}/search/${category}/${query}${pageParam}`,
{
cache: 'no-store',
}
@@ -15,9 +20,14 @@ export async function fetchRoutes(category: string, query: string = ''): Promise
}
const data = await response.json()
- return data
+ return {
+ results: data.results,
+ count: data.count,
+ next: data.next,
+ previous: data.previous,
+ }
} catch (error) {
console.error('Error fetching search results:', error)
- return { results: [], count: 0 }
+ return { results: [], count: 0, next: null, previous: null }
}
}