Files
Zbrane-Reiner-Web/src/app/(frontend)/nabidka/[slug]/page.tsx
T
Honza 87c8f27e73
CI / test (push) Successful in 1m12s
CI / build-and-push (push) Successful in 2m53s
Add category level and turn the reticle into a background watermark
2026-08-02 19:15:20 +02:00

111 lines
3.1 KiB
TypeScript

import Image from 'next/image'
import Link from 'next/link'
import { notFound } from 'next/navigation'
import { getPayload } from 'payload'
import React from 'react'
import config from '@/payload.config'
import type { Media, Product } from '@/payload-types'
import { cestaKSouboru, formatujCenu, popisStavu } from '@/lib/format'
import '../../styles.css'
export const dynamic = 'force-dynamic'
type Props = { params: Promise<{ slug: string }> }
export async function generateMetadata({ params }: Props) {
const polozka = await najdiPolozku((await params).slug)
if (!polozka) return { title: 'Položka nenalezena' }
return {
title: `${polozka.nazev} — Reiner zbraně`,
description: polozka.popis ?? undefined,
}
}
export default async function DetailPolozky({ params }: Props) {
const polozka = await najdiPolozku((await params).slug)
if (!polozka) notFound()
const obrazky = (polozka.obrazky ?? [])
.map((radek) => radek.obrazek)
.filter((o): o is Media => typeof o === 'object' && o !== null)
return (
<article className="stranka detail">
<p className="zpet">
{typeof polozka.kategorie === 'object' && polozka.kategorie !== null ? (
<Link href={`/kategorie/${polozka.kategorie.slug}`}>
Zpět na {polozka.kategorie.nazev}
</Link>
) : (
<Link href="/"> Zpět na nabídku</Link>
)}
</p>
<h1>{polozka.nazev}</h1>
<p className="detail__cena">
{formatujCenu(polozka.cena)}
<span className={`znacka-stavu znacka-stavu--${polozka.stav}`}>
{popisStavu(polozka.stav)}
</span>
</p>
{obrazky.length > 0 && (
<div className="galerie">
{obrazky.map((obrazek) => {
const varianta = obrazek.sizes?.detail
const url = varianta?.url ?? obrazek.url
const width = varianta?.width ?? obrazek.width
const height = varianta?.height ?? obrazek.height
if (!url || !width || !height) return null
return (
<Image
key={obrazek.id}
alt={obrazek.alt ?? polozka.nazev}
src={cestaKSouboru(url)}
width={width}
height={height}
sizes="(max-width: 900px) 100vw, 800px"
/>
)
})}
</div>
)}
{polozka.parametry && polozka.parametry.length > 0 && (
<table className="parametry">
<tbody>
{polozka.parametry.map((parametr) => (
<tr key={parametr.id}>
<th scope="row">{parametr.nazev}</th>
<td>{parametr.hodnota}</td>
</tr>
))}
</tbody>
</table>
)}
{polozka.popis && <div className="popis">{polozka.popis}</div>}
</article>
)
}
async function najdiPolozku(slug: string): Promise<Product | null> {
const payload = await getPayload({ config: await config })
const { docs } = await payload.find({
collection: 'products',
where: {
slug: { equals: slug },
skryto: { not_equals: true },
},
depth: 1,
limit: 1,
})
return docs[0] ?? null
}