aboutsummaryrefslogtreecommitdiffstats

Frontend Component Structure

This document outlines the component structure for the e-commerce frontend, inspired by turntupfashion.com.

Core Components

Layout Components

  • Layout.jsx - Main layout wrapper with header and footer
  • Header.jsx - Site header with navigation, search, and cart
  • Footer.jsx - Site footer with links and newsletter signup
  • MobileMenu.jsx - Responsive navigation for mobile devices
  • Breadcrumbs.jsx - Navigation breadcrumbs component
  • MainNav.jsx - Primary navigation menu
  • CategoryMenu.jsx - Category dropdown navigation
  • CountrySelector.jsx - Country and currency selector component
  • PromoBanner.jsx - Promotional announcement banner (e.g., "A24" discount code)

Product Components

  • ProductCard.jsx - Card display for product in listings
  • ProductGrid.jsx - Grid layout for product listings
  • ProductGallery.jsx - Image gallery for product detail page
  • ProductDetails.jsx - Product information display
  • ProductVariants.jsx - Size/color selection component
  • AddToCartButton.jsx - Button with quantity selector

Cart Components

  • CartIcon.jsx - Cart icon with item count indicator
  • CartDrawer.jsx - Slide-out cart drawer
  • CartItem.jsx - Individual item in cart
  • CartSummary.jsx - Order summary with subtotal and discounts

Checkout Components

  • CheckoutForm.jsx - Multi-step checkout form
  • ShippingForm.jsx - Shipping information form
  • PaymentForm.jsx - Payment information with Stripe integration
  • OrderSummary.jsx - Order review component

User Account Components

  • LoginForm.jsx - User login form
  • RegisterForm.jsx - New user registration
  • AccountDashboard.jsx - User account overview
  • OrderHistory.jsx - Past order display

UI Components

  • Button.jsx - Styled button component
  • Input.jsx - Form input field
  • Select.jsx - Dropdown select component
  • Modal.jsx - Popup modal component
  • Spinner.jsx - Loading spinner
  • Toast.jsx - Notification toast

Page Structure

Home Page (pages/index.js)

<Layout>
  <PromoBanner code="A24" message="Special discount on all items!" />
  <HeroSection />
  <FeaturedProducts />
  <NewArrivals />
  <CollectionShowcase />
  <Newsletter />
</Layout>

Product Listing Page (pages/products/index.js)

<Layout>
  <Breadcrumbs />
  <div className="grid grid-cols-12 gap-6">
    <div className="col-span-3">
      <FilterSidebar />
    </div>
    <div className="col-span-9">
      <ProductSorting />
      <ProductGrid products={products} />
      <Pagination />
    </div>
  </div>
</Layout>

Product Detail Page (pages/products/[slug].js)

<Layout>
  <Breadcrumbs />
  <div className="grid grid-cols-1 md:grid-cols-2 gap-8">
    <ProductGallery images={product.images} />
    <div>
      <ProductDetails product={product} />
      <ProductVariants variants={product.variants} />
      <AddToCartButton product={product} />
      <ProductTabs tabs={['Description', 'Details', 'Reviews']} />
    </div>
  </div>
  <RelatedProducts products={relatedProducts} />
</Layout>

Cart Page (pages/cart.js)

<Layout>
  <Breadcrumbs />
  <h1>Your Cart</h1>
  {cartItems.length > 0 ? (
    <div className="grid grid-cols-1 lg:grid-cols-3 gap-8">
      <div className="lg:col-span-2">
        {cartItems.map(item => (
          <CartItem key={item.id} item={item} />
        ))}
      </div>
      <div>
        <CartSummary />
        <PromoCodeInput />
        <CheckoutButton />
      </div>
    </div>
  ) : (
    <EmptyCart />
  )}
</Layout>

Checkout Page (pages/checkout.js)

<Layout>
  <Breadcrumbs />
  <CheckoutSteps currentStep={currentStep} />
  <div className="grid grid-cols-1 lg:grid-cols-3 gap-8">
    <div className="lg:col-span-2">
      {currentStep === 'information' && <ShippingForm />}
      {currentStep === 'shipping' && <ShippingMethodForm />}
      {currentStep === 'payment' && <PaymentForm />}
    </div>
    <div>
      <OrderSummary />
    </div>
  </div>
</Layout>

Component Examples

Promo Banner Component

// components/PromoBanner.jsx
import { useState } from 'react';

export default function PromoBanner({ code, message }) {
  const [isVisible, setIsVisible] = useState(true);

  if (!isVisible) return null;

  return (
    <div className="bg-indigo-600 text-white text-center py-2 px-4 relative">
      <span>{message} Use code <strong>{code}</strong> at checkout</span>
      <button 
        onClick={() => setIsVisible(false)} 
        className="absolute right-4 top-1/2 transform -translate-y-1/2"
        aria-label="Dismiss banner"
      >
        <svg className="h-4 w-4" viewBox="0 0 20 20" fill="currentColor">
          <path fillRule="evenodd" d="M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z" clipRule="evenodd" />
        </svg>
      </button>
    </div>
  );
}

Product Card Component

// components/ProductCard.jsx
import Image from 'next/image';
import Link from 'next/link';

export default function ProductCard({ product }) {
  return (
    <div className="group">
      <div className="relative overflow-hidden rounded-lg">
        <Link href={`/products/${product.slug}`}>
          <div className="aspect-w-1 aspect-h-1 w-full">
            <Image 
              src={product.images[0].url} 
              alt={product.name}
              layout="fill"
              objectFit="cover"
              className="group-hover:scale-105 transition-transform duration-300"
            />
          </div>
          {product.compareAtPrice && (
            <span className="absolute top-2 left-2 bg-red-500 text-white px-2 py-1 text-xs font-medium rounded">
              Sale
            </span>
          )}
        </Link>
      </div>

      <div className="mt-4 flex justify-between">
        <div>
          <h3 className="text-sm font-medium text-gray-700">
            <Link href={`/products/${product.slug}`}>
              {product.name}
            </Link>
          </h3>
        </div>
        <div>
          {product.compareAtPrice ? (
            <div className="flex space-x-2">
              <span className="text-sm font-medium text-red-600">
                ${product.price.toFixed(2)}
              </span>
              <span className="text-sm text-gray-500 line-through">
                ${product.compareAtPrice.toFixed(2)}
              </span>
            </div>
          ) : (
            <span className="text-sm font-medium text-gray-900">
              ${product.price.toFixed(2)}
            </span>
          )}
        </div>
      </div>
    </div>
  );
}

Add to Cart Button

// components/AddToCartButton.jsx
import { useState } from 'react';
import { useCart } from '@/contexts/CartContext';

export default function AddToCartButton({ product, selectedVariant }) {
  const [quantity, setQuantity] = useState(1);
  const { addItem } = useCart();

  const handleAddToCart = () => {
    if (!selectedVariant) {
      // Show error - need to select size/color
      return;
    }

    addItem(product, quantity, selectedVariant);

    // Show success toast
  };

  return (
    <div className="mt-6">
      <div className="flex items-center mb-4">
        <button 
          onClick={() => setQuantity(Math.max(1, quantity - 1))}
          className="w-10 h-10 border border-gray-300 flex items-center justify-center"
        >
          -
        </button>
        <input 
          type="number" 
          value={quantity} 
          onChange={(e) => setQuantity(Math.max(1, parseInt(e.target.value) || 1))}
          className="w-16 h-10 border-t border-b border-gray-300 text-center"
        />
        <button 
          onClick={() => setQuantity(quantity + 1)}
          className="w-10 h-10 border border-gray-300 flex items-center justify-center"
        >
          +
        </button>
      </div>

      <button
        onClick={handleAddToCart}
        className="w-full bg-black text-white py-3 px-6 hover:bg-gray-800 transition"
      >
        Add to Cart
      </button>
    </div>
  );
}

CSS and Styling

The project uses Tailwind CSS for styling with some additional custom styles where needed. Key style considerations:

  1. Color Scheme - Primary: Black (#000000) - Accent: Indigo (#4F46E5) - Backgrounds: White/light grays - Text: Dark gray for body, black for headings

  2. Typography - Primary font: Inter (sans-serif) - Heading sizes: h1 (2rem), h2 (1.5rem), h3 (1.25rem) - Body text: 1rem (16px)

  3. Spacing System - Based on Tailwind's default spacing scale - Consistent padding/margins for sections (py-16, px-4)

  4. Responsive Breakpoints - Mobile first approach - Key breakpoints: sm (640px), md (768px), lg (1024px), xl (1280px)

Component State Management

The application uses React Context for global state management:

  1. CartContext - Manages shopping cart items and operations
  2. AuthContext - Handles user authentication state
  3. UIContext - Controls UI elements like modals and notifications

For complex state logic, we use the reducer pattern with the useReducer hook.