from-to search route
This commit is contained in:
@@ -1,7 +1,54 @@
|
||||
import React from 'react'
|
||||
import Image from 'next/image'
|
||||
import { getNews } from '@/lib/main/fetchNews'
|
||||
import { notFound } from 'next/navigation'
|
||||
|
||||
const page = () => {
|
||||
return <div>page</div>
|
||||
interface PageProps {
|
||||
params: Promise<{
|
||||
slug: string
|
||||
}>
|
||||
}
|
||||
|
||||
export default page
|
||||
async function getNewsItem(slug: string) {
|
||||
const news = await getNews()
|
||||
return news.find(item => item.slug === slug)
|
||||
}
|
||||
|
||||
export default async function NewsPage({ params }: PageProps) {
|
||||
const { slug } = await params
|
||||
const newsItem = await getNewsItem(slug)
|
||||
|
||||
if (!newsItem) {
|
||||
notFound()
|
||||
}
|
||||
|
||||
return (
|
||||
<article className="mx-auto max-w-5xl px-4 py-8">
|
||||
<div className="w-full overflow-hidden rounded-2xl bg-white shadow-lg">
|
||||
<div className="relative h-[400px] w-full">
|
||||
<Image
|
||||
src={
|
||||
newsItem.titleImage.startsWith('http')
|
||||
? newsItem.titleImage
|
||||
: `http://127.0.0.1:8000${newsItem.titleImage}` || '/placeholder-image.jpg'
|
||||
}
|
||||
alt={newsItem.title}
|
||||
fill
|
||||
className="object-cover"
|
||||
priority
|
||||
sizes="(max-width: 1280px) 100vw, 1280px"
|
||||
/>
|
||||
<div className="absolute inset-0 flex items-center justify-center bg-black/40">
|
||||
<h1 className="px-4 text-center text-4xl font-bold text-white md:text-5xl">
|
||||
{newsItem.title}
|
||||
</h1>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="prose prose-lg mt-8 max-w-none">
|
||||
<div className="whitespace-pre-wrap">{newsItem.content}</div>
|
||||
</div>
|
||||
</article>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import React, { Suspense } from 'react'
|
||||
import type { Metadata } from 'next'
|
||||
import SearchCard from '../../components/SearchCard'
|
||||
import { SearchCardProps } from '@/app/types'
|
||||
|
||||
interface SearchPageProps {
|
||||
params: {
|
||||
@@ -8,10 +10,59 @@ interface SearchPageProps {
|
||||
}
|
||||
}
|
||||
|
||||
// дернуть search api для from-to параметров
|
||||
async function fetchSearch(category: string, from: string, to: string) {
|
||||
// get search api(owner_type, from, to)
|
||||
return []
|
||||
const response = await fetch(
|
||||
`${process.env.NEXT_PUBLIC_API_URL}/search/${category}/?from=${encodeURIComponent(from)}&to=${encodeURIComponent(to)}`,
|
||||
{
|
||||
cache: 'no-store',
|
||||
}
|
||||
)
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error('Failed to fetch search results')
|
||||
}
|
||||
|
||||
const data = await response.json()
|
||||
return {
|
||||
results: data.results,
|
||||
count: data.results.length,
|
||||
}
|
||||
}
|
||||
|
||||
export async function generateMetadata({
|
||||
params,
|
||||
}: {
|
||||
params: SearchPageProps['params']
|
||||
}): Promise<Metadata> {
|
||||
const [fromCity, toCity] = params.route.split('-')
|
||||
|
||||
return {
|
||||
title: `Поиск ${params.category === 'mover' ? 'перевозчика' : 'посылки'} ${fromCity} → ${toCity} | Tripwb`,
|
||||
description: `Найдите ${params.category === 'mover' ? 'перевозчика' : 'посылку'} по маршруту ${fromCity} → ${toCity} | Tripwb`,
|
||||
openGraph: {
|
||||
title: `Поиск ${params.category === 'mover' ? 'перевозчика' : 'посылки'} ${fromCity} → ${toCity} | Tripwb`,
|
||||
description: `Найдите ${params.category === 'mover' ? 'перевозчика' : 'посылку'} по маршруту ${fromCity} → ${toCity}`,
|
||||
url: `https://tripwb.com/search/${params.category}/${params.route}`,
|
||||
siteName: 'TripWB',
|
||||
images: [
|
||||
{
|
||||
url: 'https://i.ibb.co/gmqzzmb/header-logo-mod-1200x630.png',
|
||||
width: 1200,
|
||||
height: 630,
|
||||
alt: 'Tripwb - поиск перевозчиков и посылок',
|
||||
},
|
||||
],
|
||||
locale: 'ru_RU',
|
||||
type: 'website',
|
||||
},
|
||||
alternates: {
|
||||
canonical: `https://tripwb.com/search/${params.category}/${params.route}`,
|
||||
},
|
||||
robots: {
|
||||
index: true,
|
||||
follow: true,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
export default async function SearchPage(props: SearchPageProps) {
|
||||
@@ -19,7 +70,7 @@ export default async function SearchPage(props: SearchPageProps) {
|
||||
const { category, route } = params
|
||||
const [fromCity, toCity] = route.split('-')
|
||||
|
||||
const initialData = await fetchSearch(category, fromCity, toCity)
|
||||
const { results, count } = await fetchSearch(category, fromCity, toCity)
|
||||
|
||||
return (
|
||||
<div className="container mx-auto p-4">
|
||||
@@ -33,14 +84,12 @@ export default async function SearchPage(props: SearchPageProps) {
|
||||
</div>
|
||||
|
||||
<Suspense fallback={<div>Загрузка результатов...</div>}>
|
||||
{/* результаты поиска */}
|
||||
<div className="space-y-4">
|
||||
{initialData.map((item: any, index: number) => (
|
||||
<div key={index} className="rounded-lg border p-4">
|
||||
{/* Здесь будет карточка с результатом */}
|
||||
<p>Результат поиска {index + 1}</p>
|
||||
</div>
|
||||
))}
|
||||
{results.length > 0 ? (
|
||||
results.map((item: SearchCardProps) => <SearchCard key={item.id} {...item} />)
|
||||
) : (
|
||||
<div className="text-center text-gray-500">По данному маршруту ничего не найдено</div>
|
||||
)}
|
||||
</div>
|
||||
</Suspense>
|
||||
</div>
|
||||
|
||||
@@ -108,12 +108,14 @@ const SearchCard = ({
|
||||
onClick={handleLeadClick}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="rounded-lg bg-[#f8f8f8] p-5">
|
||||
<div className="flex items-baseline gap-2">
|
||||
<span className="text-gray-600">{comment}</span>
|
||||
{comment && (
|
||||
<div className="rounded-lg bg-[#f8f8f8] p-5">
|
||||
<div className="flex items-baseline gap-2">
|
||||
<span className="text-gray-600">{comment}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div className="flex justify-end pt-2 text-sm text-gray-500">Объявление № {id}</div>
|
||||
|
||||
<div className="mt-6 flex items-center justify-between">
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 25 KiB After Width: | Height: | Size: 4.2 KiB |
@@ -70,6 +70,8 @@ export interface NewsItem {
|
||||
content: string
|
||||
titleImage: string
|
||||
slug: string
|
||||
path: string
|
||||
filename: string
|
||||
}
|
||||
|
||||
export interface NewsProps {
|
||||
|
||||
@@ -13,7 +13,7 @@ const nextConfig: NextConfig = {
|
||||
protocol: 'http', // для локал девеломпента
|
||||
hostname: '127.0.0.1',
|
||||
port: '8000',
|
||||
pathname: '/media/uploads/**',
|
||||
pathname: '/media/**',
|
||||
},
|
||||
{
|
||||
protocol: 'https',
|
||||
|
||||
Reference in New Issue
Block a user