Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 5 additions & 7 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
FROM node:20-alpine AS deps
RUN corepack enable && corepack prepare pnpm@9 --activate
FROM oven/bun:1-alpine AS deps
WORKDIR /app

COPY package.json pnpm-lock.yaml ./
COPY package.json bun.lock ./

RUN pnpm install --frozen-lockfile
RUN bun install --frozen-lockfile

FROM node:20-alpine AS builder
RUN corepack enable && corepack prepare pnpm@9 --activate
FROM oven/bun:1-alpine AS builder
WORKDIR /app

COPY --from=deps /app/node_modules ./node_modules
Expand All @@ -16,7 +14,7 @@ COPY . .

ENV NEXT_TELEMETRY_DISABLED=1
ENV DOCKER_BUILD=true
RUN pnpm build
RUN bun run build

FROM node:20-alpine AS runner
WORKDIR /app
Expand Down
6 changes: 6 additions & 0 deletions app/_components/web-vitals.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
"use client";
import { useReportWebVitals } from "next/web-vitals";
import { logWebVitals } from "@/lib/utils";
export function WebVitals() {
useReportWebVitals(logWebVitals);
}
2 changes: 2 additions & 0 deletions app/accessories/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,13 @@ import { products } from "@/data/products";
import { Home } from "lucide-react";
import Link from "next/link";
import { motion } from "framer-motion";
import { WebVitals } from "../_components/web-vitals";

/**
* Accessories page displaying all accessory products
*/
export default function AccessoriesPage() {
WebVitals();
const accessoriesProducts = products.filter(
(p) => p.category === "accessories",
);
Expand Down
2 changes: 2 additions & 0 deletions app/cart/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import { Button } from "@/components/ui/button";
import { useCartStore } from "@/lib/cart-store";
import Link from "next/link";
import { ShoppingBag, Home } from "lucide-react";
import { WebVitals } from "../_components/web-vitals";

/**
* Render the shopping cart page with either an empty-cart view or a populated cart and order summary.
Expand All @@ -29,6 +30,7 @@ import { ShoppingBag, Home } from "lucide-react";
* @returns The cart page JSX element that reflects the current cart state (empty or populated).
*/
export default function CartPage() {
WebVitals();
const { items, summary } = useCartStore();

if (items.length === 0) {
Expand Down
2 changes: 2 additions & 0 deletions app/checkout/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,15 @@ import { generateOrderNumber } from "@/lib/utils";
import { useEffect, useState } from "react";
import Link from "next/link";
import { Home } from "lucide-react";
import { WebVitals } from "../_components/web-vitals";

/**
* Renders the checkout page with an order summary and payment summary, handles client-side-only rendering and navigation for empty carts, and provides a "Place Order" action that clears the cart and navigates to a success page.
*
* @returns The checkout page JSX including the list of cart items, a payment summary (subtotal, shipping, tax, total), and a "Place Order" button that finalizes the order and redirects to the success screen.
*/
export default function CheckoutPage() {
WebVitals();
const { items, summary, clearCart } = useCartStore();
const router = useRouter();
const [isClient, setIsClient] = useState(false);
Expand Down
3 changes: 3 additions & 0 deletions app/checkout/success/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { CheckCircle } from "lucide-react";
import { useSearchParams } from "next/navigation";
import { motion } from "framer-motion";
import { Suspense } from "react";
import { WebVitals } from "@/app/_components/web-vitals";

/**
* Render the order confirmation UI that displays the order number from the URL and provides navigation actions.
Expand All @@ -20,6 +21,8 @@ import { Suspense } from "react";
* @returns The React element for the order confirmation page.
*/
function OrderSuccessContent() {
WebVitals();

const searchParams = useSearchParams();
const orderNumber = searchParams.get("order") || "N/A";

Expand Down
2 changes: 2 additions & 0 deletions app/error.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { Container } from "@/components/layout/container";
import { Section } from "@/components/layout/section";
import { Button } from "@/components/ui/button";
import { AlertTriangle } from "lucide-react";
import { WebVitals } from "./_components/web-vitals";

/**
* Renders a centered error screen with an alert icon, message, and retry button.
Expand All @@ -22,6 +23,7 @@ export default function ErrorPage({
error: Error & { digest?: string };
reset: () => void;
}) {
WebVitals();
useEffect(() => {
console.error(error);
}, [error]);
Expand Down
2 changes: 2 additions & 0 deletions app/gifts/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,13 @@ import { products } from "@/data/products";
import { Home } from "lucide-react";
import Link from "next/link";
import { motion } from "framer-motion";
import { WebVitals } from "../_components/web-vitals";

/**
* Gifts page displaying curated gift products
*/
export default function GiftsPage() {
WebVitals();
const giftProducts = products.filter((p) => p.category === "gifts");

return (
Expand Down
2 changes: 1 addition & 1 deletion app/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -38,4 +38,4 @@ export default function RootLayout({
</body>
</html>
);
}
}
3 changes: 3 additions & 0 deletions app/men/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,14 @@ import { products } from "@/data/products";
import { Home } from "lucide-react";
import Link from "next/link";
import { motion } from "framer-motion";
import { WebVitals } from "../_components/web-vitals";

/**
* Men's collection page displaying all men's clothing products
*/
export default function MenPage() {
WebVitals();

const menProducts = products.filter(
(p) =>
p.category === "apparel" && (p.gender === "men" || p.gender === "unisex"),
Expand Down
2 changes: 2 additions & 0 deletions app/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,10 @@ import { HeroSection } from "@/components/home/hero-section";
import { CategoriesSection } from "@/components/home/categories-section";
import { NewsletterSection } from "@/components/home/newsletter-section";
import { products } from "@/data/products";
import { WebVitals } from "./_components/web-vitals";

export default function HomePage() {
WebVitals();
const newArrivals = products
.filter((p) => p.tags.includes("new"))
.slice(0, 8);
Expand Down
2 changes: 2 additions & 0 deletions app/products/[slug]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import { ShoppingCart, Check, Home } from "lucide-react";
import { toast } from "sonner";
import { motion } from "framer-motion";
import Link from "next/link";
import { WebVitals } from "@/app/_components/web-vitals";

interface ProductPageProps {
params: Promise<{ slug: string }>;
Expand All @@ -40,6 +41,7 @@ interface ProductPageProps {
* @returns The JSX element for the product detail page
*/
export default function ProductPage({ params }: ProductPageProps) {
WebVitals();
const { slug } = use(params);
const product = products.find((p) => p.slug === slug);

Expand Down
2 changes: 2 additions & 0 deletions app/products/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import { Filter, Home } from "lucide-react";
import { Button } from "@/components/ui/button";
import { useSearchParams } from "next/navigation";
import Link from "next/link";
import { WebVitals } from "../_components/web-vitals";

/**
* Renders the products listing content including search, sorting, filters, and the product grid.
Expand All @@ -33,6 +34,7 @@ import Link from "next/link";
* @returns The JSX element containing the products page content, including filter controls, product count summary, and the product grid.
*/
function ProductsContent() {
WebVitals();
const searchParams = useSearchParams();
const initialCategory = searchParams.get("category") || "";
const initialTag = searchParams.get("tag") || "";
Expand Down
2 changes: 2 additions & 0 deletions app/women/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,13 @@ import { products } from "@/data/products";
import { Home } from "lucide-react";
import Link from "next/link";
import { motion } from "framer-motion";
import { WebVitals } from "../_components/web-vitals";

/**
* Women's collection page displaying all women's clothing products
*/
export default function WomenPage() {
WebVitals();
const womenProducts = products.filter(
(p) =>
p.category === "apparel" &&
Expand Down
Loading