feat: optymalizacja GlobalSearch, nawigacji oraz filtrów w sklepie
This commit is contained in:
@@ -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>
|
||||
|
||||
Reference in New Issue
Block a user