feat: optymalizacja GlobalSearch, nawigacji oraz filtrów w sklepie

This commit is contained in:
MichalC
2026-06-27 21:12:23 +02:00
parent 0c59086a6b
commit c4294a81cf
43 changed files with 1623 additions and 192 deletions
+36 -7
View File
@@ -1,20 +1,40 @@
"use client";
import { useState, useRef, useEffect } from "react";
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 products = getProducts();
const results = query.length > 1
? products.filter(p => p.name.toLowerCase().includes(query.toLowerCase()) || p.brand.toLowerCase().includes(query.toLowerCase()) || p.category.toLowerCase().includes(query.toLowerCase()))
: [];
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 (
<>
@@ -29,7 +49,15 @@ export function GlobalSearch() {
<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">
<Search className="size-5 text-accent mr-3 shrink-0" />
<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"
@@ -37,8 +65,9 @@ export function GlobalSearch() {
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 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">
<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>