docs: comprehensive updates for today's shop frontend improvements
Updated documentation to cover all work completed today: ## Database Setup (docs/getting-started/database-setup.md) - Added data seeding section with all three scripts - Documented inventory creation requirement - Added complete setup workflow - Included common issues and solutions - Added database reset instructions ## New Troubleshooting Guide (docs/troubleshooting/shop-frontend.md) Comprehensive troubleshooting for: ### Cart and Product Issues - Products cannot be added to cart (inventory = 0) - Cart is empty after adding products (session ID issue) - Root causes and solutions with code examples ### Styling and Layout Issues - Pages with no styling (not extending base template) - Images not loading (placeholder SVG implementation) - Detailed before/after examples ### Navigation and Routing Issues - Product detail 404 (duplicate /shop prefix) - Missing /shop/ in links - Breadcrumb navigation patterns ### Landing Page Issues - Vendor root 404 (no landing page) - Breadcrumb home link configuration - Auto-redirect behavior ### Alpine.js Issues - Component data not available (parent init not called) - Product ID undefined (window globals solution) - Debugging tips and console commands All issues encountered today are now documented with: - Clear symptoms - Root cause explanation - How the system works - Step-by-step solutions - Code examples - Verification steps 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -31,13 +31,25 @@ DATABASE_URL=sqlite:///./ecommerce.db
|
||||
make migrate-up
|
||||
```
|
||||
|
||||
### 4. Verify Setup
|
||||
### 4. Seed Test Data (Optional)
|
||||
```bash
|
||||
# Create test vendors, products, and inventory
|
||||
python scripts/create_test_data.py
|
||||
|
||||
# Create inventory entries for existing products
|
||||
python scripts/create_inventory.py
|
||||
|
||||
# Create landing pages for vendors
|
||||
python scripts/create_landing_page.py
|
||||
```
|
||||
|
||||
### 5. Verify Setup
|
||||
```bash
|
||||
# Check that everything is working
|
||||
make verify-setup
|
||||
```
|
||||
|
||||
### 5. Start Development
|
||||
### 6. Start Development
|
||||
```bash
|
||||
# Start the development server
|
||||
make dev
|
||||
@@ -185,8 +197,139 @@ make migrate-status
|
||||
4. **Include meaningful messages when creating migrations**
|
||||
5. **Review generated migrations before applying them**
|
||||
|
||||
## Data Seeding for Development
|
||||
|
||||
### Overview
|
||||
|
||||
After setting up your database schema with migrations, you'll need test data to develop and test features. We provide several scripts to populate your database with sample data.
|
||||
|
||||
### Available Seeding Scripts
|
||||
|
||||
#### 1. Create Test Data
|
||||
**Script:** `scripts/create_test_data.py`
|
||||
|
||||
Creates complete test data including vendors, marketplace products, vendor products, themes, and content pages.
|
||||
|
||||
```bash
|
||||
python scripts/create_test_data.py
|
||||
```
|
||||
|
||||
**What it creates:**
|
||||
- 3 test vendors (WizaMart, Fashion Hub, The Book Store)
|
||||
- 20 marketplace products per vendor
|
||||
- Vendor-specific products with pricing
|
||||
- Vendor themes with custom colors
|
||||
- Sample CMS content pages (About, Contact, FAQ, etc.)
|
||||
|
||||
#### 2. Create Inventory Entries
|
||||
**Script:** `scripts/create_inventory.py`
|
||||
|
||||
Creates inventory entries for products that don't have inventory. This is **required** for the shop to function properly, as products with 0 inventory cannot be added to cart.
|
||||
|
||||
```bash
|
||||
python scripts/create_inventory.py
|
||||
```
|
||||
|
||||
**What it does:**
|
||||
- Finds all products without inventory entries
|
||||
- Creates inventory record for each product
|
||||
- Sets 100 units available in "Main Warehouse"
|
||||
- Can be run multiple times (only creates missing entries)
|
||||
|
||||
**Why it's needed:**
|
||||
- Product `available_inventory` is calculated from inventory entries
|
||||
- Empty inventory table = 0 inventory for all products
|
||||
- Add to cart functionality requires `available_inventory > 0`
|
||||
|
||||
#### 3. Create Landing Pages
|
||||
**Script:** `scripts/create_landing_page.py`
|
||||
|
||||
Creates or updates landing pages for vendors with different templates.
|
||||
|
||||
```bash
|
||||
# Interactive mode
|
||||
python scripts/create_landing_page.py
|
||||
|
||||
# Or programmatically in Python
|
||||
from scripts.create_landing_page import create_landing_page
|
||||
create_landing_page('wizamart', template='modern')
|
||||
```
|
||||
|
||||
**Available templates:**
|
||||
- `default` - Clean professional layout with 3-column quick links
|
||||
- `minimal` - Ultra-simple centered design with single CTA
|
||||
- `modern` - Full-screen hero with animations and features
|
||||
- `full` - Maximum features with split-screen hero and stats
|
||||
|
||||
### Complete Setup Workflow
|
||||
|
||||
For a fresh development environment with test data:
|
||||
|
||||
```bash
|
||||
# 1. Setup database schema
|
||||
make migrate-up
|
||||
|
||||
# 2. Create test vendors and products
|
||||
python scripts/create_test_data.py
|
||||
|
||||
# 3. Create inventory (REQUIRED for shop to work)
|
||||
python scripts/create_inventory.py
|
||||
|
||||
# 4. Create landing pages
|
||||
python scripts/create_landing_page.py
|
||||
# Follow interactive prompts to create landing pages
|
||||
|
||||
# 5. Start the server
|
||||
make dev
|
||||
|
||||
# 6. Test the shop
|
||||
# Visit: http://localhost:8000/vendors/wizamart/shop/
|
||||
```
|
||||
|
||||
### Common Issues
|
||||
|
||||
**Problem: Products can't be added to cart**
|
||||
```bash
|
||||
# Solution: Create inventory entries
|
||||
python scripts/create_inventory.py
|
||||
```
|
||||
|
||||
**Problem: Landing page shows 404**
|
||||
```bash
|
||||
# Solution: Create landing page for the vendor
|
||||
python scripts/create_landing_page.py
|
||||
# OR the vendor will auto-redirect to /shop/
|
||||
```
|
||||
|
||||
**Problem: No products showing in shop**
|
||||
```bash
|
||||
# Solution: Create test data
|
||||
python scripts/create_test_data.py
|
||||
```
|
||||
|
||||
### Database Reset (Development Only)
|
||||
|
||||
To start completely fresh:
|
||||
|
||||
```bash
|
||||
# 1. Backup first (optional but recommended)
|
||||
cp wizamart.db wizamart.db.backup
|
||||
|
||||
# 2. Delete database
|
||||
rm wizamart.db
|
||||
|
||||
# 3. Recreate schema
|
||||
make migrate-up
|
||||
|
||||
# 4. Seed all data
|
||||
python scripts/create_test_data.py
|
||||
python scripts/create_inventory.py
|
||||
python scripts/create_landing_page.py
|
||||
```
|
||||
|
||||
## Next Steps
|
||||
|
||||
- [Database Setup Guide](DATABASE_SETUP_GUIDE.md) - Complete database setup guide
|
||||
- [Shop Setup Guide](../guides/shop-setup.md) - Configure vendor storefronts
|
||||
- [Landing Pages Guide](../features/vendor-landing-pages.md) - Customize landing pages
|
||||
- [Database Migrations Guide](../development/database-migrations.md) - Advanced migration workflows
|
||||
- [API Documentation](../api/index.md) - Start building features
|
||||
|
||||
393
docs/troubleshooting/shop-frontend.md
Normal file
393
docs/troubleshooting/shop-frontend.md
Normal file
@@ -0,0 +1,393 @@
|
||||
# Shop Frontend Troubleshooting
|
||||
|
||||
Common issues and solutions for the vendor shop frontend.
|
||||
|
||||
## Cart and Product Issues
|
||||
|
||||
### Products Cannot Be Added to Cart
|
||||
|
||||
**Symptoms:**
|
||||
- "Add to Cart" button is disabled
|
||||
- No response when clicking "Add to Cart"
|
||||
- Console shows `canAddToCart: false`
|
||||
|
||||
**Root Cause:**
|
||||
Products have `available_inventory: 0` because the `inventory` table is empty.
|
||||
|
||||
**How it Works:**
|
||||
- Product's `available_inventory` is a calculated property
|
||||
- It sums `quantity - reserved_quantity` from all `inventory_entries`
|
||||
- If there are no inventory entries, `available_inventory` = 0
|
||||
- The `canAddToCart` check fails when `available_inventory <= 0`
|
||||
|
||||
**Solution:**
|
||||
```bash
|
||||
# Create inventory entries for all products
|
||||
python scripts/create_inventory.py
|
||||
```
|
||||
|
||||
This script:
|
||||
- Finds all products without inventory entries
|
||||
- Creates inventory with 100 units in "Main Warehouse"
|
||||
- Can be run multiple times (only creates missing entries)
|
||||
|
||||
**Verify Fix:**
|
||||
```python
|
||||
# Check a product's inventory
|
||||
from app.core.database import SessionLocal
|
||||
from models.database.product import Product
|
||||
|
||||
db = SessionLocal()
|
||||
product = db.query(Product).first()
|
||||
print(f"Available inventory: {product.available_inventory}")
|
||||
# Should show: Available inventory: 100
|
||||
```
|
||||
|
||||
### Cart is Empty After Adding Products
|
||||
|
||||
**Symptoms:**
|
||||
- Success toast appears: "1 item(s) added to cart!"
|
||||
- Cart count in header doesn't update
|
||||
- Cart page shows 0 items
|
||||
- Console shows `session_1234_abc` but API returns empty cart
|
||||
|
||||
**Root Cause:**
|
||||
Session ID not properly initialized in Alpine.js components.
|
||||
|
||||
**How it Works:**
|
||||
- Cart uses session ID stored in localStorage as `cart_session_id`
|
||||
- `shopLayoutData()` base component initializes `sessionId` in its `init()` method
|
||||
- Child components (product, cart) must call parent `init()` to get `sessionId`
|
||||
- If parent init isn't called, `sessionId` is `undefined`
|
||||
|
||||
**Solution Already Implemented:**
|
||||
The product and cart pages now properly call parent init:
|
||||
|
||||
```javascript
|
||||
// In product.html and cart.html
|
||||
async init() {
|
||||
// Call parent init to set up sessionId
|
||||
if (baseData.init) {
|
||||
baseData.init.call(this);
|
||||
}
|
||||
// Now sessionId is available
|
||||
await this.loadCart();
|
||||
}
|
||||
```
|
||||
|
||||
**Verify Fix:**
|
||||
Open browser console and check for:
|
||||
```
|
||||
🔍 [SHOP] Session ID: session_1763765104510_zc866tt5d
|
||||
```
|
||||
|
||||
If you see `undefined`, the parent init isn't being called properly.
|
||||
|
||||
## Styling and Layout Issues
|
||||
|
||||
### Page Has No Styling / CSS 404 Errors
|
||||
|
||||
**Symptoms:**
|
||||
- Page displays with no styling
|
||||
- Console shows 404 errors:
|
||||
- `/static/css/shared/base.css` not found
|
||||
- `/static/css/vendor/vendor.css` not found
|
||||
- Page is just plain HTML
|
||||
|
||||
**Root Cause:**
|
||||
Template doesn't extend `shop/base.html` and has hardcoded non-existent CSS references.
|
||||
|
||||
**How it Works:**
|
||||
- All shop pages should extend `shop/base.html`
|
||||
- Base template includes Tailwind CSS and shop styles
|
||||
- Standalone HTML pages with `<link>` tags won't work
|
||||
|
||||
**Solution:**
|
||||
Refactor template to extend base:
|
||||
|
||||
```jinja2
|
||||
{# BEFORE: Standalone HTML #}
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<link rel="stylesheet" href="/static/css/shared/base.css"> ❌
|
||||
</head>
|
||||
<body>
|
||||
<!-- content -->
|
||||
</body>
|
||||
</html>
|
||||
|
||||
{# AFTER: Extends base #}
|
||||
{% extends "shop/base.html" %}
|
||||
|
||||
{% block title %}My Page{% endblock %}
|
||||
|
||||
{% block alpine_data %}myComponent(){% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<!-- content -->
|
||||
{% endblock %}
|
||||
```
|
||||
|
||||
**Templates Already Fixed:**
|
||||
- ✅ `shop/product.html` - Refactored to extend base
|
||||
- ✅ `shop/cart.html` - Refactored to extend base
|
||||
- ✅ `shop/products.html` - Already extends base
|
||||
- ✅ `shop/home.html` - Already extends base
|
||||
|
||||
### Images Not Loading / Placeholder Not Showing
|
||||
|
||||
**Symptoms:**
|
||||
- Product images show broken image icon
|
||||
- Console shows 404: `/static/shop/img/placeholder.jpg`
|
||||
- OR images point to fake URLs like `https://wizamart.example.com/images/product-1.jpg`
|
||||
|
||||
**Root Cause:**
|
||||
1. Test data has fake image URLs
|
||||
2. Placeholder file was `.jpg` but contained SVG content
|
||||
|
||||
**How it Works:**
|
||||
- Products have `marketplace_product.image_link` URLs
|
||||
- Template uses fallback: `:src="image || '/static/shop/img/placeholder.svg'"`
|
||||
- `@error` handler switches to placeholder when image fails to load
|
||||
- Browsers won't render SVG content from `.jpg` files
|
||||
|
||||
**Solution Already Implemented:**
|
||||
- Created proper `/static/shop/img/placeholder.svg`
|
||||
- Added `@error` handlers to all image tags:
|
||||
|
||||
```html
|
||||
<img
|
||||
:src="product.image_link || '/static/shop/img/placeholder.svg'"
|
||||
@error="$el.src = '/static/shop/img/placeholder.svg'"
|
||||
alt="Product image"
|
||||
>
|
||||
```
|
||||
|
||||
**Update Test Data (Optional):**
|
||||
```python
|
||||
# Replace fake URLs with real placeholder images
|
||||
import sqlite3
|
||||
conn = sqlite3.connect('wizamart.db')
|
||||
cursor = conn.cursor()
|
||||
|
||||
cursor.execute("""
|
||||
UPDATE marketplace_products
|
||||
SET image_link = NULL
|
||||
WHERE image_link LIKE '%example.com%'
|
||||
""")
|
||||
conn.commit()
|
||||
```
|
||||
|
||||
## Navigation and Routing Issues
|
||||
|
||||
### Product Detail Page Returns 404
|
||||
|
||||
**Symptoms:**
|
||||
- Clicking product shows 404 error
|
||||
- URL is: `/vendors/wizamart/shop/shop/products/4` (double `/shop/`)
|
||||
- Server log shows route not found
|
||||
|
||||
**Root Cause:**
|
||||
Duplicate `/shop` prefix in route definitions when router already has prefix.
|
||||
|
||||
**How it Works:**
|
||||
```python
|
||||
# Router is mounted with prefix
|
||||
app.include_router(shop_pages.router, prefix="/shop")
|
||||
|
||||
# Route decorator should NOT repeat the prefix
|
||||
@router.get("/products/{id}") # ✅ Correct
|
||||
@router.get("/shop/products/{id}") # ❌ Wrong - creates /shop/shop/products/{id}
|
||||
```
|
||||
|
||||
**Solution Already Implemented:**
|
||||
All routes in `shop_pages.py` have been fixed to remove duplicate `/shop/` prefix.
|
||||
|
||||
### Missing `/shop/` in Links
|
||||
|
||||
**Symptoms:**
|
||||
- Links go to `/vendors/wizamart/products` instead of `/vendors/wizamart/shop/products`
|
||||
- 404 errors on navigation
|
||||
- Footer/header links broken
|
||||
|
||||
**Root Cause:**
|
||||
Template links missing `/shop/` prefix after `{{ base_url }}`.
|
||||
|
||||
**Solution:**
|
||||
```jinja2
|
||||
{# WRONG #}
|
||||
<a href="{{ base_url }}products">Products</a>
|
||||
|
||||
{# CORRECT #}
|
||||
<a href="{{ base_url }}shop/products">Products</a>
|
||||
```
|
||||
|
||||
**All Templates Fixed:**
|
||||
- ✅ `shop/base.html` - Header, footer, navigation
|
||||
- ✅ `shop/products.html` - Product links
|
||||
- ✅ `shop/product.html` - Breadcrumbs, related products
|
||||
- ✅ `shop/cart.html` - Continue shopping, checkout
|
||||
- ✅ `shop/errors/404.html` - All fallback links
|
||||
|
||||
## Landing Page Issues
|
||||
|
||||
### Vendor Root Shows 404
|
||||
|
||||
**Symptoms:**
|
||||
- `http://localhost:8000/vendors/wizamart/` returns 404
|
||||
- `/` path not found
|
||||
|
||||
**Root Cause:**
|
||||
No landing page created for vendor.
|
||||
|
||||
**How it Works:**
|
||||
```python
|
||||
# Root handler checks for landing page
|
||||
if has_landing_page():
|
||||
return render_landing_page()
|
||||
else:
|
||||
return redirect("/shop/") # Fallback
|
||||
```
|
||||
|
||||
**Solution:**
|
||||
```bash
|
||||
# Create landing page
|
||||
python scripts/create_landing_page.py
|
||||
# Choose vendor and template
|
||||
```
|
||||
|
||||
**Or Accept Redirect:**
|
||||
The system auto-redirects to `/shop/` if no landing page exists. This is normal behavior.
|
||||
|
||||
### Breadcrumb "Home" Points to Wrong Place
|
||||
|
||||
**Symptoms:**
|
||||
- Clicking "Home" in breadcrumb goes to shop instead of landing page
|
||||
- Want "Home" to point to vendor root (/)
|
||||
|
||||
**Solution Already Implemented:**
|
||||
```jinja2
|
||||
{# Breadcrumb Home link points to vendor root #}
|
||||
<a href="{{ base_url }}">Home</a>
|
||||
|
||||
{# Shop homepage link #}
|
||||
<a href="{{ base_url }}shop/">Shop</a>
|
||||
```
|
||||
|
||||
Navigation pattern:
|
||||
- **Logo click** → `/shop/` (stays in shop for convenience)
|
||||
- **Breadcrumb "Home"** → `/` (returns to landing page/root)
|
||||
- **Header "Home" link** → `/` (returns to landing page/root)
|
||||
|
||||
## Alpine.js / JavaScript Issues
|
||||
|
||||
### Component Data Not Available
|
||||
|
||||
**Symptoms:**
|
||||
- `this.sessionId` is `undefined`
|
||||
- `this.cartCount` doesn't work
|
||||
- Console: "Cannot read property of undefined"
|
||||
|
||||
**Root Cause:**
|
||||
Child component doesn't call parent `init()` method.
|
||||
|
||||
**Solution:**
|
||||
```javascript
|
||||
// Store reference to parent
|
||||
const baseData = shopLayoutData();
|
||||
|
||||
return {
|
||||
...baseData,
|
||||
|
||||
// Child properties
|
||||
items: [],
|
||||
|
||||
// Call parent init
|
||||
async init() {
|
||||
if (baseData.init) {
|
||||
baseData.init.call(this);
|
||||
}
|
||||
// Now parent properties are initialized
|
||||
await this.loadData();
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
### Product ID is Undefined
|
||||
|
||||
**Symptoms:**
|
||||
- API call: `/api/v1/shop/products/undefined`
|
||||
- Console: `productId: undefined`
|
||||
|
||||
**Root Cause:**
|
||||
Product ID not accessible from `this.$el.dataset` when `x-data` is on `<html>` tag.
|
||||
|
||||
**Solution Already Implemented:**
|
||||
Pass via window globals:
|
||||
|
||||
```html
|
||||
{% block extra_scripts %}
|
||||
<script>
|
||||
window.PRODUCT_ID = {{ product_id }};
|
||||
window.VENDOR_ID = {{ vendor.id }};
|
||||
|
||||
Alpine.data('productDetail', () => ({
|
||||
productId: window.PRODUCT_ID,
|
||||
vendorId: window.VENDOR_ID,
|
||||
// ...
|
||||
}));
|
||||
</script>
|
||||
{% endblock %}
|
||||
```
|
||||
|
||||
## Debugging Tips
|
||||
|
||||
### Enable Verbose Logging
|
||||
|
||||
```javascript
|
||||
// In shop-layout.js, the shopLog is already configured
|
||||
// Check browser console for:
|
||||
🛒 [SHOP] Shop layout initializing...
|
||||
🔍 [SHOP] Session ID: session_xxx
|
||||
[SHOP] Adding to cart: {...}
|
||||
[SHOP] Cart loaded: 3 items
|
||||
```
|
||||
|
||||
### Check Session ID
|
||||
|
||||
```javascript
|
||||
// In browser console
|
||||
localStorage.getItem('cart_session_id')
|
||||
// Should show: "session_1763765104510_zc866tt5d"
|
||||
```
|
||||
|
||||
### Inspect Product Data
|
||||
|
||||
```javascript
|
||||
// In browser console on product page
|
||||
Alpine.$data(document.querySelector('[x-data]')).product
|
||||
// Shows full product object with inventory
|
||||
```
|
||||
|
||||
### Check API Responses
|
||||
|
||||
In browser Network tab, filter by "shop" and check:
|
||||
- GET `/api/v1/shop/products` - Should return products array
|
||||
- GET `/api/v1/shop/cart/{session_id}` - Should return cart items
|
||||
- POST `/api/v1/shop/cart/{session_id}/items` - Should return success
|
||||
|
||||
## Getting Help
|
||||
|
||||
1. Check this guide first
|
||||
2. Check browser console for errors
|
||||
3. Check server logs for API errors
|
||||
4. Verify database has inventory entries
|
||||
5. Ensure all templates extend `shop/base.html`
|
||||
6. Check that session ID is initialized
|
||||
|
||||
If still stuck, provide:
|
||||
- Browser console output
|
||||
- Server log excerpt
|
||||
- Network tab showing failed requests
|
||||
- Steps to reproduce
|
||||
Reference in New Issue
Block a user