"use client"; import { useEffect, useState, useMemo } from "react"; import { useSearchParams } from "next/navigation"; import Link from "next/link"; import Image from "next/image"; interface Entry { id: number; product_make: string; product_model: string; product_price?: string; review_overview_text?: string; bg_entry_sub_cat?: number; bg_entry_cat?: number; index?: { id: string; filename_disk?: string; type?: string; }; header?: { id: string; filename_disk?: string; type?: string; }; } interface SubCategory { id: number; name: string; bg_entry_cat?: number; } interface Category { id: number; name: string; } export default function BuyingGuidePage() { const searchParams = useSearchParams(); const initialQuery = searchParams.get("query") || ""; const [query, setQuery] = useState(initialQuery); const [debouncedQuery, setDebouncedQuery] = useState(initialQuery); const [entries, setEntries] = useState([]); const [categories, setCategories] = useState([]); const [subcategories, setSubcategories] = useState([]); const [selectedCat, setSelectedCat] = useState(""); const [selectedSubCat, setSelectedSubCat] = useState(""); const [loading, setLoading] = useState(true); useEffect(() => { const timer = setTimeout(() => setDebouncedQuery(query), 300); return () => clearTimeout(timer); }, [query]); useEffect(() => { const fetchData = async () => { try { const [entriesRes, catRes, subCatRes] = await Promise.all([ fetch(`${process.env.NEXT_PUBLIC_API_BASE_URL}/items/bg_entries?fields=id,index.id,index.filename_disk,index.type,header.id,header.filename_disk,product_make,product_model,product_price,review_overview_text,bg_entry_cat,bg_entry_sub_cat&limit=-1&sort[]=sort`), fetch(`${process.env.NEXT_PUBLIC_API_BASE_URL}/items/bg_cat?fields=id,name&limit=-1`), fetch(`${process.env.NEXT_PUBLIC_API_BASE_URL}/items/bg_sub_cat?fields=id,name,bg_entry_cat&limit=-1`), ]); const [entriesData, catData, subCatData] = await Promise.all([ entriesRes.json(), catRes.json(), subCatRes.json(), ]); setEntries(entriesData?.data || []); setCategories(catData?.data || []); setSubcategories(subCatData?.data || []); setLoading(false); } catch (err) { console.error("Error fetching data:", err); setLoading(false); } }; fetchData(); }, []); const normalize = (str: string) => str?.toLowerCase().replace(/[_\s]/g, ""); const filtered = useMemo(() => { const q = normalize(debouncedQuery); return entries.filter((entry) => { const catMatch = selectedCat ? entry.bg_entry_cat === parseInt(selectedCat) : true; const subCatMatch = selectedSubCat ? entry.bg_entry_sub_cat === parseInt(selectedSubCat) : true; const searchMatch = q ? [entry.product_make, entry.product_model, entry.review_overview_text].some((field) => normalize(field || "").includes(q) ) : true; return catMatch && subCatMatch && searchMatch; }); }, [entries, debouncedQuery, selectedCat, selectedSubCat]); const filteredSubcategories = useMemo(() => { return selectedCat ? subcategories.filter((sub) => sub.bg_entry_cat === parseInt(selectedCat)) : subcategories; }, [subcategories, selectedCat]); const featuredEntry = useMemo(() => { if (!entries.length) return null; const randomIndex = Math.floor(Math.random() * entries.length); return entries[randomIndex]; }, [entries]); const secondFeaturedEntry = useMemo(() => { if (entries.length < 2) return null; let secondIndex = Math.floor(Math.random() * entries.length); while (entries[secondIndex].id === featuredEntry?.id) { secondIndex = Math.floor(Math.random() * entries.length); } return entries[secondIndex]; }, [entries, featuredEntry]); return (

Buying Guide

setQuery(e.target.value)} placeholder="Search products by make, model, etc..." className="w-full mb-4 dark:bg-background border border-border rounded-md p-2" />

Discover reviewed laser products and accessories.

← Back to Main Menu
{[featuredEntry, secondFeaturedEntry].map((entry, idx) => ( entry && (

Featured Product

{entry.header?.filename_disk ? ( Header image ) : (
No Header
)} {entry.product_make} {entry.product_model} {entry.product_price && (

Starting at {entry.product_price}

)}

{entry.review_overview_text?.slice(0, 140)}...

) ))}

Popular Categories

    {categories.slice(0, 5).map((cat) => (
  • ))}

Recently Added

    {entries.slice(0, 3).map((e) => (
  • {e.product_make} {e.product_model}
  • ))}

What Is This?

This Buying Guide helps you compare laser-related gear with hands-on reviews, scores, and recommendations. Use the filters and search to find what you’re looking for!


{loading ? (

Loading entries...

) : filtered.length === 0 ? (

No entries found.

) : (
{filtered.map((entry) => { const filename = entry.index?.filename_disk; return (
{filename ? ( {`${entry.product_make} ) : (
No Image
)}

{entry.product_make}

{entry.product_model} {entry.product_price !== undefined && (

Starting at {entry.product_price}

)}

{entry.review_overview_text?.slice(0, 120)}...

); })}
)}
); }