refactor: rename shopLayoutData to storefrontLayoutData
Some checks failed
Some checks failed
Align Alpine.js base component naming with storefront terminology. Updated across all storefront JS, templates, and documentation. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -175,7 +175,7 @@
|
||||
<script>
|
||||
document.addEventListener('alpine:init', () => {
|
||||
Alpine.data('shoppingCart', () => {
|
||||
const baseData = shopLayoutData();
|
||||
const baseData = storefrontLayoutData();
|
||||
|
||||
return {
|
||||
...baseData,
|
||||
|
||||
@@ -146,7 +146,7 @@ window.CATEGORY_SLUG = '{{ category_slug | default("") }}';
|
||||
|
||||
document.addEventListener('alpine:init', () => {
|
||||
Alpine.data('shopCategory', () => ({
|
||||
...shopLayoutData(),
|
||||
...storefrontLayoutData(),
|
||||
|
||||
// Data
|
||||
categorySlug: window.CATEGORY_SLUG,
|
||||
|
||||
@@ -218,7 +218,7 @@ window.STORE_ID = {{ store.id }};
|
||||
|
||||
document.addEventListener('alpine:init', () => {
|
||||
Alpine.data('productDetail', () => {
|
||||
const baseData = shopLayoutData();
|
||||
const baseData = storefrontLayoutData();
|
||||
|
||||
return {
|
||||
...baseData,
|
||||
|
||||
@@ -145,7 +145,7 @@
|
||||
<script>
|
||||
document.addEventListener('alpine:init', () => {
|
||||
Alpine.data('shopProducts', () => ({
|
||||
...shopLayoutData(),
|
||||
...storefrontLayoutData(),
|
||||
products: [],
|
||||
loading: true,
|
||||
filters: {
|
||||
@@ -205,7 +205,7 @@ document.addEventListener('alpine:init', () => {
|
||||
this.loadProducts();
|
||||
},
|
||||
|
||||
// formatPrice is inherited from shopLayoutData() via spread operator
|
||||
// formatPrice is inherited from storefrontLayoutData() via spread operator
|
||||
|
||||
async addToCart(product) {
|
||||
console.log('[SHOP] Adding to cart:', product);
|
||||
|
||||
@@ -170,7 +170,7 @@
|
||||
<script>
|
||||
document.addEventListener('alpine:init', () => {
|
||||
Alpine.data('shopSearch', () => ({
|
||||
...shopLayoutData(),
|
||||
...storefrontLayoutData(),
|
||||
|
||||
// Search state
|
||||
searchInput: '',
|
||||
|
||||
@@ -135,7 +135,7 @@
|
||||
<script>
|
||||
document.addEventListener('alpine:init', () => {
|
||||
Alpine.data('shopWishlist', () => ({
|
||||
...shopLayoutData(),
|
||||
...storefrontLayoutData(),
|
||||
|
||||
// Data
|
||||
items: [],
|
||||
|
||||
@@ -477,7 +477,7 @@
|
||||
<script>
|
||||
function checkoutPage() {
|
||||
return {
|
||||
...shopLayoutData(),
|
||||
...storefrontLayoutData(),
|
||||
|
||||
// State
|
||||
loading: true,
|
||||
@@ -595,8 +595,8 @@ function checkoutPage() {
|
||||
console.log('[CHECKOUT] Initializing...');
|
||||
|
||||
// Initialize session
|
||||
if (typeof shopLayoutData === 'function') {
|
||||
const baseData = shopLayoutData();
|
||||
if (typeof storefrontLayoutData === 'function') {
|
||||
const baseData = storefrontLayoutData();
|
||||
if (baseData.init) {
|
||||
baseData.init.call(this);
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
{% block meta_description %}{{ page.meta_description or store.description or store.name }}{% endblock %}
|
||||
|
||||
{# Alpine.js component #}
|
||||
{% block alpine_data %}shopLayoutData(){% endblock %}
|
||||
{% block alpine_data %}storefrontLayoutData(){% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="min-h-screen">
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
{% block meta_description %}{{ page.meta_description or store.description or store.name }}{% endblock %}
|
||||
|
||||
{# Alpine.js component #}
|
||||
{% block alpine_data %}shopLayoutData(){% endblock %}
|
||||
{% block alpine_data %}storefrontLayoutData(){% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="min-h-screen">
|
||||
|
||||
@@ -16,7 +16,7 @@ const shopLog = {
|
||||
* Shop Layout Data
|
||||
* Base Alpine.js component for shop pages
|
||||
*/
|
||||
function shopLayoutData() {
|
||||
function storefrontLayoutData() {
|
||||
return {
|
||||
// Theme state
|
||||
dark: localStorage.getItem('shop-theme') === 'dark',
|
||||
@@ -243,7 +243,7 @@ function shopLayoutData() {
|
||||
}
|
||||
|
||||
// Make available globally
|
||||
window.shopLayoutData = shopLayoutData;
|
||||
window.storefrontLayoutData = storefrontLayoutData;
|
||||
|
||||
/**
|
||||
* Language Selector Component
|
||||
|
||||
@@ -318,7 +318,7 @@
|
||||
<script>
|
||||
function addressesPage() {
|
||||
return {
|
||||
...shopLayoutData(),
|
||||
...storefrontLayoutData(),
|
||||
|
||||
// State
|
||||
loading: true,
|
||||
|
||||
@@ -163,7 +163,7 @@
|
||||
<script>
|
||||
function accountDashboard() {
|
||||
return {
|
||||
...shopLayoutData(),
|
||||
...storefrontLayoutData(),
|
||||
showLogoutModal: false,
|
||||
|
||||
confirmLogout() {
|
||||
|
||||
@@ -288,7 +288,7 @@
|
||||
<script>
|
||||
function shopProfilePage() {
|
||||
return {
|
||||
...shopLayoutData(),
|
||||
...storefrontLayoutData(),
|
||||
|
||||
// State
|
||||
profile: null,
|
||||
@@ -508,7 +508,7 @@ function shopProfilePage() {
|
||||
}
|
||||
},
|
||||
|
||||
// formatPrice is inherited from shopLayoutData() via spread operator
|
||||
// formatPrice is inherited from storefrontLayoutData() via spread operator
|
||||
|
||||
formatDate(dateStr) {
|
||||
if (!dateStr) return '-';
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
function customerLoyaltyDashboard() {
|
||||
return {
|
||||
...shopLayoutData(),
|
||||
...storefrontLayoutData(),
|
||||
|
||||
// Data
|
||||
card: null,
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
function customerLoyaltyEnroll() {
|
||||
return {
|
||||
...shopLayoutData(),
|
||||
...storefrontLayoutData(),
|
||||
|
||||
// Program info
|
||||
program: null,
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
function customerLoyaltyHistory() {
|
||||
return {
|
||||
...shopLayoutData(),
|
||||
...storefrontLayoutData(),
|
||||
|
||||
// Data
|
||||
card: null,
|
||||
|
||||
@@ -86,7 +86,7 @@
|
||||
<script>
|
||||
function customerLoyaltyEnrollSuccess() {
|
||||
return {
|
||||
...shopLayoutData(),
|
||||
...storefrontLayoutData(),
|
||||
walletUrls: { google_wallet_url: null, apple_wallet_url: null },
|
||||
async init() {
|
||||
try {
|
||||
|
||||
@@ -253,7 +253,7 @@
|
||||
<script>
|
||||
function shopMessages() {
|
||||
return {
|
||||
...shopLayoutData(),
|
||||
...storefrontLayoutData(),
|
||||
loading: true,
|
||||
conversations: [],
|
||||
selectedConversation: null,
|
||||
|
||||
@@ -340,7 +340,7 @@
|
||||
<script>
|
||||
function shopOrderDetailPage() {
|
||||
return {
|
||||
...shopLayoutData(),
|
||||
...storefrontLayoutData(),
|
||||
|
||||
// State
|
||||
order: null,
|
||||
@@ -416,7 +416,7 @@ function shopOrderDetailPage() {
|
||||
return this.statuses[status]?.class || 'bg-gray-100 text-gray-800 dark:bg-gray-700 dark:text-gray-200';
|
||||
},
|
||||
|
||||
// formatPrice is inherited from shopLayoutData() via spread operator
|
||||
// formatPrice is inherited from storefrontLayoutData() via spread operator
|
||||
|
||||
formatDateTime(dateStr) {
|
||||
if (!dateStr) return '-';
|
||||
|
||||
@@ -134,7 +134,7 @@
|
||||
<script>
|
||||
function shopOrdersPage() {
|
||||
return {
|
||||
...shopLayoutData(),
|
||||
...storefrontLayoutData(),
|
||||
|
||||
// State
|
||||
orders: [],
|
||||
@@ -209,7 +209,7 @@ function shopOrdersPage() {
|
||||
return this.statuses[status]?.class || 'bg-gray-100 text-gray-800 dark:bg-gray-700 dark:text-gray-200';
|
||||
},
|
||||
|
||||
// formatPrice is inherited from shopLayoutData() via spread operator
|
||||
// formatPrice is inherited from storefrontLayoutData() via spread operator
|
||||
|
||||
formatDate(dateStr) {
|
||||
if (!dateStr) return '-';
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{# app/templates/storefront/base.html #}
|
||||
{# Base template for store shop frontend with theme support #}
|
||||
<!DOCTYPE html>
|
||||
<html lang="en" x-data="{% block alpine_data %}shopLayoutData(){% endblock %}" x-bind:class="{ 'dark': dark }">
|
||||
<html lang="en" x-data="{% block alpine_data %}storefrontLayoutData(){% endblock %}" x-bind:class="{ 'dark': dark }">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
|
||||
@@ -412,7 +412,7 @@ All authentication pages follow the shop template pattern:
|
||||
<script>
|
||||
function componentName() {
|
||||
return {
|
||||
...shopLayoutData(),
|
||||
...storefrontLayoutData(),
|
||||
// Component-specific data/methods
|
||||
}
|
||||
}
|
||||
@@ -487,7 +487,7 @@ Custom Tailwind CSS modal for logout confirmation instead of browser's native `c
|
||||
```javascript
|
||||
function accountDashboard() {
|
||||
return {
|
||||
...shopLayoutData(),
|
||||
...storefrontLayoutData(),
|
||||
showLogoutModal: false, // Modal state
|
||||
|
||||
confirmLogout() {
|
||||
|
||||
@@ -291,7 +291,7 @@ Scripts MUST load in this exact order (see base.html):
|
||||
7. Page-specific JS ← Optional page scripts
|
||||
|
||||
Why This Order Matters:
|
||||
• shop-layout.js defines shopLayoutData() BEFORE Alpine initializes
|
||||
• shop-layout.js defines storefrontLayoutData() BEFORE Alpine initializes
|
||||
• Alpine.js defers to ensure DOM is ready
|
||||
• Shared utilities available to all scripts
|
||||
• Icons and logging available immediately
|
||||
@@ -311,7 +311,7 @@ Alpine.js Component Architecture:
|
||||
|
||||
Provides shared functionality for all shop pages:
|
||||
|
||||
function shopLayoutData() {
|
||||
function storefrontLayoutData() {
|
||||
return {
|
||||
// Theme state
|
||||
dark: localStorage.getItem('shop-theme') === 'dark',
|
||||
@@ -368,16 +368,16 @@ Provides shared functionality for all shop pages:
|
||||
}
|
||||
|
||||
// Make globally available
|
||||
window.shopLayoutData = shopLayoutData;
|
||||
window.storefrontLayoutData = storefrontLayoutData;
|
||||
|
||||
⭐ PAGE-SPECIFIC COMPONENTS:
|
||||
|
||||
Each page extends shopLayoutData() for page-specific functionality:
|
||||
Each page extends storefrontLayoutData() for page-specific functionality:
|
||||
|
||||
// Example: products.html
|
||||
document.addEventListener('alpine:init', () => {
|
||||
Alpine.data('shopProducts', () => ({
|
||||
...shopLayoutData(), // Extend base component
|
||||
...storefrontLayoutData(), // Extend base component
|
||||
|
||||
// Page-specific state
|
||||
products: [],
|
||||
@@ -387,7 +387,7 @@ Each page extends shopLayoutData() for page-specific functionality:
|
||||
// Override init to add page-specific initialization
|
||||
async init() {
|
||||
shopLog.info('Products page initializing...');
|
||||
this.loadCart(); // From shopLayoutData
|
||||
this.loadCart(); // From storefrontLayoutData
|
||||
await this.loadProducts(); // Page-specific
|
||||
},
|
||||
|
||||
@@ -405,18 +405,18 @@ Template Usage:
|
||||
──────────────────────────────────────────────────────────────────
|
||||
|
||||
{# In base.html - uses block to allow override #}
|
||||
<html x-data="{% block alpine_data %}shopLayoutData(){% endblock %}"
|
||||
<html x-data="{% block alpine_data %}storefrontLayoutData(){% endblock %}"
|
||||
x-bind:class="{ 'dark': dark }">
|
||||
|
||||
{# In products.html - overrides to use page-specific component #}
|
||||
{% block alpine_data %}shopProducts(){% endblock %}
|
||||
|
||||
{# In home.html - uses default base component #}
|
||||
{# No block override needed, inherits shopLayoutData() #}
|
||||
{# No block override needed, inherits storefrontLayoutData() #}
|
||||
|
||||
⭐ COMPONENT HIERARCHY:
|
||||
|
||||
shopLayoutData() ← Base component (shared state & methods)
|
||||
storefrontLayoutData() ← Base component (shared state & methods)
|
||||
↓
|
||||
shopProducts() ← Products page (extends base + products state)
|
||||
shopCart() ← Cart page (extends base + cart state)
|
||||
@@ -435,11 +435,11 @@ Tradeoffs:
|
||||
⚠️ Can't easily split page into independent sub-components
|
||||
|
||||
Best Practices:
|
||||
1. Always extend shopLayoutData() in page components
|
||||
1. Always extend storefrontLayoutData() in page components
|
||||
2. Override init() if you need page-specific initialization
|
||||
3. Call parent methods when needed (this.loadCart(), this.showToast())
|
||||
4. Keep page-specific state in the page component
|
||||
5. Keep shared state in shopLayoutData()
|
||||
5. Keep shared state in storefrontLayoutData()
|
||||
|
||||
Responsibilities:
|
||||
✅ Load products from API
|
||||
|
||||
@@ -445,7 +445,7 @@ function shop[PageName]() {
|
||||
pageLog.info('Adding to cart:', item.name);
|
||||
|
||||
// Get cart from shop layout
|
||||
const shopLayout = Alpine.store('shop') || window.shopLayoutData();
|
||||
const shopLayout = Alpine.store('shop') || window.storefrontLayoutData();
|
||||
|
||||
if (shopLayout && typeof shopLayout.addToCart === 'function') {
|
||||
shopLayout.addToCart(item, quantity);
|
||||
@@ -463,7 +463,7 @@ function shop[PageName]() {
|
||||
* Show toast notification
|
||||
*/
|
||||
showToast(message, type = 'info') {
|
||||
const shopLayout = Alpine.store('shop') || window.shopLayoutData();
|
||||
const shopLayout = Alpine.store('shop') || window.storefrontLayoutData();
|
||||
if (shopLayout && typeof shopLayout.showToast === 'function') {
|
||||
shopLayout.showToast(message, type);
|
||||
}
|
||||
@@ -606,7 +606,7 @@ async loadProduct(id) {
|
||||
}
|
||||
|
||||
addToCartWithQuantity() {
|
||||
const shopLayout = window.shopLayoutData();
|
||||
const shopLayout = window.storefrontLayoutData();
|
||||
shopLayout.addToCart(this.product, this.quantity);
|
||||
}
|
||||
```
|
||||
@@ -663,19 +663,19 @@ async init() {
|
||||
}
|
||||
|
||||
loadCart() {
|
||||
const shopLayout = window.shopLayoutData();
|
||||
const shopLayout = window.storefrontLayoutData();
|
||||
this.cart = shopLayout.cart;
|
||||
this.calculateTotals();
|
||||
}
|
||||
|
||||
updateQuantity(productId, quantity) {
|
||||
const shopLayout = window.shopLayoutData();
|
||||
const shopLayout = window.storefrontLayoutData();
|
||||
shopLayout.updateCartItem(productId, quantity);
|
||||
this.loadCart();
|
||||
}
|
||||
|
||||
removeItem(productId) {
|
||||
const shopLayout = window.shopLayoutData();
|
||||
const shopLayout = window.storefrontLayoutData();
|
||||
shopLayout.removeFromCart(productId);
|
||||
this.loadCart();
|
||||
}
|
||||
@@ -754,7 +754,7 @@ Always use the shop layout's cart methods:
|
||||
|
||||
```javascript
|
||||
// ✅ GOOD: Uses shop layout
|
||||
const shopLayout = window.shopLayoutData();
|
||||
const shopLayout = window.storefrontLayoutData();
|
||||
shopLayout.addToCart(product, quantity);
|
||||
|
||||
// ❌ BAD: Direct localStorage manipulation
|
||||
|
||||
@@ -56,7 +56,7 @@ 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
|
||||
- `storefrontLayoutData()` 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`
|
||||
|
||||
@@ -295,7 +295,7 @@ Child component doesn't call parent `init()` method.
|
||||
**Solution:**
|
||||
```javascript
|
||||
// Store reference to parent
|
||||
const baseData = shopLayoutData();
|
||||
const baseData = storefrontLayoutData();
|
||||
|
||||
return {
|
||||
...baseData,
|
||||
|
||||
Reference in New Issue
Block a user