153 lines
4.5 KiB
TypeScript
153 lines
4.5 KiB
TypeScript
'use client'
|
||
|
||
import React, { useState, useMemo } from 'react'
|
||
import SearchCard from './SearchCard'
|
||
import { SearchCardProps } from '@/app/types'
|
||
import SearchFilters from './SearchFilters'
|
||
import { fetchRoutes } from '@/lib/search/fetchRoutes'
|
||
import { usePathname, useSearchParams } from 'next/navigation'
|
||
import Pagination from './Pagination'
|
||
|
||
interface ClientResultsProps {
|
||
initialResults: SearchCardProps[]
|
||
initialCount?: number
|
||
initialNext?: string | null
|
||
initialPrevious?: string | null
|
||
}
|
||
|
||
export default function ClientResults({
|
||
initialResults,
|
||
initialCount = 0,
|
||
initialNext = null,
|
||
initialPrevious = null,
|
||
}: ClientResultsProps) {
|
||
const [selectedTransport, setSelectedTransport] = useState<number[]>([])
|
||
const [selectedPackageTypes, setSelectedPackageTypes] = useState<number[]>([])
|
||
const [results, setResults] = useState(initialResults)
|
||
const [isLoading, setIsLoading] = useState(false)
|
||
const [currentPage, setCurrentPage] = useState(1)
|
||
const [hasNext, setHasNext] = useState(!!initialNext)
|
||
const [hasPrevious, setHasPrevious] = useState(!!initialPrevious)
|
||
const [totalCount, setTotalCount] = useState(initialCount)
|
||
|
||
const pathname = usePathname()
|
||
const searchParams = useSearchParams()
|
||
|
||
const filteredResults = useMemo(() => {
|
||
let filtered = [...results]
|
||
|
||
if (selectedTransport.length > 0) {
|
||
filtered = filtered.filter(item =>
|
||
selectedTransport.some(id => {
|
||
switch (id) {
|
||
case 1:
|
||
return item.type_transport === 'road'
|
||
case 2:
|
||
return item.type_transport === 'avia'
|
||
case 3:
|
||
return true // 'both' отдает все
|
||
default:
|
||
return false
|
||
}
|
||
})
|
||
)
|
||
}
|
||
|
||
if (selectedPackageTypes.length > 0) {
|
||
filtered = filtered.filter(item => {
|
||
return selectedPackageTypes.some(id => {
|
||
const match = (() => {
|
||
switch (id) {
|
||
case 1:
|
||
return item.formatted_cargo_type === 'Письмо или Документы'
|
||
case 2:
|
||
return item.formatted_cargo_type === 'Посылка (до 30кг)'
|
||
case 3:
|
||
return item.formatted_cargo_type === 'Попутчик'
|
||
case 4:
|
||
return item.formatted_cargo_type === 'Бандероль (до 5кг)'
|
||
case 5:
|
||
return item.formatted_cargo_type === 'Груз (свыше 30 кг)'
|
||
default:
|
||
return false
|
||
}
|
||
})()
|
||
|
||
return match
|
||
})
|
||
})
|
||
}
|
||
|
||
return filtered
|
||
}, [results, selectedTransport, selectedPackageTypes])
|
||
|
||
const handleFiltersChange = ({
|
||
transport,
|
||
packageTypes,
|
||
}: {
|
||
transport: number[]
|
||
packageTypes: number[]
|
||
}) => {
|
||
setSelectedTransport(transport)
|
||
setSelectedPackageTypes(packageTypes)
|
||
}
|
||
|
||
const handlePageChange = async (newPage: number) => {
|
||
setIsLoading(true)
|
||
try {
|
||
const category = pathname.split('/')[2] // получаем категорию из URL
|
||
const params = new URLSearchParams(searchParams.toString())
|
||
const {
|
||
results: newResults,
|
||
next,
|
||
previous,
|
||
count,
|
||
} = await fetchRoutes(category, params.toString(), newPage)
|
||
setResults(newResults)
|
||
setCurrentPage(newPage)
|
||
setHasNext(!!next)
|
||
setHasPrevious(!!previous)
|
||
setTotalCount(count)
|
||
} catch (error) {
|
||
console.error('Error fetching page:', error)
|
||
} finally {
|
||
setIsLoading(false)
|
||
}
|
||
}
|
||
|
||
const totalPages = Math.ceil(totalCount / 10) // 10 - размер страницы
|
||
|
||
return (
|
||
<div className="space-y-6">
|
||
<SearchFilters onFiltersChange={handleFiltersChange} />
|
||
|
||
{isLoading ? (
|
||
<div className="flex justify-center">
|
||
<div className="h-8 w-8 animate-spin rounded-full border-b-2 border-gray-900"></div>
|
||
</div>
|
||
) : (
|
||
<>
|
||
<div className="grid gap-4">
|
||
{filteredResults.map(result => (
|
||
<SearchCard key={result.id} {...result} />
|
||
))}
|
||
</div>
|
||
|
||
<Pagination
|
||
currentPage={currentPage}
|
||
totalPages={totalPages}
|
||
hasNext={hasNext}
|
||
hasPrevious={hasPrevious}
|
||
isLoading={isLoading}
|
||
onPageChange={handlePageChange}
|
||
/>
|
||
|
||
{filteredResults.length === 0 && (
|
||
<div className="text-center text-gray-500">Результаты не найдены</div>
|
||
)}
|
||
</>
|
||
)}
|
||
</div>
|
||
)
|
||
}
|