diff --git a/app/admin/stock/page.tsx b/app/admin/stock/page.tsx new file mode 100644 index 0000000..e9721a8 --- /dev/null +++ b/app/admin/stock/page.tsx @@ -0,0 +1,45 @@ +/** + * Stock Management Page + * Full page for managing inventory and stock levels + */ + +"use client"; + +import { useAuth } from "@/lib/hooks/useAuth"; +import { useRouter } from "next/navigation"; +import { useEffect } from "react"; +import Navbar from "@/components/NavBar"; +import StockManagementDashboard from "@/components/products/StockManagementDashboard"; + +export default function StockManagementPage() { + const { isAdmin, isLoading } = useAuth(); + const router = useRouter(); + + useEffect(() => { + if (!isLoading && !isAdmin) { + router.push("/dashboard"); + } + }, [isAdmin, isLoading, router]); + + if (isLoading) { + return ( +
+
+
+ ); + } + + if (!isAdmin) { + return null; + } + + return ( +
+ + +
+ +
+
+ ); +} diff --git a/app/products/[id]/page.tsx b/app/products/[id]/page.tsx new file mode 100644 index 0000000..90151a6 --- /dev/null +++ b/app/products/[id]/page.tsx @@ -0,0 +1,162 @@ +"use client"; + +import { useEffect, useMemo, useState } from "react"; +import { useParams } from "next/navigation"; +import Navbar from "@/components/NavBar"; +import { getPublicProductById, recordProductView } from "@/lib/api/products"; +import type { ProductWithDetails, ProductMedia } from "@/types/product"; + +export default function ProductDetailPage() { + const params = useParams<{ id: string }>(); + const id = params?.id; + const [product, setProduct] = useState(null); + const [loading, setLoading] = useState(true); + const [error, setError] = useState(null); + const [activeMediaIndex, setActiveMediaIndex] = useState(0); + + useEffect(() => { + const run = async () => { + if (!id) return; + setLoading(true); + setError(null); + const res = await getPublicProductById(id); + if (res.success && res.data) { + setProduct(res.data); + setActiveMediaIndex(0); + // fire-and-forget view record + recordProductView(id).catch(() => {}); + } else { + setError(res.error || "Failed to load product"); + } + setLoading(false); + }; + run(); + }, [id]); + + const renderMedia = (media: ProductMedia) => { + if (media.mediaType === "video") { + return