fix(ui): inject window.FRONTEND_TYPE from server + rename SHOP→STOREFRONT
Server now injects window.FRONTEND_TYPE in all base templates via get_context_for_frontend(). Both log-config.js and dev-toolbar.js read this instead of guessing from URL paths, fixing: - UNKNOWN prefix on merchant pages - Incorrect detection on custom domains/subdomains in prod Also adds frontend_type to login page contexts (admin, merchant, store). Renames all [SHOP] logger prefixes to [STOREFRONT] across 7 files (storefront-layout.js + 6 storefront templates). Adds 'merchant' and 'storefront' to log-config.js frontend detection, log levels, and logger selection. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -208,7 +208,7 @@ document.addEventListener('alpine:init', () => {
|
||||
|
||||
// Initialize
|
||||
async init() {
|
||||
console.log('[SHOP] Cart page initializing...');
|
||||
console.log('[STOREFRONT] Cart page initializing...');
|
||||
|
||||
// Call parent init to set up sessionId
|
||||
if (baseData.init) {
|
||||
@@ -223,17 +223,17 @@ document.addEventListener('alpine:init', () => {
|
||||
this.loading = true;
|
||||
|
||||
try {
|
||||
console.log(`[SHOP] Loading cart for session ${this.sessionId}...`);
|
||||
console.log(`[STOREFRONT] Loading cart for session ${this.sessionId}...`);
|
||||
const response = await fetch(`/api/v1/storefront/cart/${this.sessionId}`);
|
||||
|
||||
if (response.ok) {
|
||||
const data = await response.json();
|
||||
this.items = data.items || [];
|
||||
this.cartCount = this.totalItems;
|
||||
console.log('[SHOP] Cart loaded:', this.items.length, 'items');
|
||||
console.log('[STOREFRONT] Cart loaded:', this.items.length, 'items');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('[SHOP] Failed to load cart:', error);
|
||||
console.error('[STOREFRONT] Failed to load cart:', error);
|
||||
this.showToast('Failed to load cart', 'error');
|
||||
} finally {
|
||||
this.loading = false;
|
||||
@@ -249,7 +249,7 @@ document.addEventListener('alpine:init', () => {
|
||||
this.updating = true;
|
||||
|
||||
try {
|
||||
console.log('[SHOP] Updating quantity:', productId, newQuantity);
|
||||
console.log('[STOREFRONT] Updating quantity:', productId, newQuantity);
|
||||
const response = await fetch(
|
||||
`/api/v1/storefront/cart/${this.sessionId}/items/${productId}`,
|
||||
{
|
||||
@@ -268,7 +268,7 @@ document.addEventListener('alpine:init', () => {
|
||||
throw new Error('Failed to update quantity');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('[SHOP] Update quantity error:', error);
|
||||
console.error('[STOREFRONT] Update quantity error:', error);
|
||||
this.showToast('Failed to update quantity', 'error');
|
||||
} finally {
|
||||
this.updating = false;
|
||||
@@ -280,7 +280,7 @@ document.addEventListener('alpine:init', () => {
|
||||
this.updating = true;
|
||||
|
||||
try {
|
||||
console.log('[SHOP] Removing item:', productId);
|
||||
console.log('[STOREFRONT] Removing item:', productId);
|
||||
const response = await fetch(
|
||||
`/api/v1/storefront/cart/${this.sessionId}/items/${productId}`,
|
||||
{
|
||||
@@ -295,7 +295,7 @@ document.addEventListener('alpine:init', () => {
|
||||
throw new Error('Failed to remove item');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('[SHOP] Remove item error:', error);
|
||||
console.error('[STOREFRONT] Remove item error:', error);
|
||||
this.showToast('Failed to remove item', 'error');
|
||||
} finally {
|
||||
this.updating = false;
|
||||
|
||||
@@ -187,8 +187,8 @@ document.addEventListener('alpine:init', () => {
|
||||
},
|
||||
|
||||
async init() {
|
||||
console.log('[SHOP] Category page initializing...');
|
||||
console.log('[SHOP] Category slug:', this.categorySlug);
|
||||
console.log('[STOREFRONT] Category page initializing...');
|
||||
console.log('[STOREFRONT] Category slug:', this.categorySlug);
|
||||
|
||||
// Convert slug to display name
|
||||
this.categoryName = this.categorySlug
|
||||
@@ -213,7 +213,7 @@ document.addEventListener('alpine:init', () => {
|
||||
params.append('sort', this.sortBy);
|
||||
}
|
||||
|
||||
console.log(`[SHOP] Loading category products from /api/v1/storefront/products?${params}`);
|
||||
console.log(`[STOREFRONT] Loading category products from /api/v1/storefront/products?${params}`);
|
||||
|
||||
const response = await fetch(`/api/v1/storefront/products?${params}`);
|
||||
|
||||
@@ -223,12 +223,12 @@ document.addEventListener('alpine:init', () => {
|
||||
|
||||
const data = await response.json();
|
||||
|
||||
console.log(`[SHOP] Loaded ${data.products.length} products (total: ${data.total})`);
|
||||
console.log(`[STOREFRONT] Loaded ${data.products.length} products (total: ${data.total})`);
|
||||
|
||||
this.products = data.products;
|
||||
this.total = data.total;
|
||||
} catch (error) {
|
||||
console.error('[SHOP] Failed to load category products:', error);
|
||||
console.error('[STOREFRONT] Failed to load category products:', error);
|
||||
this.showToast('Failed to load products', 'error');
|
||||
} finally {
|
||||
this.loading = false;
|
||||
@@ -243,7 +243,7 @@ document.addEventListener('alpine:init', () => {
|
||||
},
|
||||
|
||||
async addToCart(product) {
|
||||
console.log('[SHOP] Adding to cart:', product);
|
||||
console.log('[STOREFRONT] Adding to cart:', product);
|
||||
|
||||
try {
|
||||
const url = `/api/v1/storefront/cart/${this.sessionId}/items`;
|
||||
@@ -262,16 +262,16 @@ document.addEventListener('alpine:init', () => {
|
||||
|
||||
if (response.ok) {
|
||||
const result = await response.json();
|
||||
console.log('[SHOP] Add to cart success:', result);
|
||||
console.log('[STOREFRONT] Add to cart success:', result);
|
||||
this.cartCount += 1;
|
||||
this.showToast(`${product.marketplace_product.title} added to cart`, 'success');
|
||||
} else {
|
||||
const error = await response.json();
|
||||
console.error('[SHOP] Add to cart error:', error);
|
||||
console.error('[STOREFRONT] Add to cart error:', error);
|
||||
this.showToast(error.message || 'Failed to add to cart', 'error');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('[SHOP] Add to cart exception:', error);
|
||||
console.error('[STOREFRONT] Add to cart exception:', error);
|
||||
this.showToast('Failed to add to cart', 'error');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -256,16 +256,16 @@ document.addEventListener('alpine:init', () => {
|
||||
|
||||
// Initialize
|
||||
async init() {
|
||||
console.log('[SHOP] Product detail page initializing...');
|
||||
console.log('[STOREFRONT] Product detail page initializing...');
|
||||
|
||||
// Call parent init to set up sessionId
|
||||
if (baseData.init) {
|
||||
baseData.init.call(this);
|
||||
}
|
||||
|
||||
console.log('[SHOP] Product ID:', this.productId);
|
||||
console.log('[SHOP] Store ID:', this.storeId);
|
||||
console.log('[SHOP] Session ID:', this.sessionId);
|
||||
console.log('[STOREFRONT] Product ID:', this.productId);
|
||||
console.log('[STOREFRONT] Store ID:', this.storeId);
|
||||
console.log('[STOREFRONT] Session ID:', this.sessionId);
|
||||
|
||||
await this.loadProduct();
|
||||
},
|
||||
@@ -275,7 +275,7 @@ document.addEventListener('alpine:init', () => {
|
||||
this.loading = true;
|
||||
|
||||
try {
|
||||
console.log(`[SHOP] Loading product ${this.productId}...`);
|
||||
console.log(`[STOREFRONT] Loading product ${this.productId}...`);
|
||||
const response = await fetch(`/api/v1/storefront/products/${this.productId}`);
|
||||
|
||||
if (!response.ok) {
|
||||
@@ -283,7 +283,7 @@ document.addEventListener('alpine:init', () => {
|
||||
}
|
||||
|
||||
this.product = await response.json();
|
||||
console.log('[SHOP] Product loaded:', this.product);
|
||||
console.log('[STOREFRONT] Product loaded:', this.product);
|
||||
|
||||
// Set default image
|
||||
if (this.product?.marketplace_product?.image_link) {
|
||||
@@ -297,7 +297,7 @@ document.addEventListener('alpine:init', () => {
|
||||
await this.loadRelatedProducts();
|
||||
|
||||
} catch (error) {
|
||||
console.error('[SHOP] Failed to load product:', error);
|
||||
console.error('[STOREFRONT] Failed to load product:', error);
|
||||
this.showToast('Failed to load product', 'error');
|
||||
// Redirect back to products after error
|
||||
setTimeout(() => {
|
||||
@@ -320,10 +320,10 @@ document.addEventListener('alpine:init', () => {
|
||||
.filter(p => p.id !== parseInt(this.productId))
|
||||
.slice(0, 4);
|
||||
|
||||
console.log('[SHOP] Loaded related products:', this.relatedProducts.length);
|
||||
console.log('[STOREFRONT] Loaded related products:', this.relatedProducts.length);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('[SHOP] Failed to load related products:', error);
|
||||
console.error('[STOREFRONT] Failed to load related products:', error);
|
||||
}
|
||||
},
|
||||
|
||||
@@ -356,7 +356,7 @@ document.addEventListener('alpine:init', () => {
|
||||
// Add to cart
|
||||
async addToCart() {
|
||||
if (!this.canAddToCart) {
|
||||
console.warn('[SHOP] Cannot add to cart:', {
|
||||
console.warn('[STOREFRONT] Cannot add to cart:', {
|
||||
canAddToCart: this.canAddToCart,
|
||||
isActive: this.product?.is_active,
|
||||
inventory: this.product?.available_inventory,
|
||||
@@ -374,7 +374,7 @@ document.addEventListener('alpine:init', () => {
|
||||
quantity: this.quantity
|
||||
};
|
||||
|
||||
console.log('[SHOP] Adding to cart:', {
|
||||
console.log('[STOREFRONT] Adding to cart:', {
|
||||
url,
|
||||
sessionId: this.sessionId,
|
||||
productId: this.productId,
|
||||
@@ -390,14 +390,14 @@ document.addEventListener('alpine:init', () => {
|
||||
body: JSON.stringify(payload)
|
||||
});
|
||||
|
||||
console.log('[SHOP] Add to cart response:', {
|
||||
console.log('[STOREFRONT] Add to cart response:', {
|
||||
status: response.status,
|
||||
ok: response.ok
|
||||
});
|
||||
|
||||
if (response.ok) {
|
||||
const result = await response.json();
|
||||
console.log('[SHOP] Add to cart success:', result);
|
||||
console.log('[STOREFRONT] Add to cart success:', result);
|
||||
|
||||
this.cartCount += this.quantity;
|
||||
this.showToast(
|
||||
@@ -409,11 +409,11 @@ document.addEventListener('alpine:init', () => {
|
||||
this.quantity = this.product?.min_quantity || 1;
|
||||
} else {
|
||||
const error = await response.json();
|
||||
console.error('[SHOP] Add to cart error response:', error);
|
||||
console.error('[STOREFRONT] Add to cart error response:', error);
|
||||
throw new Error(error.detail || 'Failed to add to cart');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('[SHOP] Add to cart exception:', error);
|
||||
console.error('[STOREFRONT] Add to cart exception:', error);
|
||||
this.showToast(error.message || 'Failed to add to cart', 'error');
|
||||
} finally {
|
||||
this.addingToCart = false;
|
||||
|
||||
@@ -160,7 +160,7 @@ document.addEventListener('alpine:init', () => {
|
||||
},
|
||||
|
||||
async init() {
|
||||
console.log('[SHOP] Products page initializing...');
|
||||
console.log('[STOREFRONT] Products page initializing...');
|
||||
await this.loadProducts();
|
||||
},
|
||||
|
||||
@@ -178,7 +178,7 @@ document.addEventListener('alpine:init', () => {
|
||||
params.append('search', this.filters.search);
|
||||
}
|
||||
|
||||
console.log(`[SHOP] Loading products from /api/v1/storefront/products?${params}`);
|
||||
console.log(`[STOREFRONT] Loading products from /api/v1/storefront/products?${params}`);
|
||||
|
||||
const response = await fetch(`/api/v1/storefront/products?${params}`);
|
||||
|
||||
@@ -188,12 +188,12 @@ document.addEventListener('alpine:init', () => {
|
||||
|
||||
const data = await response.json();
|
||||
|
||||
console.log(`[SHOP] Loaded ${data.products.length} products (total: ${data.total})`);
|
||||
console.log(`[STOREFRONT] Loaded ${data.products.length} products (total: ${data.total})`);
|
||||
|
||||
this.products = data.products;
|
||||
this.pagination.total = data.total;
|
||||
} catch (error) {
|
||||
console.error('[SHOP] Failed to load products:', error);
|
||||
console.error('[STOREFRONT] Failed to load products:', error);
|
||||
this.showToast('Failed to load products', 'error');
|
||||
} finally {
|
||||
this.loading = false;
|
||||
@@ -208,7 +208,7 @@ document.addEventListener('alpine:init', () => {
|
||||
// formatPrice is inherited from storefrontLayoutData() via spread operator
|
||||
|
||||
async addToCart(product) {
|
||||
console.log('[SHOP] Adding to cart:', product);
|
||||
console.log('[STOREFRONT] Adding to cart:', product);
|
||||
|
||||
try {
|
||||
const url = `/api/v1/storefront/cart/${this.sessionId}/items`;
|
||||
@@ -227,16 +227,16 @@ document.addEventListener('alpine:init', () => {
|
||||
|
||||
if (response.ok) {
|
||||
const result = await response.json();
|
||||
console.log('[SHOP] Add to cart success:', result);
|
||||
console.log('[STOREFRONT] Add to cart success:', result);
|
||||
this.cartCount += 1;
|
||||
this.showToast(`${product.marketplace_product.title} added to cart`, 'success');
|
||||
} else {
|
||||
const error = await response.json();
|
||||
console.error('[SHOP] Add to cart error:', error);
|
||||
console.error('[STOREFRONT] Add to cart error:', error);
|
||||
this.showToast(error.message || 'Failed to add to cart', 'error');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('[SHOP] Add to cart exception:', error);
|
||||
console.error('[STOREFRONT] Add to cart exception:', error);
|
||||
this.showToast('Failed to add to cart', 'error');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -212,7 +212,7 @@ document.addEventListener('alpine:init', () => {
|
||||
},
|
||||
|
||||
async init() {
|
||||
console.log('[SHOP] Search page initializing...');
|
||||
console.log('[STOREFRONT] Search page initializing...');
|
||||
|
||||
// Check for query parameter in URL
|
||||
const urlParams = new URLSearchParams(window.location.search);
|
||||
@@ -254,7 +254,7 @@ document.addEventListener('alpine:init', () => {
|
||||
limit: this.perPage
|
||||
});
|
||||
|
||||
console.log(`[SHOP] Searching: /api/v1/storefront/products/search?${params}`);
|
||||
console.log(`[STOREFRONT] Searching: /api/v1/storefront/products/search?${params}`);
|
||||
|
||||
const response = await fetch(`/api/v1/storefront/products/search?${params}`);
|
||||
|
||||
@@ -264,12 +264,12 @@ document.addEventListener('alpine:init', () => {
|
||||
|
||||
const data = await response.json();
|
||||
|
||||
console.log(`[SHOP] Search found ${data.total} results`);
|
||||
console.log(`[STOREFRONT] Search found ${data.total} results`);
|
||||
|
||||
this.products = data.products;
|
||||
this.total = data.total;
|
||||
} catch (error) {
|
||||
console.error('[SHOP] Search failed:', error);
|
||||
console.error('[STOREFRONT] Search failed:', error);
|
||||
this.showToast('Search failed. Please try again.', 'error');
|
||||
this.products = [];
|
||||
this.total = 0;
|
||||
@@ -289,7 +289,7 @@ document.addEventListener('alpine:init', () => {
|
||||
},
|
||||
|
||||
async addToCart(product) {
|
||||
console.log('[SHOP] Adding to cart:', product);
|
||||
console.log('[STOREFRONT] Adding to cart:', product);
|
||||
|
||||
try {
|
||||
const url = `/api/v1/storefront/cart/${this.sessionId}/items`;
|
||||
@@ -308,16 +308,16 @@ document.addEventListener('alpine:init', () => {
|
||||
|
||||
if (response.ok) {
|
||||
const result = await response.json();
|
||||
console.log('[SHOP] Add to cart success:', result);
|
||||
console.log('[STOREFRONT] Add to cart success:', result);
|
||||
this.cartCount += 1;
|
||||
this.showToast(`${product.marketplace_product?.title || 'Product'} added to cart`, 'success');
|
||||
} else {
|
||||
const error = await response.json();
|
||||
console.error('[SHOP] Add to cart error:', error);
|
||||
console.error('[STOREFRONT] Add to cart error:', error);
|
||||
this.showToast(error.message || 'Failed to add to cart', 'error');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('[SHOP] Add to cart exception:', error);
|
||||
console.error('[STOREFRONT] Add to cart exception:', error);
|
||||
this.showToast('Failed to add to cart', 'error');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -143,7 +143,7 @@ document.addEventListener('alpine:init', () => {
|
||||
isLoggedIn: false,
|
||||
|
||||
async init() {
|
||||
console.log('[SHOP] Wishlist page initializing...');
|
||||
console.log('[STOREFRONT] Wishlist page initializing...');
|
||||
|
||||
// Check if user is logged in
|
||||
this.isLoggedIn = await this.checkLoginStatus();
|
||||
@@ -168,7 +168,7 @@ document.addEventListener('alpine:init', () => {
|
||||
this.loading = true;
|
||||
|
||||
try {
|
||||
console.log('[SHOP] Loading wishlist...');
|
||||
console.log('[STOREFRONT] Loading wishlist...');
|
||||
|
||||
const response = await fetch('/api/v1/storefront/wishlist');
|
||||
|
||||
@@ -182,11 +182,11 @@ document.addEventListener('alpine:init', () => {
|
||||
|
||||
const data = await response.json();
|
||||
|
||||
console.log(`[SHOP] Loaded ${data.items?.length || 0} wishlist items`);
|
||||
console.log(`[STOREFRONT] Loaded ${data.items?.length || 0} wishlist items`);
|
||||
|
||||
this.items = data.items || [];
|
||||
} catch (error) {
|
||||
console.error('[SHOP] Failed to load wishlist:', error);
|
||||
console.error('[STOREFRONT] Failed to load wishlist:', error);
|
||||
this.showToast('Failed to load wishlist', 'error');
|
||||
} finally {
|
||||
this.loading = false;
|
||||
@@ -195,7 +195,7 @@ document.addEventListener('alpine:init', () => {
|
||||
|
||||
async removeFromWishlist(item) {
|
||||
try {
|
||||
console.log('[SHOP] Removing from wishlist:', item);
|
||||
console.log('[STOREFRONT] Removing from wishlist:', item);
|
||||
|
||||
const response = await fetch(`/api/v1/storefront/wishlist/${item.id}`, {
|
||||
method: 'DELETE'
|
||||
@@ -208,13 +208,13 @@ document.addEventListener('alpine:init', () => {
|
||||
throw new Error('Failed to remove from wishlist');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('[SHOP] Failed to remove from wishlist:', error);
|
||||
console.error('[STOREFRONT] Failed to remove from wishlist:', error);
|
||||
this.showToast('Failed to remove from wishlist', 'error');
|
||||
}
|
||||
},
|
||||
|
||||
async addToCart(product) {
|
||||
console.log('[SHOP] Adding to cart:', product);
|
||||
console.log('[STOREFRONT] Adding to cart:', product);
|
||||
|
||||
try {
|
||||
const url = `/api/v1/storefront/cart/${this.sessionId}/items`;
|
||||
@@ -233,16 +233,16 @@ document.addEventListener('alpine:init', () => {
|
||||
|
||||
if (response.ok) {
|
||||
const result = await response.json();
|
||||
console.log('[SHOP] Add to cart success:', result);
|
||||
console.log('[STOREFRONT] Add to cart success:', result);
|
||||
this.cartCount += 1;
|
||||
this.showToast(`${product.marketplace_product?.title || 'Product'} added to cart`, 'success');
|
||||
} else {
|
||||
const error = await response.json();
|
||||
console.error('[SHOP] Add to cart error:', error);
|
||||
console.error('[STOREFRONT] Add to cart error:', error);
|
||||
this.showToast(error.message || 'Failed to add to cart', 'error');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('[SHOP] Add to cart exception:', error);
|
||||
console.error('[STOREFRONT] Add to cart exception:', error);
|
||||
this.showToast('Failed to add to cart', 'error');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -62,6 +62,7 @@ async def admin_login_page(
|
||||
context = {
|
||||
"request": request,
|
||||
"current_language": language,
|
||||
"frontend_type": "admin",
|
||||
**get_jinja2_globals(language),
|
||||
}
|
||||
return templates.TemplateResponse("tenancy/admin/login.html", context)
|
||||
|
||||
@@ -72,6 +72,7 @@ async def merchant_login_page(
|
||||
context = {
|
||||
"request": request,
|
||||
"current_language": language,
|
||||
"frontend_type": "merchant",
|
||||
**get_jinja2_globals(language),
|
||||
}
|
||||
return templates.TemplateResponse("tenancy/merchant/login.html", context)
|
||||
|
||||
@@ -5,11 +5,11 @@
|
||||
* Works with store-specific themes
|
||||
*/
|
||||
|
||||
const shopLog = {
|
||||
info: (...args) => console.info('🛒 [SHOP]', ...args),
|
||||
warn: (...args) => console.warn('⚠️ [SHOP]', ...args),
|
||||
error: (...args) => console.error('❌ [SHOP]', ...args),
|
||||
debug: (...args) => console.log('🔍 [SHOP]', ...args)
|
||||
const shopLog = window.LogConfig?.createLogger('STOREFRONT') || {
|
||||
info: (...args) => console.info('🛒 [STOREFRONT]', ...args),
|
||||
warn: (...args) => console.warn('⚠️ [STOREFRONT]', ...args),
|
||||
error: (...args) => console.error('❌ [STOREFRONT]', ...args),
|
||||
debug: (...args) => console.log('🔍 [STOREFRONT]', ...args)
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -149,6 +149,9 @@ def get_context_for_frontend(
|
||||
# Pass enabled module codes to templates for conditional rendering
|
||||
context["enabled_modules"] = enabled_module_codes
|
||||
|
||||
# Pass frontend type to templates (used by JS for logging, dev toolbar, etc.)
|
||||
context["frontend_type"] = frontend_type.value
|
||||
|
||||
# For storefront, build nav menu structure from module declarations
|
||||
if frontend_type == FrontendType.STOREFRONT:
|
||||
from app.modules.core.services.menu_discovery_service import (
|
||||
|
||||
@@ -100,6 +100,9 @@
|
||||
|
||||
<!-- Core Scripts - ORDER MATTERS! -->
|
||||
|
||||
<!-- 0. Frontend type (server-injected, used by log-config and dev-toolbar) -->
|
||||
<script>window.FRONTEND_TYPE = '{{ frontend_type | default("admin") }}';</script>
|
||||
|
||||
<!-- 1. FIRST: Log Configuration -->
|
||||
<script defer src="{{ url_for('static', path='shared/js/log-config.js') }}"></script>
|
||||
|
||||
|
||||
@@ -50,6 +50,9 @@
|
||||
|
||||
<!-- Core Scripts - ORDER MATTERS! -->
|
||||
|
||||
<!-- 0. Frontend type (server-injected, used by log-config and dev-toolbar) -->
|
||||
<script>window.FRONTEND_TYPE = '{{ frontend_type | default("merchant") }}';</script>
|
||||
|
||||
<!-- 1. FIRST: Log Configuration -->
|
||||
<script defer src="{{ url_for('static', path='shared/js/log-config.js') }}"></script>
|
||||
|
||||
|
||||
@@ -54,6 +54,9 @@
|
||||
|
||||
<!-- Core Scripts - ORDER MATTERS! -->
|
||||
|
||||
<!-- 0. Frontend type (server-injected, used by log-config and dev-toolbar) -->
|
||||
<script>window.FRONTEND_TYPE = '{{ frontend_type | default("store") }}';</script>
|
||||
|
||||
<!-- 1. FIRST: Log Configuration -->
|
||||
<script defer src="{{ url_for('static', path='shared/js/log-config.js') }}"></script>
|
||||
|
||||
|
||||
@@ -349,6 +349,9 @@
|
||||
|
||||
{# JavaScript Loading Order (CRITICAL - must be in this order) #}
|
||||
|
||||
{# 0. Frontend type (server-injected, used by log-config and dev-toolbar) #}
|
||||
<script>window.FRONTEND_TYPE = '{{ frontend_type | default("storefront") }}';</script>
|
||||
|
||||
{# 1. Log Configuration (must load first) #}
|
||||
<script defer src="{{ url_for('static', path='shared/js/log-config.js') }}"></script>
|
||||
|
||||
|
||||
@@ -286,11 +286,11 @@
|
||||
}
|
||||
|
||||
function detectFrontend() {
|
||||
// Prefer server-injected value (set in base templates)
|
||||
if (window.FRONTEND_TYPE) return window.FRONTEND_TYPE;
|
||||
|
||||
// Fallback for pages without base template (e.g., API docs)
|
||||
var path = window.location.pathname;
|
||||
if (path.startsWith('/store/') || path === '/store') return 'store';
|
||||
if (path.startsWith('/admin/') || path === '/admin') return 'admin';
|
||||
if (path.indexOf('/merchants/') !== -1) return 'merchant';
|
||||
if (path.indexOf('/storefront/') !== -1) return 'storefront';
|
||||
if (path.startsWith('/api/')) return 'api';
|
||||
return 'unknown';
|
||||
}
|
||||
|
||||
@@ -43,14 +43,11 @@ const LOG_LEVELS = {
|
||||
|
||||
/**
|
||||
* Detect which frontend we're in based on URL path
|
||||
* @returns {string} 'admin' | 'store' | 'shop' | 'unknown'
|
||||
* @returns {string} 'admin' | 'store' | 'merchant' | 'storefront' | 'unknown'
|
||||
*/
|
||||
function detectFrontend() {
|
||||
const path = window.location.pathname;
|
||||
|
||||
if (path.startsWith('/admin')) return 'admin';
|
||||
if (path.startsWith('/store')) return 'store';
|
||||
if (path.startsWith('/shop')) return 'shop';
|
||||
// Prefer server-injected value (set in base templates before this script loads)
|
||||
if (window.FRONTEND_TYPE) return window.FRONTEND_TYPE;
|
||||
|
||||
return 'unknown';
|
||||
}
|
||||
@@ -94,9 +91,13 @@ const DEFAULT_LOG_LEVELS = {
|
||||
development: LOG_LEVELS.DEBUG,
|
||||
production: LOG_LEVELS.INFO // Stores might need more logging
|
||||
},
|
||||
shop: {
|
||||
merchant: {
|
||||
development: LOG_LEVELS.DEBUG,
|
||||
production: LOG_LEVELS.ERROR // Shop frontend: minimal logging in production
|
||||
production: LOG_LEVELS.INFO // Merchant portal: same as store
|
||||
},
|
||||
storefront: {
|
||||
development: LOG_LEVELS.DEBUG,
|
||||
production: LOG_LEVELS.ERROR // Storefront: minimal logging in production
|
||||
},
|
||||
unknown: {
|
||||
development: LOG_LEVELS.DEBUG,
|
||||
@@ -275,10 +276,10 @@ const storeLoggers = {
|
||||
};
|
||||
|
||||
// ============================================================================
|
||||
// PRE-CONFIGURED LOGGERS FOR SHOP FRONTEND
|
||||
// PRE-CONFIGURED LOGGERS FOR STOREFRONT
|
||||
// ============================================================================
|
||||
|
||||
const shopLoggers = {
|
||||
const storefrontLoggers = {
|
||||
// Product browsing
|
||||
catalog: createLogger('CATALOG', ACTIVE_LOG_LEVEL),
|
||||
product: createLogger('PRODUCT', ACTIVE_LOG_LEVEL),
|
||||
@@ -309,8 +310,10 @@ function getLoggers() {
|
||||
return adminLoggers;
|
||||
case 'store':
|
||||
return storeLoggers;
|
||||
case 'shop':
|
||||
return shopLoggers;
|
||||
case 'merchant':
|
||||
return storeLoggers; // Merchant portal reuses store logger set
|
||||
case 'storefront':
|
||||
return storefrontLoggers;
|
||||
default:
|
||||
return {}; // Empty object, use createLogger instead
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user