Skip to content

Planning Exercise: E-commerce Shopping Cart

Scenario Description

Your team needs to implement an e-commerce shopping cart feature. The product manager has provided a requirements document, and you need to use the writing-plans skill to break it down into executable development tasks.

Requirements Document

markdown
# Shopping Cart Feature Requirements

## Core Features

### 1. Add Products
- User can click "Add to Cart" button to add products
- If product already in cart, increase quantity
- Show success notification after adding

### 2. View Cart
- Display all products in cart
- Each product shows: image, name, unit price, quantity, subtotal
- Display total item count and total amount

### 3. Modify Quantity
- User can adjust quantity via +/- buttons
- Quantity cannot be less than 1
- Subtotal and total update in real-time

### 4. Remove Products
- User can remove products from cart
- Show confirmation dialog before removal

### 5. Data Persistence
- Cart data saved in LocalStorage
- Data persists after page refresh

## Technical Constraints

- Use Svelte framework
- Use TypeScript
- Follow TDD development process

Your Task

Use the writing-plans skill to:

  1. Analyze Requirements: Understand specific requirements for each feature
  2. Design Architecture: Determine component structure and data flow
  3. Break Down Tasks: Split requirements into 2-5 minute tasks
  4. Write Plan: Generate detailed implementation plan

Planning Guide

Task Breakdown Principles

Each task should be:

  • Atomic: One task does one thing
  • Verifiable: Has clear completion criteria
  • Small: Completable in 2-5 minutes
  • Independently Testable: Can be tested independently

Task Format

markdown
## Task N: Task Title

### Files
- List of files to create/modify

### Operations
1. Specific operation steps
2. Include necessary code snippets

### Verification
- Expected results
- Verification commands

Design Thinking

Before writing the plan, think about:

  1. State Management: How to store and manage cart state?
  2. Component Structure: What components are needed? How are responsibilities divided?
  3. Data Flow: How does data flow between components?
  4. Testing Strategy: How to ensure quality?

Hints

Hint 1: Component Structure

Suggested component structure:

text
src/
├── stores/
│   └── cart.ts          # Cart state management
├── lib/
│   ├── Cart.svelte      # Cart container
│   ├── CartItem.svelte  # Single product row
│   ├── CartSummary.svelte # Price summary
│   └── AddToCart.svelte # Add button
└── types/
    └── cart.ts          # Type definitions

Hint 2: State Management

Use Svelte Store:

typescript
// stores/cart.ts
import { writable, derived } from 'svelte/store';
import { browser } from '$app/environment';
import type { CartItem, Product } from '../types/cart';

// Initialize from LocalStorage
const stored = browser 
  ? JSON.parse(localStorage.getItem('cart') || '[]')
  : [];

export const cartItems = writable<CartItem[]>(stored);

// Auto-save to LocalStorage
cartItems.subscribe(items => {
  if (browser) {
    localStorage.setItem('cart', JSON.stringify(items));
  }
});

// Derived data: count and total
export const cartCount = derived(cartItems, 
  items => items.reduce((sum, item) => sum + item.quantity, 0)
);

export const cartTotal = derived(cartItems,
  items => items.reduce((sum, item) => sum + item.price * item.quantity, 0)
);

// Action methods
export function addToCart(product: Product) {
  // See implementation below
}
export function updateQuantity(id: string, quantity: number) {
  // See implementation below
}
export function removeFromCart(id: string) {
  // See implementation below
}

Hint 3: Task Breakdown

Start with the simplest:

  1. First establish type definitions
  2. Then implement state management
  3. Then implement UI components
  4. Finally implement interaction features

Hint 4: TDD Thinking

Each task should include tests:

markdown
Task: Create CartItem type
Verification: TypeScript compiles, type checks correctly

Task: Implement addToCart method
Verification: Unit tests pass
  - Add new product: cart count +1
  - Add existing product: quantity +1

Reference Solution

markdown
# Shopping Cart Implementation Plan

## Design Overview

### Component Structure
- `Cart.svelte` - Main cart container
- `CartItem.svelte` - Single product row
- `CartSummary.svelte` - Price summary
- `AddToCart.svelte` - Add button

### State Management
Use Svelte Store + LocalStorage persistence

---

## Task 1: Create Type Definitions

### Files
- Create `src/types/cart.ts`

### Operations
```typescript
// src/types/cart.ts
export interface Product {
  id: string;
  name: string;
  price: number;
  imageUrl: string;
}

export interface CartItem {
  productId: string;
  name: string;
  price: number;
  imageUrl: string;
  quantity: number;
}

Verification

  • TypeScript compiles
  • No type errors

Task 2: Create Cart Store

Files

  • Create src/stores/cart.ts

Operations

typescript
// src/stores/cart.ts
import { writable, derived } from 'svelte/store';
import { browser } from '$app/environment';
import type { CartItem, Product } from '../types/cart';

const stored = browser 
  ? JSON.parse(localStorage.getItem('cart') || '[]')
  : [];

export const cartItems = writable<CartItem[]>(stored);

cartItems.subscribe(items => {
  if (browser) {
    localStorage.setItem('cart', JSON.stringify(items));
  }
});

export const cartCount = derived(cartItems, 
  items => items.reduce((sum, item) => sum + item.quantity, 0)
);

export const cartTotal = derived(cartItems,
  items => items.reduce((sum, item) => sum + item.price * item.quantity, 0)
);

Verification

  • TypeScript compiles
  • Store can be imported normally

Task 3: Implement addToCart Method

Files

  • Modify src/stores/cart.ts

Operations

typescript
export function addToCart(product: Product) {
  cartItems.update(items => {
    const existing = items.find(item => item.productId === product.id);
    if (existing) {
      return items.map(item =>
        item.productId === product.id
          ? { ...item, quantity: item.quantity + 1 }
          : item
      );
    }
    return [...items, {
      productId: product.id,
      name: product.name,
      price: product.price,
      imageUrl: product.imageUrl,
      quantity: 1
    }];
  });
}

Verification

  • Unit test: Add new product
  • Unit test: Add existing product

Task 4: Implement updateQuantity Method

Files

  • Modify src/stores/cart.ts

Operations

typescript
export function updateQuantity(productId: string, quantity: number) {
  if (quantity < 1) return;
  
  cartItems.update(items =>
    items.map(item =>
      item.productId === productId
        ? { ...item, quantity }
        : item
    )
  );
}

Verification

  • Unit test: Quantity updates correctly
  • Unit test: No update when quantity < 1

Task 5: Implement removeFromCart Method

Files

  • Modify src/stores/cart.ts

Operations

typescript
export function removeFromCart(productId: string) {
  cartItems.update(items =>
    items.filter(item => item.productId !== productId)
  );
}

Verification

  • Unit test: Product removed from cart

Task 6: Create CartItem Component

Files

  • Create src/lib/CartItem.svelte

Operations

svelte
<script lang="ts">
  import type { CartItem } from '../types/cart';
  import { updateQuantity, removeFromCart } from '../stores/cart';
  
  export let item: CartItem;
</script>

<div class="cart-item">
  <img src={item.imageUrl} alt={item.name} />
  <div class="info">
    <h3>{item.name}</h3>
    <p class="price">${item.price.toFixed(2)}</p>
  </div>
  <div class="quantity">
    <button on:click={() => updateQuantity(item.productId, item.quantity - 1)}>-</button>
    <span>{item.quantity}</span>
    <button on:click={() => updateQuantity(item.productId, item.quantity + 1)}>+</button>
  </div>
  <p class="subtotal">${(item.price * item.quantity).toFixed(2)}</p>
  <button class="remove" on:click={() => removeFromCart(item.productId)}>×</button>
</div>

Verification

  • Component renders normally
  • Displays correct product info

Task 7: Create CartSummary Component

Files

  • Create src/lib/CartSummary.svelte

Operations

svelte
<script lang="ts">
  import { cartCount, cartTotal } from '../stores/cart';
</script>

<div class="cart-summary">
  <p>Total Items: <strong>{$cartCount}</strong></p>
  <p>Total: <strong>${$cartTotal.toFixed(2)}</strong></p>
</div>

Verification

  • Displays correct count and total

Task 8: Create Cart Main Container

Files

  • Create src/lib/Cart.svelte

Operations

svelte
<script lang="ts">
  import { cartItems } from '../stores/cart';
  import CartItem from './CartItem.svelte';
  import CartSummary from './CartSummary.svelte';
</script>

<div class="cart">
  <h2>Shopping Cart</h2>
  
  {#if $cartItems.length === 0}
    <p class="empty">Your cart is empty</p>
  {:else}
    <div class="items">
      {#each $cartItems as item (item.productId)}
        <CartItem {item} />
      {/each}
    </div>
    <CartSummary />
  {/if}
</div>

Verification

  • Empty cart shows message
  • Products show list

Task 9: Create AddToCart Component

Files

  • Create src/lib/AddToCart.svelte

Operations

svelte
<script lang="ts">
  import { addToCart } from '../stores/cart';
  import type { Product } from '../types/cart';
  
  export let product: Product;
  let added = false;
  
  function handleAdd() {
    addToCart(product);
    added = true;
    setTimeout(() => added = false, 2000);
  }
</script>

<button 
  class="add-to-cart" 
  class:added
  on:click={handleAdd}
>
  {added ? 'Added ✓' : 'Add to Cart'}
</button>

Verification

  • Shows "Added" after click
  • Product appears in cart

Task 10: Integration Test

Files

  • Create src/routes/+page.svelte (test page)

Operations

svelte
<script lang="ts">
  import Cart from '../lib/Cart.svelte';
  import AddToCart from '../lib/AddToCart.svelte';
  
  const demoProducts = [
    { id: '1', name: 'Product A', price: 99.99, imageUrl: '/placeholder.jpg' },
    { id: '2', name: 'Product B', price: 149.99, imageUrl: '/placeholder.jpg' },
  ];
</script>

<main>
  <section class="products">
    {#each demoProducts as product}
      <div class="product">
        <h3>{product.name}</h3>
        <p>${product.price}</p>
        <AddToCart {product} />
      </div>
    {/each}
  </section>
  
  <Cart />
</main>

Verification

  • Complete flow test
  • Add product → View cart → Modify quantity → Remove product

Completion Criteria

  • [ ] All TypeScript type definitions complete
  • [ ] Store method unit tests pass
  • [ ] All components render normally
  • [ ] LocalStorage persistence works
  • [ ] Data persists after page refresh

## Key Learning Points

### 1. Task Granularity

Good task granularity:
- Too big: Implement shopping cart feature (cannot verify)
- Too small: Create a file (meaningless)
- Just right: Implement addToCart method (verifiable, 2-5 minutes)

### 2. Progressive Development

Start from core:
1. Type definitions → 2. State management → 3. UI components → 4. Interaction features

### 3. Verifiability

Each task has clear verification criteria:
- Compiles successfully
- Tests pass
- Functionality works

### 4. Architecture First

Think about architecture before writing plan:
- Component responsibility division
- Data flow direction
- State management strategy

## Common Mistakes

| Mistake | Correct Approach |
|---------|------------------|
| Task too big (implement entire feature) | Break into verifiable small tasks |
| Missing verification criteria | Each task has clear verification method |
| Ignoring tests | Each functional task includes tests |
| Not considering dependencies | Order tasks by dependency |

## Advanced Exercises

After completing the basic exercise, try:

1. **Add coupon feature**: Enter promo code, calculate discount
2. **Add inventory check**: Products have stock limits
3. **Add batch operations**: Select all, batch delete

## Related Skills

- [writing-plans](/en/skills/writing-plans) - Planning skill
- [brainstorming](/en/skills/brainstorming) - Requirements exploration
- [test-driven-development](/en/skills/test-driven-development) - Core TDD skill
- [executing-plans](/en/skills/executing-plans) - Plan execution