diff options
author | 2025-05-28 15:06:59 +0530 | |
---|---|---|
committer | 2025-05-28 15:06:59 +0530 | |
commit | a92719db37afc5cdf375f3ad5ce8e9602450ab2d (patch) | |
tree | 783530b755b1fe1c1b1981ad8d6230e662cf0a64 | |
download | blcklst-a92719db37afc5cdf375f3ad5ce8e9602450ab2d.tar.gz blcklst-a92719db37afc5cdf375f3ad5ce8e9602450ab2d.tar.bz2 blcklst-a92719db37afc5cdf375f3ad5ce8e9602450ab2d.zip |
feat: added the docs page
-rw-r--r-- | README.md | 87 | ||||
-rw-r--r-- | docs/components.md | 327 | ||||
-rw-r--r-- | docs/implementation.md | 708 | ||||
-rw-r--r-- | docs/project-plan.md | 95 |
4 files changed, 1217 insertions, 0 deletions
diff --git a/README.md b/README.md new file mode 100644 index 0000000..4feb096 --- /dev/null +++ b/README.md @@ -0,0 +1,87 @@ +# E-Commerce Clothing Brand Website + +A modern e-commerce platform for a clothing brand similar to turntupfashion.com, built with Next.js, Express, and MongoDB. + +## Project Overview + +This project provides a complete e-commerce solution with the following features: +- Responsive product catalog with filtering and search +- User authentication and account management +- Shopping cart and checkout process +- Payment processing integration +- Admin dashboard for product and order management +- Multi-currency support + +## Tech Stack + +- **Frontend**: Next.js, React, Tailwind CSS +- **Backend**: Node.js, Express.js +- **Database**: MongoDB with Mongoose +- **Authentication**: JWT +- **Payment**: Stripe API + +## Getting Started + +### Prerequisites + +- Node.js (v16+) +- MongoDB +- Stripe account for payment processing + +### Installation + +1. Clone the repository +```bash +git clone https://github.com/yourusername/ecom.git +cd ecom +``` + +2. Set up the frontend +```bash +cd frontend +npm install +cp .env.example .env.local +# Edit .env.local with your environment variables +``` + +3. Set up the backend +```bash +cd ../backend +npm install +cp .env.example .env +# Edit .env with your environment variables +``` + +4. Start development servers + +Frontend: +```bash +cd frontend +npm run dev +``` + +Backend: +```bash +cd backend +npm run dev +``` + +## Project Structure + +The project follows a clear separation between frontend and backend: + +- `/frontend`: Next.js application with pages, components, and assets +- `/backend`: Express.js API with controllers, models, and routes +- `/admin`: Admin dashboard (optional separate application) +- `/shared`: Shared code and types between frontend and backend + +## Documentation + +For more detailed documentation, see: +- [Project Plan](./docs/project-plan.md) - Complete project overview and timeline +- [Implementation Guide](./docs/implementation.md) - Step-by-step implementation details +- [Component Structure](./docs/components.md) - Frontend component organization + +## License + +MIT diff --git a/docs/components.md b/docs/components.md new file mode 100644 index 0000000..5303dc0 --- /dev/null +++ b/docs/components.md @@ -0,0 +1,327 @@ +# 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 + +### Navigation Components + +- `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`) +```jsx +<Layout> + <PromoBanner code="A24" message="Special discount on all items!" /> + <HeroSection /> + <FeaturedProducts /> + <NewArrivals /> + <CollectionShowcase /> + <Newsletter /> +</Layout> +``` + +### Product Listing Page (`pages/products/index.js`) +```jsx +<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`) +```jsx +<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`) +```jsx +<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`) +```jsx +<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 + +```jsx +// 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 + +```jsx +// 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 + +```jsx +// 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.
\ No newline at end of file diff --git a/docs/implementation.md b/docs/implementation.md new file mode 100644 index 0000000..03d8c43 --- /dev/null +++ b/docs/implementation.md @@ -0,0 +1,708 @@ +# Implementation Guide + +This guide provides practical steps to implement the e-commerce platform based on the project plan. + +## Getting Started + +### 1. Development Environment Setup + +```bash +# Create project directory structure +mkdir -p ecom/{frontend,backend,admin,shared} + +# Initialize frontend (Next.js) +cd ecom/frontend +npx create-next-app . --typescript --tailwind --eslint + +# Initialize backend (Express.js + MongoDB) +cd ../backend +npm init -y +npm install express mongoose dotenv cors helmet jsonwebtoken bcrypt stripe + +# Create basic directory structure for backend +mkdir -p config controllers middleware models routes services utils +touch server.js .env .env.example .gitignore README.md +``` + +### 2. Frontend Implementation Steps + +#### Step 1: Set up basic components +- Create layout components (header, footer, navigation) +- Set up routing structure +- Implement basic styling with Tailwind CSS + +#### Step 2: Key pages implementation +- Homepage with featured products and promotions +- Product listing page with filtering +- Product detail page +- Cart page +- Checkout flow +- User account pages + +```jsx +// Example: Product Card Component (frontend/src/components/ProductCard.jsx) +import Image from 'next/image'; +import Link from 'next/link'; + +const ProductCard = ({ product }) => { + return ( + <div className="group relative"> + <div className="aspect-h-1 aspect-w-1 w-full overflow-hidden rounded-md bg-gray-200 lg:aspect-none group-hover:opacity-75 lg:h-80"> + <Image + src={product.imageSrc} + alt={product.imageAlt} + className="h-full w-full object-cover object-center lg:h-full lg:w-full" + width={500} + height={500} + /> + </div> + <div className="mt-4 flex justify-between"> + <div> + <h3 className="text-sm text-gray-700"> + <Link href={`/products/${product.id}`}> + <span aria-hidden="true" className="absolute inset-0" /> + {product.name} + </Link> + </h3> + <p className="mt-1 text-sm text-gray-500">{product.color}</p> + </div> + <p className="text-sm font-medium text-gray-900">{product.price}</p> + </div> + </div> + ); +}; + +export default ProductCard; +``` + +#### Step 3: State management +- Implement context providers for: + - Shopping cart + - User authentication + - Product filtering + +```jsx +// Example: CartContext (frontend/src/contexts/CartContext.jsx) +import { createContext, useContext, useReducer, useEffect } from 'react'; + +const CartContext = createContext(); + +const cartReducer = (state, action) => { + switch (action.type) { + case 'ADD_ITEM': + // Check if item exists + const existingItemIndex = state.items.findIndex( + (item) => item.id === action.payload.id && + item.selectedSize === action.payload.selectedSize + ); + + if (existingItemIndex >= 0) { + // Item exists, update quantity + const updatedItems = [...state.items]; + updatedItems[existingItemIndex].quantity += action.payload.quantity; + + return { + ...state, + items: updatedItems, + }; + } + + // Item doesn't exist, add new + return { + ...state, + items: [...state.items, action.payload], + }; + + case 'REMOVE_ITEM': + return { + ...state, + items: state.items.filter( + (item) => !(item.id === action.payload.id && + item.selectedSize === action.payload.selectedSize) + ), + }; + + case 'UPDATE_QUANTITY': + return { + ...state, + items: state.items.map((item) => { + if (item.id === action.payload.id && + item.selectedSize === action.payload.selectedSize) { + return { + ...item, + quantity: action.payload.quantity, + }; + } + return item; + }), + }; + + case 'CLEAR_CART': + return { + ...state, + items: [], + }; + + default: + return state; + } +}; + +export const CartProvider = ({ children }) => { + const [state, dispatch] = useReducer(cartReducer, { + items: [], + }); + + // Load cart from localStorage on mount + useEffect(() => { + try { + const savedCart = localStorage.getItem('cart'); + if (savedCart) { + const parsedCart = JSON.parse(savedCart); + dispatch({ type: 'REPLACE_CART', payload: parsedCart }); + } + } catch (error) { + console.error('Error loading cart from localStorage:', error); + } + }, []); + + // Save cart to localStorage on update + useEffect(() => { + try { + localStorage.setItem('cart', JSON.stringify(state.items)); + } catch (error) { + console.error('Error saving cart to localStorage:', error); + } + }, [state.items]); + + const addItem = (product, quantity = 1, selectedSize) => { + dispatch({ + type: 'ADD_ITEM', + payload: { ...product, quantity, selectedSize }, + }); + }; + + const removeItem = (productId, selectedSize) => { + dispatch({ + type: 'REMOVE_ITEM', + payload: { id: productId, selectedSize }, + }); + }; + + const updateQuantity = (productId, selectedSize, quantity) => { + dispatch({ + type: 'UPDATE_QUANTITY', + payload: { id: productId, selectedSize, quantity }, + }); + }; + + const clearCart = () => { + dispatch({ type: 'CLEAR_CART' }); + }; + + const cartTotal = state.items.reduce( + (total, item) => total + item.price * item.quantity, + 0 + ); + + const itemCount = state.items.reduce( + (count, item) => count + item.quantity, + 0 + ); + + return ( + <CartContext.Provider + value={{ + items: state.items, + addItem, + removeItem, + updateQuantity, + clearCart, + cartTotal, + itemCount, + }} + > + {children} + </CartContext.Provider> + ); +}; + +export const useCart = () => useContext(CartContext); +``` + +### 3. Backend Implementation Steps + +#### Step 1: Database models +- Create schemas for products, users, orders +- Set up database connection + +```javascript +// Example: Product Model (backend/models/Product.js) +const mongoose = require('mongoose'); + +const productSchema = new mongoose.Schema({ + name: { + type: String, + required: true, + trim: true + }, + slug: { + type: String, + required: true, + unique: true, + lowercase: true + }, + description: { + type: String, + required: true + }, + price: { + type: Number, + required: true, + min: 0 + }, + compareAtPrice: { + type: Number, + min: 0 + }, + images: [{ + url: String, + alt: String + }], + category: { + type: mongoose.Schema.Types.ObjectId, + ref: 'Category', + required: true + }, + variants: [{ + color: String, + size: String, + inventory: Number + }], + tags: [String], + featured: { + type: Boolean, + default: false + }, + createdAt: { + type: Date, + default: Date.now + }, + updatedAt: { + type: Date, + default: Date.now + } +}, { timestamps: true }); + +// Add index for search +productSchema.index({ + name: 'text', + description: 'text', + tags: 'text' +}); + +module.exports = mongoose.model('Product', productSchema); +``` + +#### Step 2: API endpoints +- Create RESTful routes for products, users, orders +- Implement authentication middleware + +```javascript +// Example: Product Routes (backend/routes/products.js) +const express = require('express'); +const router = express.Router(); +const productController = require('../controllers/productController'); +const { authenticate, isAdmin } = require('../middleware/authMiddleware'); + +// Public routes +router.get('/', productController.getAllProducts); +router.get('/featured', productController.getFeaturedProducts); +router.get('/category/:categoryId', productController.getProductsByCategory); +router.get('/search', productController.searchProducts); +router.get('/:id', productController.getProductById); +router.get('/slug/:slug', productController.getProductBySlug); + +// Protected routes (admin only) +router.post('/', authenticate, isAdmin, productController.createProduct); +router.put('/:id', authenticate, isAdmin, productController.updateProduct); +router.delete('/:id', authenticate, isAdmin, productController.deleteProduct); +router.post('/bulk', authenticate, isAdmin, productController.bulkImportProducts); + +module.exports = router; +``` + +#### Step 3: Payment integration +- Set up Stripe API for payment processing +- Implement checkout logic + +```javascript +// Example: Payment Controller (backend/controllers/paymentController.js) +const stripe = require('stripe')(process.env.STRIPE_SECRET_KEY); +const Order = require('../models/Order'); +const Product = require('../models/Product'); + +exports.createCheckoutSession = async (req, res) => { + try { + const { items, shippingAddress } = req.body; + + // Validate cart items and get from database to ensure price integrity + const productIds = items.map(item => item.id); + const products = await Product.find({ _id: { $in: productIds } }); + + // Map products to line items for Stripe + const lineItems = items.map(item => { + const product = products.find(p => p._id.toString() === item.id); + + if (!product) { + throw new Error(`Product not found: ${item.id}`); + } + + return { + price_data: { + currency: 'inr', + product_data: { + name: product.name, + images: product.images.map(img => img.url), + }, + unit_amount: Math.round(product.price * 100), // Stripe requires amount in cents + }, + quantity: item.quantity, + }; + }); + + // Create a new order in pending state + const order = new Order({ + user: req.user ? req.user._id : null, + items: items.map(item => ({ + product: item.id, + quantity: item.quantity, + price: products.find(p => p._id.toString() === item.id).price, + selectedVariant: { + size: item.selectedSize, + color: item.selectedColor + } + })), + shippingAddress, + total: items.reduce((sum, item) => { + const product = products.find(p => p._id.toString() === item.id); + return sum + (product.price * item.quantity); + }, 0), + status: 'pending' + }); + + await order.save(); + + // Create Stripe checkout session + const session = await stripe.checkout.sessions.create({ + payment_method_types: ['card'], + line_items: lineItems, + mode: 'payment', + success_url: `${process.env.FRONTEND_URL}/checkout/success?session_id={CHECKOUT_SESSION_ID}`, + cancel_url: `${process.env.FRONTEND_URL}/cart`, + metadata: { + orderId: order._id.toString() + } + }); + + res.json({ id: session.id, url: session.url }); + } catch (error) { + console.error('Payment session error:', error); + res.status(500).json({ error: error.message }); + } +}; + +exports.handleWebhook = async (req, res) => { + const signature = req.headers['stripe-signature']; + + try { + const event = stripe.webhooks.constructEvent( + req.body, + signature, + process.env.STRIPE_WEBHOOK_SECRET + ); + + if (event.type === 'checkout.session.completed') { + const session = event.data.object; + const orderId = session.metadata.orderId; + + // Update order status to paid + await Order.findByIdAndUpdate(orderId, { + status: 'paid', + paymentId: session.payment_intent + }); + + // Here you would also update inventory, send confirmation emails, etc. + } + + res.json({ received: true }); + } catch (error) { + console.error('Webhook error:', error); + res.status(400).send(`Webhook Error: ${error.message}`); + } +}; +``` + +### 4. Admin Dashboard Implementation + +- Implement pages for product, order, and user management +- Create forms for product creation and editing +- Develop dashboard for sales analytics + +### 5. Deployment Strategy + +#### Development Environment +- Local development with Docker + +#### Staging Environment +- AWS/Vercel deployment +- Continuous integration with GitHub Actions + +#### Production Environment +- Load-balanced setup +- Database backups +- CDN for static assets + +## Key Features Implementation Details + +### 1. Country/Currency Selector + +```jsx +// Example component +import { useState, useEffect } from 'react'; +import { useRouter } from 'next/router'; + +const countryCurrencyMap = { + US: { currency: 'USD', symbol: '$' }, + IN: { currency: 'INR', symbol: '₹' }, + GB: { currency: 'GBP', symbol: '£' }, + // Add more countries as needed +}; + +export default function CurrencySelector() { + const [selectedCountry, setSelectedCountry] = useState('IN'); + const router = useRouter(); + + // Effect to set country based on user's location or saved preference + useEffect(() => { + const savedCountry = localStorage.getItem('selectedCountry'); + if (savedCountry) { + setSelectedCountry(savedCountry); + } else { + // Could add geolocation API to auto-detect + } + }, []); + + // Update when user changes selection + const handleCountryChange = (e) => { + const country = e.target.value; + setSelectedCountry(country); + localStorage.setItem('selectedCountry', country); + + // Force refresh to update prices + router.reload(); + }; + + return ( + <div className="relative"> + <select + value={selectedCountry} + onChange={handleCountryChange} + className="block appearance-none bg-white border border-gray-300 px-4 py-2 pr-8 rounded shadow leading-tight focus:outline-none focus:shadow-outline" + > + <option value="IN">India (₹)</option> + <option value="US">United States ($)</option> + <option value="GB">United Kingdom (£)</option> + {/* Add more countries */} + </select> + <div className="pointer-events-none absolute inset-y-0 right-0 flex items-center px-2 text-gray-700"> + <svg className="fill-current h-4 w-4" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20"> + <path d="M9.293 12.95l.707.707L15.657 8l-1.414-1.414L10 10.828 5.757 6.586 4.343 8z" /> + </svg> + </div> + </div> + ); +} +``` + +### 2. Responsive Product Gallery + +```jsx +// Example implementation +import { useState } from 'react'; +import Image from 'next/image'; + +export default function ProductGallery({ images }) { + const [mainImage, setMainImage] = useState(images[0]); + + return ( + <div className="grid gap-4"> + <div className="relative h-96 overflow-hidden rounded-lg"> + <Image + src={mainImage.url} + alt={mainImage.alt} + layout="fill" + objectFit="cover" + className="w-full h-full object-center object-cover" + /> + </div> + <div className="grid grid-cols-5 gap-2"> + {images.map((image, i) => ( + <button + key={i} + onClick={() => setMainImage(image)} + className={`relative h-20 overflow-hidden rounded-md ${ + mainImage.url === image.url ? 'ring-2 ring-indigo-500' : '' + }`} + > + <Image + src={image.url} + alt={image.alt} + layout="fill" + objectFit="cover" + className="w-full h-full object-center object-cover" + /> + </button> + ))} + </div> + </div> + ); +} +``` + +### 3. Promotional Banner Component + +```jsx +// Example implementation +import { useState, useEffect } from 'react'; + +export default function PromoBanner({ code, message, expiry }) { + const [isVisible, setIsVisible] = useState(true); + + // Check if banner should be shown (e.g., not dismissed recently) + useEffect(() => { + const bannerDismissed = localStorage.getItem('promoBannerDismissed'); + if (bannerDismissed) { + const dismissTime = parseInt(bannerDismissed); + // Show again after 1 day + if (Date.now() - dismissTime < 24 * 60 * 60 * 1000) { + setIsVisible(false); + } + } + }, []); + + const handleDismiss = () => { + setIsVisible(false); + localStorage.setItem('promoBannerDismissed', Date.now().toString()); + }; + + if (!isVisible) return null; + + return ( + <div className="bg-indigo-600 py-3"> + <div className="mx-auto max-w-7xl px-3 sm:px-6 lg:px-8"> + <div className="flex flex-wrap items-center justify-between"> + <div className="flex w-0 flex-1 items-center"> + <span className="flex rounded-lg bg-indigo-800 p-2"> + <svg className="h-6 w-6 text-white" fill="none" viewBox="0 0 24 24" stroke="currentColor"> + <path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M11 5.882V19.24a1.76 1.76 0 01-3.417.592l-2.147-6.15M18 13a3 3 0 100-6M5.436 13.683A4.001 4.001 0 017 6h1.832c4.1 0 7.625-1.234 9.168-3v14c-1.543-1.766-5.067-3-9.168-3H7a3.988 3.988 0 01-1.564-.317z" /> + </svg> + </span> + <p className="ml-3 font-medium text-white"> + <span className="md:hidden">{message}</span> + <span className="hidden md:inline"> + {message} Use code <span className="font-bold">{code}</span> at checkout + </span> + </p> + </div> + <div className="order-3 mt-2 w-full flex-shrink-0 sm:order-2 sm:mt-0 sm:w-auto"> + <a + href="#" + className="flex items-center justify-center rounded-md border border-transparent bg-white px-4 py-2 text-sm font-medium text-indigo-600 shadow-sm hover:bg-indigo-50" + > + Shop Now + </a> + </div> + <div className="order-2 flex-shrink-0 sm:order-3 sm:ml-3"> + <button + type="button" + onClick={handleDismiss} + className="-mr-1 flex rounded-md p-2 hover:bg-indigo-500 focus:outline-none focus:ring-2 focus:ring-white sm:-mr-2" + > + <span className="sr-only">Dismiss</span> + <svg className="h-6 w-6 text-white" fill="none" viewBox="0 0 24 24" stroke="currentColor"> + <path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M6 18L18 6M6 6l12 12" /> + </svg> + </button> + </div> + </div> + </div> + </div> + ); +} +``` + +## Testing and Quality Assurance + +### Unit Testing +```bash +# Frontend testing +cd frontend +npm test + +# Backend testing +cd ../backend +npm test +``` + +### End-to-End Testing +```bash +# Install Cypress +cd frontend +npm install cypress --save-dev + +# Run E2E tests +npx cypress open +``` + +## Performance Optimization Strategies + +1. **Image Optimization** + - Use Next.js Image component + - Implement lazy loading + - Serve responsive images + +2. **Code Splitting** + - Leverage Next.js automatic code splitting + - Use dynamic imports for large components + +3. **Server-Side Rendering** + - Use SSR for product listings and detail pages + - Implement Incremental Static Regeneration for frequently updated pages + +4. **API Response Caching** + - Implement Redis for caching + - Add HTTP cache headers + +## Security Best Practices + +1. **Authentication** + - Implement JWT with refresh tokens + - Store tokens securely in HTTP-only cookies + +2. **API Security** + - Implement rate limiting + - Use CORS protection + - Validate all inputs + +3. **Payment Data** + - Use Stripe Elements for secure payment form + - Never store sensitive payment information + +## Ongoing Maintenance Plan + +1. Regular dependency updates +2. Security patches +3. Performance monitoring +4. Backup strategy +5. Scaling plan as traffic increases
\ No newline at end of file diff --git a/docs/project-plan.md b/docs/project-plan.md new file mode 100644 index 0000000..5716264 --- /dev/null +++ b/docs/project-plan.md @@ -0,0 +1,95 @@ +# E-Commerce Project Plan + +## Project Overview +This project aims to create an e-commerce platform for a clothing brand similar to turntupfashion.com, featuring modern design, seamless user experience, and robust e-commerce functionality. + +## Technology Stack +- **Frontend**: React.js with Next.js +- **Styling**: Tailwind CSS +- **Backend**: Node.js with Express.js +- **Database**: MongoDB with Mongoose +- **Authentication**: JWT with OAuth +- **Payment**: Stripe API +- **Deployment**: Docker containers on AWS/Vercel + +## Core Features + +### User-Facing Features +- **Homepage** - Featured products, new arrivals, promotions +- **Product Catalog** - Filtering, sorting, search +- **Product Detail** - Image gallery, variants, add to cart +- **Shopping Cart** - Item management, promotions, calculations +- **Checkout** - Guest checkout, shipping, payment +- **User Accounts** - Order history, addresses, wishlist +- **Country/Currency** - Multi-currency support + +### Admin Features +- **Product Management** - CRUD operations, inventory +- **Order Management** - Processing, status updates, invoicing +- **Customer Management** - Information, support tools +- **Content Management** - Homepage, promotions +- **Analytics** - Sales reporting, insights + +## Development Phases + +### Phase 1: Setup (2 weeks) +- Environment setup, repository initialization +- Basic API endpoints and database configuration +- Design system and component library + +### Phase 2: Core Functionality (4 weeks) +- Product catalog and browsing +- Product detail pages +- Shopping cart functionality +- User authentication +- Checkout flow (without payment) + +### Phase 3: Payment & UX (3 weeks) +- Payment gateway integration +- Order management +- User accounts and profiles +- Country/currency selector +- Mobile responsiveness + +### Phase 4: Admin & Backend (3 weeks) +- Admin product management +- Order processing workflows +- Inventory management +- Analytics dashboard +- Content management + +### Phase 5: Testing & Optimization (2 weeks) +- Comprehensive testing +- Performance optimization +- SEO implementation +- Accessibility compliance +- Security audit + +### Phase 6: Launch (2 weeks) +- Final QA testing +- Production setup +- Data migration +- Deployment +- Launch preparation + +## Technical Requirements + +- **Performance**: Web Vitals optimization, image optimization, code splitting +- **Security**: HTTPS, authentication, input validation, PCI compliance +- **SEO**: Semantic HTML, metadata, structured data +- **Accessibility**: WCAG 2.1 AA compliance + +## Timeline +- **Week 1-2**: Project setup +- **Week 3-6**: Core functionality +- **Week 7-9**: Payment and UX +- **Week 10-12**: Admin dashboard +- **Week 13-14**: Testing and optimization +- **Week 15-16**: Launch preparation + +## Team Structure +- 1 Project Manager +- 2 Frontend Developers +- 2 Backend Developers +- 1 UI/UX Designer +- 1 QA Engineer
\ No newline at end of file |