Files
thermcool/components/layout/GlobalSearch.tsx
T

124 lines
5.2 KiB
TypeScript

"use client";
import { useState, useRef, useEffect, useMemo } from "react";
import { Search } from "lucide-react";
import { getProducts } from "@/content/products";
import Link from "next/link";
import Image from "next/image";
import { formatCurrency } from "@/lib/utils";
import { useRouter } from "next/navigation";
const allProducts = getProducts();
export function GlobalSearch() {
const [query, setQuery] = useState("");
const [isOpen, setIsOpen] = useState(false);
const router = useRouter();
const results = useMemo(() => {
if (query.length < 2) return [];
const q = query.toLowerCase();
return allProducts
.filter(p =>
p.name.toLowerCase().includes(q) ||
p.brand.toLowerCase().includes(q) ||
p.category.toLowerCase().includes(q) ||
(p.sku && p.sku.toLowerCase().includes(q))
)
.slice(0, 20);
}, [query]);
const handleKeyDown = (e: React.KeyboardEvent) => {
if (e.key === 'Enter' && query.length > 1) {
router.push(`/sklep?search=${encodeURIComponent(query)}`);
setIsOpen(false);
setQuery('');
}
};
return (
<>
<button
onClick={() => setIsOpen(true)}
className="p-2 text-primary hover:text-accent hover:bg-background rounded-lg transition-colors outline-none cursor-pointer"
aria-label="Szukaj na stronie"
>
<Search className="size-5" />
</button>
<dialog className={`modal ${isOpen ? "modal-open" : ""}`}>
<div className="modal-box p-0 max-w-2xl bg-white rounded-2xl overflow-hidden mt-[-20vh]">
<div className="flex items-center border-b border-border px-4 py-3 bg-slate-50">
<button aria-label="Szukaj" onClick={() => {
if (query.length > 1) {
router.push(`/sklep?search=${encodeURIComponent(query)}`);
setIsOpen(false);
setQuery('');
}
}}>
<Search className="size-5 text-accent mr-3 shrink-0 hover:text-primary transition-colors cursor-pointer" />
</button>
<input
autoFocus
type="text"
placeholder="Wpisz nazwę klimatyzatora (np. Rotenso, Pular)..."
className="flex-1 outline-none text-base placeholder:text-text-muted/50 bg-transparent py-2 text-primary font-medium"
value={query}
onChange={(e) => setQuery(e.target.value)}
onKeyDown={handleKeyDown}
/>
<button type="button" onClick={() => setIsOpen(false)} className="text-xs font-semibold text-text-muted hover:text-primary transition-colors bg-white px-2 py-1 rounded border border-border shadow-sm">
ESC
</button>
</div>
{query.length > 1 ? (
<div className="max-h-[60vh] overflow-y-auto p-2 bg-white">
{results.length > 0 ? (
<div className="flex flex-col gap-1">
{results.map((product) => (
<Link
key={product.slug}
href={`/sklep/${product.slug}`}
onClick={() => setIsOpen(false)}
className="flex items-center gap-4 p-3 hover:bg-slate-50 rounded-lg transition-colors group border border-transparent hover:border-border"
>
<div className="w-16 h-16 bg-white border border-border rounded-md overflow-hidden relative shrink-0">
<Image
src={product.image || 'https://images.unsplash.com/photo-1621905251189-08b45d6a269e?w=800&q=80'}
alt={product.name}
fill
className="object-contain p-1 mix-blend-multiply"
/>
</div>
<div className="flex-1 flex flex-col">
<span className="text-[10px] font-bold text-text-muted uppercase tracking-wider">{product.brand}</span>
<span className="text-sm font-semibold text-primary group-hover:text-accent transition-colors">{product.name}</span>
<span className="text-xs text-text-muted mt-0.5">{product.specs?.['Moc chłodnicza'] ? `${product.specs['Moc chłodnicza']} kW • ` : ''}{product.category}</span>
</div>
<div className="text-right">
<span className="text-sm font-bold text-primary block">{product.price !== null ? formatCurrency(product.price) : 'Zapytaj o cenę'}</span>
</div>
</Link>
))}
</div>
) : (
<div className="p-8 text-center text-text-muted">
Brak wyników dla <span className="font-semibold">"{query}"</span>
</div>
)}
</div>
) : (
<div className="p-8 text-center text-text-muted/50 text-sm bg-white">
Wpisz co najmniej 2 znaki, aby rozpocząć wyszukiwanie w sklepie
</div>
)}
</div>
<form method="dialog" className="modal-backdrop">
<button onClick={() => setIsOpen(false)}>close</button>
</form>
</dialog>
</>
);
}