-
+
Failed to Load Products
@@ -175,13 +171,13 @@ const Products: React.FC = ({
return (
-
+
{title}
-
+
-
+
No Products Found
@@ -196,12 +192,12 @@ const Products: React.FC = ({
return (
-
+
{title}
{/* Products Grid */}
-
+
{products.map((product) => (
= ({
>
{loadingMore ? (
-
+
Loading...
) : (
diff --git a/components/shopify/promo-banner.tsx b/components/shopify/promo-banner.tsx
new file mode 100644
index 0000000..57729c1
--- /dev/null
+++ b/components/shopify/promo-banner.tsx
@@ -0,0 +1,55 @@
+'use client';
+
+import React from 'react';
+import Link from 'next/link';
+import { RiArrowLeftSLine, RiArrowRightSLine } from '@remixicon/react';
+import {
+ Carousel,
+ CarouselContent,
+ CarouselItem,
+ CarouselPrevious,
+ CarouselNext,
+} from '@/components/ui/carousel';
+
+const PROMOS = [
+ { text: 'Send a Gift Card', href: '/' },
+ { text: 'Free shipping on orders over $100', href: '/' },
+ { text: '30-day return policy', href: '/' },
+];
+
+const PromoBanner: React.FC = () => {
+ return (
+
+
+
+ {PROMOS.map((promo) => (
+
+
+
+ {promo.text}
+
+
+
+ ))}
+
+
+
+
+
+
+
+
+
+ );
+};
+
+export default PromoBanner;
diff --git a/components/shopify/search-dialog.tsx b/components/shopify/search-dialog.tsx
new file mode 100644
index 0000000..8ebba67
--- /dev/null
+++ b/components/shopify/search-dialog.tsx
@@ -0,0 +1,114 @@
+'use client';
+
+import React, { useEffect, useState } from 'react';
+import { useRouter } from 'next/navigation';
+import { Command } from 'cmdk';
+import { RiSearchLine } from '@remixicon/react';
+import { Dialog, DialogContent, DialogTitle } from '@/components/ui/dialog';
+import { Loader } from '@/components/ui/loader';
+import { getProducts, type Product } from '@/hooks/use-shopify-products';
+
+interface SearchDialogProps {
+ open: boolean;
+ onOpenChange: (open: boolean) => void;
+}
+
+const SearchDialog: React.FC = ({ open, onOpenChange }) => {
+ const router = useRouter();
+ const [products, setProducts] = useState([]);
+ const [loading, setLoading] = useState(false);
+ const [query, setQuery] = useState('');
+
+ // Load the catalog once per open; cmdk filters it as the user types
+ useEffect(() => {
+ if (!open) {
+ setQuery('');
+ return;
+ }
+
+ let cancelled = false;
+ setLoading(true);
+ getProducts({ first: 100, sortKey: 'TITLE' })
+ .then((data) => {
+ if (!cancelled) setProducts(data);
+ })
+ .catch((err) => {
+ console.error('Failed to load products for search:', err);
+ })
+ .finally(() => {
+ if (!cancelled) setLoading(false);
+ });
+
+ return () => {
+ cancelled = true;
+ };
+ }, [open]);
+
+ const handleSelect = (handle: string) => {
+ onOpenChange(false);
+ router.push(`/products/${handle}`);
+ };
+
+ return (
+
+ );
+};
+
+export default SearchDialog;
diff --git a/components/shopify/shop-footer.tsx b/components/shopify/shop-footer.tsx
index 452ff07..dc848f8 100644
--- a/components/shopify/shop-footer.tsx
+++ b/components/shopify/shop-footer.tsx
@@ -2,20 +2,12 @@ import React from 'react';
const Footer: React.FC = () => {
return (
-