# Shop Frontend Troubleshooting

Common issues and solutions for the store 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/store/store.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://orion.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('orion.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: `/stores/orion/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 `/stores/orion/products` instead of `/stores/orion/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

### Store Root Shows 404

**Symptoms:**
- `http://localhost:8000/stores/orion/` returns 404
- `/` path not found

**Root Cause:**
No landing page created for store.

**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 store 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 store root (/)

**Solution Already Implemented:**
```jinja2
{# Breadcrumb Home link points to store 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.STORE_ID = {{ store.id }};

Alpine.data('productDetail', () => ({
    productId: window.PRODUCT_ID,
    storeId: window.STORE_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
