fix: storefront login 403, cookie path, double-storefront URLs, and auth redirects
- Extract store/platform context from Referer header for storefront API requests
(StoreContextMiddleware and PlatformContextMiddleware) so login POST works in
dev mode where API paths lack /platforms/{code}/ prefix
- Set customer token cookie path to "/" for cross-route compatibility
- Fix double storefront in URLs: replace {{ base_url }}storefront/ with {{ base_url }}
across all 24 storefront templates
- Fix auth error redirect to include platform prefix and use store_code
- Update seed script to output correct storefront login URLs
- Add 20 new unit tests covering all fixes; fix 9 pre-existing test failures
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -434,14 +434,19 @@ def _redirect_to_login(request: Request) -> RedirectResponse:
|
||||
|
||||
base_url = "/"
|
||||
if access_method == "path" and store:
|
||||
full_prefix = (
|
||||
store_context.get("full_prefix", "/store/")
|
||||
if store_context
|
||||
else "/store/"
|
||||
)
|
||||
base_url = f"{full_prefix}{store.subdomain}/"
|
||||
platform = getattr(request.state, "platform", None)
|
||||
platform_original_path = getattr(request.state, "platform_original_path", None)
|
||||
if platform and platform_original_path and platform_original_path.startswith("/platforms/"):
|
||||
base_url = f"/platforms/{platform.code}/storefront/{store.store_code}/"
|
||||
else:
|
||||
full_prefix = (
|
||||
store_context.get("full_prefix", "/storefront/")
|
||||
if store_context
|
||||
else "/storefront/"
|
||||
)
|
||||
base_url = f"{full_prefix}{store.store_code}/"
|
||||
|
||||
login_url = f"{base_url}storefront/account/login"
|
||||
login_url = f"{base_url}account/login"
|
||||
logger.debug(f"Redirecting to {login_url}")
|
||||
return RedirectResponse(url=login_url, status_code=302)
|
||||
# Fallback to root for unknown contexts (PLATFORM)
|
||||
|
||||
@@ -352,7 +352,7 @@
|
||||
x-transition:leave="transform transition ease-in-out duration-300"
|
||||
x-transition:leave-start="translate-x-0"
|
||||
x-transition:leave-end="translate-x-full"
|
||||
class="w-screen max-w-lg"
|
||||
class="w-screen max-w-lg h-full"
|
||||
>
|
||||
<div class="flex h-full flex-col bg-white dark:bg-gray-800 shadow-xl">
|
||||
<!-- Header -->
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
<div class="breadcrumb mb-6">
|
||||
<a href="{{ base_url }}" class="hover:text-primary">Home</a>
|
||||
<span>/</span>
|
||||
<a href="{{ base_url }}storefront/products" class="hover:text-primary">Products</a>
|
||||
<a href="{{ base_url }}products" class="hover:text-primary">Products</a>
|
||||
<span>/</span>
|
||||
<span class="text-gray-900 dark:text-gray-200 font-medium">Cart</span>
|
||||
</div>
|
||||
@@ -40,7 +40,7 @@
|
||||
<p class="text-gray-600 dark:text-gray-400 mb-6">
|
||||
Add some products to get started!
|
||||
</p>
|
||||
<a href="{{ base_url }}storefront/products" class="inline-block px-6 py-3 bg-primary text-white rounded-lg hover:bg-primary-dark transition-colors">
|
||||
<a href="{{ base_url }}products" class="inline-block px-6 py-3 bg-primary text-white rounded-lg hover:bg-primary-dark transition-colors">
|
||||
Browse Products
|
||||
</a>
|
||||
</div>
|
||||
@@ -154,7 +154,7 @@
|
||||
Proceed to Checkout
|
||||
</button>
|
||||
|
||||
<a href="{{ base_url }}storefront/products" class="block w-full px-6 py-3 text-center border-2 border-gray-300 dark:border-gray-600 rounded-lg hover:bg-gray-100 dark:hover:bg-gray-700 transition-colors">
|
||||
<a href="{{ base_url }}products" class="block w-full px-6 py-3 text-center border-2 border-gray-300 dark:border-gray-600 rounded-lg hover:bg-gray-100 dark:hover:bg-gray-700 transition-colors">
|
||||
Continue Shopping
|
||||
</a>
|
||||
|
||||
@@ -309,9 +309,9 @@ document.addEventListener('alpine:init', () => {
|
||||
|
||||
if (!token) {
|
||||
// Redirect to login with return URL
|
||||
window.location.href = '{{ base_url }}storefront/account/login?return={{ base_url }}storefront/checkout';
|
||||
window.location.href = '{{ base_url }}account/login?return={{ base_url }}checkout';
|
||||
} else {
|
||||
window.location.href = '{{ base_url }}storefront/checkout';
|
||||
window.location.href = '{{ base_url }}checkout';
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
<div class="breadcrumb mb-6">
|
||||
<a href="{{ base_url }}" class="hover:text-primary">Home</a>
|
||||
<span>/</span>
|
||||
<a href="{{ base_url }}storefront/products" class="hover:text-primary">Products</a>
|
||||
<a href="{{ base_url }}products" class="hover:text-primary">Products</a>
|
||||
<span>/</span>
|
||||
<span class="text-gray-900 dark:text-gray-200 font-medium" x-text="categoryName">{{ category_slug | replace('-', ' ') | title if category_slug else 'Category' }}</span>
|
||||
</div>
|
||||
@@ -61,14 +61,14 @@
|
||||
<div x-show="!loading && products.length > 0" class="product-grid">
|
||||
<template x-for="product in products" :key="product.id">
|
||||
<div class="bg-white dark:bg-gray-800 rounded-lg shadow-sm hover:shadow-md transition-shadow overflow-hidden">
|
||||
<a :href="`{{ base_url }}storefront/products/${product.id}`">
|
||||
<a :href="`{{ base_url }}products/${product.id}`">
|
||||
<img loading="lazy" :src="product.marketplace_product?.image_link || '/static/storefront/img/placeholder.svg'"
|
||||
@error="$el.src = '/static/storefront/img/placeholder.svg'"
|
||||
:alt="product.marketplace_product?.title"
|
||||
class="w-full h-48 object-cover">
|
||||
</a>
|
||||
<div class="p-4">
|
||||
<a :href="`{{ base_url }}storefront/products/${product.id}`" class="block">
|
||||
<a :href="`{{ base_url }}products/${product.id}`" class="block">
|
||||
<h3 class="text-lg font-semibold text-gray-800 dark:text-gray-200 mb-2 line-clamp-2" x-text="product.marketplace_product?.title"></h3>
|
||||
</a>
|
||||
<p class="text-sm text-gray-600 dark:text-gray-400 mb-3 line-clamp-2" x-text="product.marketplace_product?.description"></p>
|
||||
@@ -99,7 +99,7 @@
|
||||
<p class="text-gray-600 dark:text-gray-400 mb-4">
|
||||
Check back later or browse other categories.
|
||||
</p>
|
||||
<a href="{{ base_url }}storefront/products" class="inline-block px-6 py-3 bg-primary text-white rounded-lg hover:bg-primary-dark transition-colors" style="background-color: var(--color-primary)">
|
||||
<a href="{{ base_url }}products" class="inline-block px-6 py-3 bg-primary text-white rounded-lg hover:bg-primary-dark transition-colors" style="background-color: var(--color-primary)">
|
||||
Browse All Products
|
||||
</a>
|
||||
</div>
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
<div class="breadcrumb mb-6">
|
||||
<a href="{{ base_url }}" class="hover:text-primary">Home</a>
|
||||
<span>/</span>
|
||||
<a href="{{ base_url }}storefront/products" class="hover:text-primary">Products</a>
|
||||
<a href="{{ base_url }}products" class="hover:text-primary">Products</a>
|
||||
<span>/</span>
|
||||
<span class="text-gray-900 dark:text-gray-200 font-medium" x-text="product?.marketplace_product?.title || 'Product'">Product</span>
|
||||
</div>
|
||||
@@ -186,7 +186,7 @@
|
||||
<div class="product-grid">
|
||||
<template x-for="related in relatedProducts" :key="related.id">
|
||||
<div class="bg-white dark:bg-gray-800 rounded-lg shadow-sm hover:shadow-md transition-shadow overflow-hidden cursor-pointer">
|
||||
<a :href="`{{ base_url }}storefront/products/${related.id}`">
|
||||
<a :href="`{{ base_url }}products/${related.id}`">
|
||||
<img
|
||||
:src="related.marketplace_product?.image_link || '/static/storefront/img/placeholder.svg'"
|
||||
@error="$el.src = '/static/storefront/img/placeholder.svg'"
|
||||
@@ -195,7 +195,7 @@
|
||||
>
|
||||
</a>
|
||||
<div class="p-4">
|
||||
<a :href="`{{ base_url }}storefront/products/${related.id}`">
|
||||
<a :href="`{{ base_url }}products/${related.id}`">
|
||||
<h3 class="text-lg font-semibold text-gray-800 dark:text-gray-200 mb-2 line-clamp-2" x-text="related.marketplace_product?.title"></h3>
|
||||
</a>
|
||||
<p class="text-2xl font-bold text-primary">
|
||||
@@ -301,7 +301,7 @@ document.addEventListener('alpine:init', () => {
|
||||
this.showToast('Failed to load product', 'error');
|
||||
// Redirect back to products after error
|
||||
setTimeout(() => {
|
||||
window.location.href = '{{ base_url }}storefront/products';
|
||||
window.location.href = '{{ base_url }}products';
|
||||
}, 2000);
|
||||
} finally {
|
||||
this.loading = false;
|
||||
|
||||
@@ -73,14 +73,14 @@
|
||||
<div x-show="!loading && products.length > 0" class="product-grid">
|
||||
<template x-for="product in products" :key="product.id">
|
||||
<div class="bg-white dark:bg-gray-800 rounded-lg shadow-sm hover:shadow-md transition-shadow overflow-hidden">
|
||||
<a :href="`{{ base_url }}storefront/products/${product.id}`">
|
||||
<a :href="`{{ base_url }}products/${product.id}`">
|
||||
<img loading="lazy" :src="product.marketplace_product?.image_link || '/static/storefront/img/placeholder.svg'"
|
||||
@error="$el.src = '/static/storefront/img/placeholder.svg'"
|
||||
:alt="product.marketplace_product?.title"
|
||||
class="w-full h-48 object-cover">
|
||||
</a>
|
||||
<div class="p-4">
|
||||
<a :href="`{{ base_url }}storefront/products/${product.id}`" class="block">
|
||||
<a :href="`{{ base_url }}products/${product.id}`" class="block">
|
||||
<h3 class="text-lg font-semibold text-gray-800 dark:text-gray-200 mb-2 line-clamp-2" x-text="product.marketplace_product?.title"></h3>
|
||||
</a>
|
||||
<p class="text-sm text-gray-600 dark:text-gray-400 mb-3 line-clamp-2" x-text="product.marketplace_product?.description"></p>
|
||||
|
||||
@@ -80,14 +80,14 @@
|
||||
<div x-show="!loading && query && products.length > 0" class="product-grid">
|
||||
<template x-for="product in products" :key="product.id">
|
||||
<div class="bg-white dark:bg-gray-800 rounded-lg shadow-sm hover:shadow-md transition-shadow overflow-hidden">
|
||||
<a :href="`{{ base_url }}storefront/products/${product.id}`">
|
||||
<a :href="`{{ base_url }}products/${product.id}`">
|
||||
<img loading="lazy" :src="product.marketplace_product?.image_link || '/static/storefront/img/placeholder.svg'"
|
||||
@error="$el.src = '/static/storefront/img/placeholder.svg'"
|
||||
:alt="product.marketplace_product?.title"
|
||||
class="w-full h-48 object-cover">
|
||||
</a>
|
||||
<div class="p-4">
|
||||
<a :href="`{{ base_url }}storefront/products/${product.id}`" class="block">
|
||||
<a :href="`{{ base_url }}products/${product.id}`" class="block">
|
||||
<h3 class="text-lg font-semibold text-gray-800 dark:text-gray-200 mb-2 line-clamp-2" x-text="product.marketplace_product?.title"></h3>
|
||||
</a>
|
||||
<p class="text-sm text-gray-600 dark:text-gray-400 mb-3 line-clamp-2" x-text="product.marketplace_product?.description"></p>
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
<div class="breadcrumb mb-6">
|
||||
<a href="{{ base_url }}" class="hover:text-primary">Home</a>
|
||||
<span>/</span>
|
||||
<a href="{{ base_url }}storefront/account/dashboard" class="hover:text-primary">Account</a>
|
||||
<a href="{{ base_url }}account/dashboard" class="hover:text-primary">Account</a>
|
||||
<span>/</span>
|
||||
<span class="text-gray-900 dark:text-gray-200 font-medium">Wishlist</span>
|
||||
</div>
|
||||
@@ -46,7 +46,7 @@
|
||||
<p class="text-gray-600 dark:text-gray-400 mb-6">
|
||||
Log in to your account to view and manage your wishlist.
|
||||
</p>
|
||||
<a href="{{ base_url }}storefront/account/login" class="inline-block px-6 py-3 bg-primary text-white rounded-lg hover:bg-primary-dark transition-colors" style="background-color: var(--color-primary)">
|
||||
<a href="{{ base_url }}account/login" class="inline-block px-6 py-3 bg-primary text-white rounded-lg hover:bg-primary-dark transition-colors" style="background-color: var(--color-primary)">
|
||||
Log In
|
||||
</a>
|
||||
</div>
|
||||
@@ -64,14 +64,14 @@
|
||||
<span x-html="$icon('heart', 'w-5 h-5 text-red-500 fill-current')"></span>
|
||||
</button>
|
||||
|
||||
<a :href="`{{ base_url }}storefront/products/${item.product.id}`">
|
||||
<a :href="`{{ base_url }}products/${item.product.id}`">
|
||||
<img loading="lazy" :src="item.product.marketplace_product?.image_link || '/static/storefront/img/placeholder.svg'"
|
||||
@error="$el.src = '/static/storefront/img/placeholder.svg'"
|
||||
:alt="item.product.marketplace_product?.title"
|
||||
class="w-full h-48 object-cover">
|
||||
</a>
|
||||
<div class="p-4">
|
||||
<a :href="`{{ base_url }}storefront/products/${item.product.id}`" class="block">
|
||||
<a :href="`{{ base_url }}products/${item.product.id}`" class="block">
|
||||
<h3 class="text-lg font-semibold text-gray-800 dark:text-gray-200 mb-2 line-clamp-2" x-text="item.product.marketplace_product?.title"></h3>
|
||||
</a>
|
||||
<p class="text-sm text-gray-600 dark:text-gray-400 mb-3 line-clamp-2" x-text="item.product.marketplace_product?.description"></p>
|
||||
@@ -122,7 +122,7 @@
|
||||
<p class="text-gray-600 dark:text-gray-400 mb-6">
|
||||
Save items you like by clicking the heart icon on product pages.
|
||||
</p>
|
||||
<a href="{{ base_url }}storefront/products" class="inline-block px-6 py-3 bg-primary text-white rounded-lg hover:bg-primary-dark transition-colors" style="background-color: var(--color-primary)">
|
||||
<a href="{{ base_url }}products" class="inline-block px-6 py-3 bg-primary text-white rounded-lg hover:bg-primary-dark transition-colors" style="background-color: var(--color-primary)">
|
||||
Browse Products
|
||||
</a>
|
||||
</div>
|
||||
|
||||
@@ -11,10 +11,10 @@
|
||||
{# Breadcrumbs #}
|
||||
<nav class="mb-6" aria-label="Breadcrumb">
|
||||
<ol class="flex items-center space-x-2 text-sm text-gray-500 dark:text-gray-400">
|
||||
<li><a href="{{ base_url }}storefront/" class="hover:text-primary">Home</a></li>
|
||||
<li><a href="{{ base_url }}" class="hover:text-primary">Home</a></li>
|
||||
<li class="flex items-center">
|
||||
<span class="h-4 w-4 mx-2" x-html="$icon('chevron-right', 'h-4 w-4')"></span>
|
||||
<a href="{{ base_url }}storefront/cart" class="hover:text-primary">Cart</a>
|
||||
<a href="{{ base_url }}cart" class="hover:text-primary">Cart</a>
|
||||
</li>
|
||||
<li class="flex items-center">
|
||||
<span class="h-4 w-4 mx-2" x-html="$icon('chevron-right', 'h-4 w-4')"></span>
|
||||
@@ -36,7 +36,7 @@
|
||||
<span class="mx-auto h-12 w-12 text-gray-400 mb-4 block" x-html="$icon('shopping-bag', 'h-12 w-12 mx-auto')"></span>
|
||||
<h3 class="text-xl font-semibold text-gray-700 dark:text-gray-200 mb-2">Your cart is empty</h3>
|
||||
<p class="text-gray-500 dark:text-gray-400 mb-6">Add some products before checking out.</p>
|
||||
<a href="{{ base_url }}storefront/products" class="inline-block px-6 py-3 text-white rounded-lg transition-colors" style="background-color: var(--color-primary)">
|
||||
<a href="{{ base_url }}products" class="inline-block px-6 py-3 text-white rounded-lg transition-colors" style="background-color: var(--color-primary)">
|
||||
Browse Products
|
||||
</a>
|
||||
</div>
|
||||
@@ -900,7 +900,7 @@ function checkoutPage() {
|
||||
console.log('[CHECKOUT] Order placed:', order.order_number);
|
||||
|
||||
// Redirect to confirmation page
|
||||
window.location.href = '{{ base_url }}storefront/order-confirmation?order=' + order.order_number;
|
||||
window.location.href = '{{ base_url }}order-confirmation?order=' + order.order_number;
|
||||
|
||||
} catch (error) {
|
||||
console.error('[CHECKOUT] Error placing order:', error);
|
||||
|
||||
@@ -36,7 +36,7 @@
|
||||
|
||||
{# CTA Button #}
|
||||
<div class="flex flex-col sm:flex-row gap-4 justify-center">
|
||||
<a href="{{ base_url }}storefront/"
|
||||
<a href="{{ base_url }}"
|
||||
class="inline-flex items-center justify-center px-8 py-4 text-lg font-semibold rounded-lg text-white bg-primary hover:bg-primary-dark transition-colors shadow-lg hover:shadow-xl"
|
||||
style="background-color: var(--color-primary)">
|
||||
Browse Our Shop
|
||||
@@ -71,7 +71,7 @@
|
||||
Explore
|
||||
</h2>
|
||||
<div class="grid grid-cols-1 md:grid-cols-3 gap-8">
|
||||
<a href="{{ base_url }}storefront/products"
|
||||
<a href="{{ base_url }}products"
|
||||
class="block p-8 bg-white dark:bg-gray-900 rounded-lg shadow-md hover:shadow-xl transition-shadow text-center group">
|
||||
<div class="text-4xl mb-4">🛍️</div>
|
||||
<h3 class="text-xl font-semibold text-gray-900 dark:text-white mb-2 group-hover:text-primary">
|
||||
@@ -84,7 +84,7 @@
|
||||
|
||||
{% if header_pages %}
|
||||
{% for page in header_pages[:2] %}
|
||||
<a href="{{ base_url }}storefront/{{ page.slug }}"
|
||||
<a href="{{ base_url }}{{ page.slug }}"
|
||||
class="block p-8 bg-white dark:bg-gray-900 rounded-lg shadow-md hover:shadow-xl transition-shadow text-center group">
|
||||
<div class="text-4xl mb-4">📄</div>
|
||||
<h3 class="text-xl font-semibold text-gray-900 dark:text-white mb-2 group-hover:text-primary">
|
||||
@@ -96,7 +96,7 @@
|
||||
</a>
|
||||
{% endfor %}
|
||||
{% else %}
|
||||
<a href="{{ base_url }}storefront/about"
|
||||
<a href="{{ base_url }}about"
|
||||
class="block p-8 bg-white dark:bg-gray-900 rounded-lg shadow-md hover:shadow-xl transition-shadow text-center group">
|
||||
<div class="text-4xl mb-4">ℹ️</div>
|
||||
<h3 class="text-xl font-semibold text-gray-900 dark:text-white mb-2 group-hover:text-primary">
|
||||
@@ -107,7 +107,7 @@
|
||||
</p>
|
||||
</a>
|
||||
|
||||
<a href="{{ base_url }}storefront/contact"
|
||||
<a href="{{ base_url }}contact"
|
||||
class="block p-8 bg-white dark:bg-gray-900 rounded-lg shadow-md hover:shadow-xl transition-shadow text-center group">
|
||||
<div class="text-4xl mb-4">📧</div>
|
||||
<h3 class="text-xl font-semibold text-gray-900 dark:text-white mb-2 group-hover:text-primary">
|
||||
|
||||
@@ -43,7 +43,7 @@
|
||||
{% endif %}
|
||||
|
||||
<div class="flex flex-col sm:flex-row gap-4">
|
||||
<a href="{{ base_url }}storefront/"
|
||||
<a href="{{ base_url }}"
|
||||
class="inline-flex items-center justify-center px-8 py-4 text-lg font-semibold rounded-lg text-white bg-primary hover:bg-primary-dark transition-colors shadow-lg"
|
||||
style="background-color: var(--color-primary)">
|
||||
Shop Now
|
||||
@@ -174,7 +174,7 @@
|
||||
Explore More
|
||||
</h2>
|
||||
<div class="grid grid-cols-1 md:grid-cols-3 gap-8">
|
||||
<a href="{{ base_url }}storefront/products"
|
||||
<a href="{{ base_url }}products"
|
||||
class="group relative overflow-hidden rounded-2xl bg-gradient-to-br from-primary/10 to-primary/5 dark:from-primary/20 dark:to-primary/10 p-8 hover:shadow-xl transition-all">
|
||||
<div class="relative z-10">
|
||||
<div class="text-5xl mb-4">🛍️</div>
|
||||
@@ -190,7 +190,7 @@
|
||||
|
||||
{% if header_pages %}
|
||||
{% for page in header_pages[:2] %}
|
||||
<a href="{{ base_url }}storefront/{{ page.slug }}"
|
||||
<a href="{{ base_url }}{{ page.slug }}"
|
||||
class="group relative overflow-hidden rounded-2xl bg-gradient-to-br from-accent/10 to-accent/5 dark:from-accent/20 dark:to-accent/10 p-8 hover:shadow-xl transition-all">
|
||||
<div class="relative z-10">
|
||||
<div class="text-5xl mb-4">📄</div>
|
||||
@@ -205,7 +205,7 @@
|
||||
</a>
|
||||
{% endfor %}
|
||||
{% else %}
|
||||
<a href="{{ base_url }}storefront/about"
|
||||
<a href="{{ base_url }}about"
|
||||
class="group relative overflow-hidden rounded-2xl bg-gradient-to-br from-accent/10 to-accent/5 dark:from-accent/20 dark:to-accent/10 p-8 hover:shadow-xl transition-all">
|
||||
<div class="relative z-10">
|
||||
<div class="text-5xl mb-4">ℹ️</div>
|
||||
@@ -219,7 +219,7 @@
|
||||
<div class="absolute inset-0 bg-accent opacity-0 group-hover:opacity-5 transition-opacity"></div>
|
||||
</a>
|
||||
|
||||
<a href="{{ base_url }}storefront/contact"
|
||||
<a href="{{ base_url }}contact"
|
||||
class="group relative overflow-hidden rounded-2xl bg-gradient-to-br from-primary/10 to-primary/5 dark:from-primary/20 dark:to-primary/10 p-8 hover:shadow-xl transition-all">
|
||||
<div class="relative z-10">
|
||||
<div class="text-5xl mb-4">📧</div>
|
||||
@@ -246,7 +246,7 @@
|
||||
<p class="text-xl mb-10 opacity-90">
|
||||
Join thousands of satisfied customers today
|
||||
</p>
|
||||
<a href="{{ base_url }}storefront/products"
|
||||
<a href="{{ base_url }}products"
|
||||
class="inline-flex items-center justify-center px-10 py-5 text-lg font-bold rounded-xl text-primary bg-white hover:bg-gray-50 transition-all transform hover:scale-105 shadow-2xl">
|
||||
View All Products
|
||||
<span class="w-5 h-5 ml-2" x-html="$icon('arrow-right', 'w-5 h-5')"></span>
|
||||
|
||||
@@ -37,7 +37,7 @@
|
||||
|
||||
{# Single CTA #}
|
||||
<div>
|
||||
<a href="{{ base_url }}storefront/"
|
||||
<a href="{{ base_url }}"
|
||||
class="inline-flex items-center justify-center px-10 py-5 text-xl font-semibold rounded-full text-white bg-primary hover:bg-primary-dark transition-all transform hover:scale-105 shadow-2xl"
|
||||
style="background-color: var(--color-primary)">
|
||||
Enter Shop
|
||||
@@ -49,11 +49,11 @@
|
||||
{% if header_pages or footer_pages %}
|
||||
<div class="mt-16 pt-8 border-t border-gray-200 dark:border-gray-700">
|
||||
<div class="flex flex-wrap justify-center gap-6 text-sm">
|
||||
<a href="{{ base_url }}storefront/products" class="text-gray-600 dark:text-gray-400 hover:text-primary transition-colors">
|
||||
<a href="{{ base_url }}products" class="text-gray-600 dark:text-gray-400 hover:text-primary transition-colors">
|
||||
Products
|
||||
</a>
|
||||
{% for page in (header_pages or footer_pages)[:4] %}
|
||||
<a href="{{ base_url }}storefront/{{ page.slug }}" class="text-gray-600 dark:text-gray-400 hover:text-primary transition-colors">
|
||||
<a href="{{ base_url }}{{ page.slug }}" class="text-gray-600 dark:text-gray-400 hover:text-primary transition-colors">
|
||||
{{ page.title }}
|
||||
</a>
|
||||
{% endfor %}
|
||||
|
||||
@@ -40,7 +40,7 @@
|
||||
|
||||
{# CTAs #}
|
||||
<div class="flex flex-col sm:flex-row gap-6 justify-center animate-fade-in animation-delay-400">
|
||||
<a href="{{ base_url }}storefront/"
|
||||
<a href="{{ base_url }}"
|
||||
class="group inline-flex items-center justify-center px-10 py-5 text-lg font-bold rounded-xl text-white bg-primary hover:bg-primary-dark transition-all transform hover:scale-105 shadow-2xl hover:shadow-3xl"
|
||||
style="background-color: var(--color-primary)">
|
||||
<span>Start Shopping</span>
|
||||
@@ -137,7 +137,7 @@
|
||||
<p class="text-xl mb-10 opacity-90">
|
||||
Explore our collection and find what you're looking for
|
||||
</p>
|
||||
<a href="{{ base_url }}storefront/products"
|
||||
<a href="{{ base_url }}products"
|
||||
class="inline-flex items-center justify-center px-10 py-5 text-lg font-bold rounded-xl text-primary bg-white hover:bg-gray-50 transition-all transform hover:scale-105 shadow-2xl">
|
||||
Browse Products
|
||||
<span class="w-5 h-5 ml-2" x-html="$icon('chevron-right', 'w-5 h-5')"></span>
|
||||
|
||||
@@ -178,23 +178,8 @@ def customer_login(
|
||||
},
|
||||
)
|
||||
|
||||
# Calculate cookie path based on store access method
|
||||
store_context = getattr(request.state, "store_context", None)
|
||||
access_method = (
|
||||
store_context.get("detection_method", "unknown")
|
||||
if store_context
|
||||
else "unknown"
|
||||
)
|
||||
|
||||
cookie_path = "/storefront"
|
||||
if access_method == "path":
|
||||
full_prefix = (
|
||||
store_context.get("full_prefix", "/store/")
|
||||
if store_context
|
||||
else "/store/"
|
||||
)
|
||||
cookie_path = f"{full_prefix}{store.subdomain}/storefront"
|
||||
|
||||
# Set cookie with path=/ so it's sent with all requests
|
||||
# (platform prefix varies between dev and prod, broad path avoids mismatch)
|
||||
response.set_cookie(
|
||||
key="customer_token",
|
||||
value=login_result["token_data"]["access_token"],
|
||||
@@ -202,12 +187,12 @@ def customer_login(
|
||||
secure=should_use_secure_cookies(),
|
||||
samesite="lax",
|
||||
max_age=login_result["token_data"]["expires_in"],
|
||||
path=cookie_path,
|
||||
path="/",
|
||||
)
|
||||
|
||||
logger.debug(
|
||||
f"Set customer_token cookie with {login_result['token_data']['expires_in']}s expiry "
|
||||
f"(path={cookie_path}, httponly=True, secure={should_use_secure_cookies()})",
|
||||
f"(path=/, httponly=True, secure={should_use_secure_cookies()})",
|
||||
)
|
||||
|
||||
return CustomerLoginResponse(
|
||||
@@ -237,25 +222,9 @@ def customer_logout(request: Request, response: Response):
|
||||
},
|
||||
)
|
||||
|
||||
store_context = getattr(request.state, "store_context", None)
|
||||
access_method = (
|
||||
store_context.get("detection_method", "unknown")
|
||||
if store_context
|
||||
else "unknown"
|
||||
)
|
||||
response.delete_cookie(key="customer_token", path="/")
|
||||
|
||||
cookie_path = "/storefront"
|
||||
if access_method == "path" and store:
|
||||
full_prefix = (
|
||||
store_context.get("full_prefix", "/store/")
|
||||
if store_context
|
||||
else "/store/"
|
||||
)
|
||||
cookie_path = f"{full_prefix}{store.subdomain}/storefront"
|
||||
|
||||
response.delete_cookie(key="customer_token", path=cookie_path)
|
||||
|
||||
logger.debug(f"Deleted customer_token cookie (path={cookie_path})")
|
||||
logger.debug("Deleted customer_token cookie (path=/)")
|
||||
|
||||
return LogoutResponse(message="Logged out successfully")
|
||||
|
||||
|
||||
@@ -153,14 +153,19 @@ async def shop_account_root(request: Request):
|
||||
|
||||
base_url = "/"
|
||||
if access_method == "path" and store:
|
||||
full_prefix = (
|
||||
store_context.get("full_prefix", "/store/")
|
||||
if store_context
|
||||
else "/store/"
|
||||
)
|
||||
base_url = f"{full_prefix}{store.subdomain}/"
|
||||
platform = getattr(request.state, "platform", None)
|
||||
platform_original_path = getattr(request.state, "platform_original_path", None)
|
||||
if platform and platform_original_path and platform_original_path.startswith("/platforms/"):
|
||||
base_url = f"/platforms/{platform.code}/storefront/{store.store_code}/"
|
||||
else:
|
||||
full_prefix = (
|
||||
store_context.get("full_prefix", "/storefront/")
|
||||
if store_context
|
||||
else "/storefront/"
|
||||
)
|
||||
base_url = f"{full_prefix}{store.store_code}/"
|
||||
|
||||
return RedirectResponse(url=f"{base_url}storefront/account/dashboard", status_code=302)
|
||||
return RedirectResponse(url=f"{base_url}account/dashboard", status_code=302)
|
||||
|
||||
|
||||
# ============================================================================
|
||||
|
||||
@@ -400,7 +400,7 @@ function addressesPage() {
|
||||
|
||||
if (!response.ok) {
|
||||
if (response.status === 401) {
|
||||
window.location.href = '{{ base_url }}storefront/account/login';
|
||||
window.location.href = '{{ base_url }}account/login';
|
||||
return;
|
||||
}
|
||||
throw new Error('Failed to load addresses');
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6 mb-8">
|
||||
|
||||
<!-- Orders Card -->
|
||||
<a href="{{ base_url }}storefront/account/orders"
|
||||
<a href="{{ base_url }}account/orders"
|
||||
class="block bg-white dark:bg-gray-800 rounded-lg shadow hover:shadow-lg transition-shadow p-6 border border-gray-200 dark:border-gray-700">
|
||||
<div class="flex items-center mb-4">
|
||||
<div class="flex-shrink-0">
|
||||
@@ -36,7 +36,7 @@
|
||||
</a>
|
||||
|
||||
<!-- Profile Card -->
|
||||
<a href="{{ base_url }}storefront/account/profile"
|
||||
<a href="{{ base_url }}account/profile"
|
||||
class="block bg-white dark:bg-gray-800 rounded-lg shadow hover:shadow-lg transition-shadow p-6 border border-gray-200 dark:border-gray-700">
|
||||
<div class="flex items-center mb-4">
|
||||
<div class="flex-shrink-0">
|
||||
@@ -53,7 +53,7 @@
|
||||
</a>
|
||||
|
||||
<!-- Addresses Card -->
|
||||
<a href="{{ base_url }}storefront/account/addresses"
|
||||
<a href="{{ base_url }}account/addresses"
|
||||
class="block bg-white dark:bg-gray-800 rounded-lg shadow hover:shadow-lg transition-shadow p-6 border border-gray-200 dark:border-gray-700">
|
||||
<div class="flex items-center mb-4">
|
||||
<div class="flex-shrink-0">
|
||||
@@ -67,7 +67,7 @@
|
||||
</a>
|
||||
|
||||
<!-- Messages Card -->
|
||||
<a href="{{ base_url }}storefront/account/messages"
|
||||
<a href="{{ base_url }}account/messages"
|
||||
class="block bg-white dark:bg-gray-800 rounded-lg shadow hover:shadow-lg transition-shadow p-6 border border-gray-200 dark:border-gray-700"
|
||||
x-data="{ unreadCount: 0 }"
|
||||
x-init="fetch('/api/v1/storefront/messages/unread-count').then(r => r.json()).then(d => unreadCount = d.unread_count).catch(() => {})">
|
||||
@@ -157,14 +157,14 @@ function accountDashboard() {
|
||||
|
||||
// Redirect to login page
|
||||
setTimeout(() => {
|
||||
window.location.href = '{{ base_url }}storefront/account/login';
|
||||
window.location.href = '{{ base_url }}account/login';
|
||||
}, 500);
|
||||
} else {
|
||||
console.error('Logout failed with status:', response.status);
|
||||
this.showToast('Logout failed', 'error');
|
||||
// Still redirect on failure (cookie might be deleted)
|
||||
setTimeout(() => {
|
||||
window.location.href = '{{ base_url }}storefront/account/login';
|
||||
window.location.href = '{{ base_url }}account/login';
|
||||
}, 1000);
|
||||
}
|
||||
})
|
||||
@@ -173,7 +173,7 @@ function accountDashboard() {
|
||||
this.showToast('Logout failed', 'error');
|
||||
// Redirect anyway
|
||||
setTimeout(() => {
|
||||
window.location.href = '{{ base_url }}storefront/account/login';
|
||||
window.location.href = '{{ base_url }}account/login';
|
||||
}, 1000);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -143,13 +143,13 @@
|
||||
<span class="text-sm text-gray-600 dark:text-gray-400">Remember your password?</span>
|
||||
<a class="text-sm font-medium hover:underline ml-1"
|
||||
style="color: var(--color-primary);"
|
||||
href="{{ base_url }}storefront/account/login">
|
||||
href="{{ base_url }}account/login">
|
||||
Sign in
|
||||
</a>
|
||||
</p>
|
||||
<p class="mt-2 text-center">
|
||||
<a class="text-sm font-medium text-gray-600 dark:text-gray-400 hover:underline"
|
||||
href="{{ base_url }}storefront/">
|
||||
href="{{ base_url }}">
|
||||
← Continue shopping
|
||||
</a>
|
||||
</p>
|
||||
|
||||
@@ -127,7 +127,7 @@
|
||||
style="color: var(--color-primary);">
|
||||
<span class="ml-2 text-gray-700 dark:text-gray-400">Remember me</span>
|
||||
</label>
|
||||
<a href="{{ base_url }}storefront/account/forgot-password"
|
||||
<a href="{{ base_url }}account/forgot-password"
|
||||
class="text-sm font-medium hover:underline"
|
||||
style="color: var(--color-primary);">
|
||||
Forgot password?
|
||||
@@ -150,13 +150,13 @@
|
||||
<span class="text-sm text-gray-600 dark:text-gray-400">Don't have an account?</span>
|
||||
<a class="text-sm font-medium hover:underline ml-1"
|
||||
style="color: var(--color-primary);"
|
||||
href="{{ base_url }}storefront/account/register">
|
||||
href="{{ base_url }}account/register">
|
||||
Create an account
|
||||
</a>
|
||||
</p>
|
||||
<p class="mt-2 text-center">
|
||||
<a class="text-sm font-medium text-gray-600 dark:text-gray-400 hover:underline"
|
||||
href="{{ base_url }}storefront/">
|
||||
href="{{ base_url }}">
|
||||
← Continue shopping
|
||||
</a>
|
||||
</p>
|
||||
@@ -263,7 +263,7 @@
|
||||
|
||||
// Redirect to account page or return URL
|
||||
setTimeout(() => {
|
||||
const returnUrl = new URLSearchParams(window.location.search).get('return') || '{{ base_url }}storefront/account';
|
||||
const returnUrl = new URLSearchParams(window.location.search).get('return') || '{{ base_url }}account';
|
||||
window.location.href = returnUrl;
|
||||
}, 1000);
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
<nav class="mb-6" aria-label="Breadcrumb">
|
||||
<ol class="flex items-center space-x-2 text-sm text-gray-500 dark:text-gray-400">
|
||||
<li>
|
||||
<a href="{{ base_url }}storefront/account/dashboard" class="hover:text-primary">My Account</a>
|
||||
<a href="{{ base_url }}account/dashboard" class="hover:text-primary">My Account</a>
|
||||
</li>
|
||||
<li class="flex items-center">
|
||||
<span class="h-4 w-4 mx-2" x-html="$icon('chevron-right', 'h-4 w-4')"></span>
|
||||
@@ -330,7 +330,7 @@ function shopProfilePage() {
|
||||
try {
|
||||
const token = localStorage.getItem('customer_token');
|
||||
if (!token) {
|
||||
window.location.href = '{{ base_url }}storefront/account/login?next=' + encodeURIComponent(window.location.pathname);
|
||||
window.location.href = '{{ base_url }}account/login?next=' + encodeURIComponent(window.location.pathname);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -344,7 +344,7 @@ function shopProfilePage() {
|
||||
if (response.status === 401) {
|
||||
localStorage.removeItem('customer_token');
|
||||
localStorage.removeItem('customer_user');
|
||||
window.location.href = '{{ base_url }}storefront/account/login?next=' + encodeURIComponent(window.location.pathname);
|
||||
window.location.href = '{{ base_url }}account/login?next=' + encodeURIComponent(window.location.pathname);
|
||||
return;
|
||||
}
|
||||
throw new Error('Failed to load profile');
|
||||
@@ -380,7 +380,7 @@ function shopProfilePage() {
|
||||
try {
|
||||
const token = localStorage.getItem('customer_token');
|
||||
if (!token) {
|
||||
window.location.href = '{{ base_url }}storefront/account/login';
|
||||
window.location.href = '{{ base_url }}account/login';
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -429,7 +429,7 @@ function shopProfilePage() {
|
||||
try {
|
||||
const token = localStorage.getItem('customer_token');
|
||||
if (!token) {
|
||||
window.location.href = '{{ base_url }}storefront/account/login';
|
||||
window.location.href = '{{ base_url }}account/login';
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -472,7 +472,7 @@ function shopProfilePage() {
|
||||
try {
|
||||
const token = localStorage.getItem('customer_token');
|
||||
if (!token) {
|
||||
window.location.href = '{{ base_url }}storefront/account/login';
|
||||
window.location.href = '{{ base_url }}account/login';
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -218,7 +218,7 @@
|
||||
<span class="text-sm text-gray-600 dark:text-gray-400">Already have an account?</span>
|
||||
<a class="text-sm font-medium hover:underline ml-1"
|
||||
style="color: var(--color-primary);"
|
||||
href="{{ base_url }}storefront/account/login">
|
||||
href="{{ base_url }}account/login">
|
||||
Sign in instead
|
||||
</a>
|
||||
</p>
|
||||
@@ -360,7 +360,7 @@
|
||||
|
||||
// Redirect to login after 2 seconds
|
||||
setTimeout(() => {
|
||||
window.location.href = '{{ base_url }}storefront/account/login?registered=true';
|
||||
window.location.href = '{{ base_url }}account/login?registered=true';
|
||||
}, 2000);
|
||||
|
||||
} catch (error) {
|
||||
|
||||
@@ -80,7 +80,7 @@
|
||||
Please request a new password reset link.
|
||||
</p>
|
||||
|
||||
<a href="{{ base_url }}storefront/account/forgot-password"
|
||||
<a href="{{ base_url }}account/forgot-password"
|
||||
class="btn-primary-theme inline-block px-6 py-2 text-sm font-medium text-white rounded-lg">
|
||||
Request New Link
|
||||
</a>
|
||||
@@ -164,7 +164,7 @@
|
||||
You can now sign in with your new password.
|
||||
</p>
|
||||
|
||||
<a href="{{ base_url }}storefront/account/login"
|
||||
<a href="{{ base_url }}account/login"
|
||||
class="btn-primary-theme inline-block px-6 py-2 text-sm font-medium text-white rounded-lg">
|
||||
Sign In
|
||||
</a>
|
||||
@@ -177,13 +177,13 @@
|
||||
<span class="text-sm text-gray-600 dark:text-gray-400">Remember your password?</span>
|
||||
<a class="text-sm font-medium hover:underline ml-1"
|
||||
style="color: var(--color-primary);"
|
||||
href="{{ base_url }}storefront/account/login">
|
||||
href="{{ base_url }}account/login">
|
||||
Sign in
|
||||
</a>
|
||||
</p>
|
||||
<p class="mt-2 text-center">
|
||||
<a class="text-sm font-medium text-gray-600 dark:text-gray-400 hover:underline"
|
||||
href="{{ base_url }}storefront/">
|
||||
href="{{ base_url }}">
|
||||
← Continue shopping
|
||||
</a>
|
||||
</p>
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
<div class="max-w-4xl mx-auto px-4 sm:px-6 lg:px-8 py-8">
|
||||
<!-- Page Header -->
|
||||
<div class="mb-8">
|
||||
<a href="{{ base_url }}storefront/account/dashboard" class="inline-flex items-center text-sm text-gray-600 dark:text-gray-400 hover:text-primary mb-4">
|
||||
<a href="{{ base_url }}account/dashboard" class="inline-flex items-center text-sm text-gray-600 dark:text-gray-400 hover:text-primary mb-4">
|
||||
<span x-html="$icon('arrow-left', 'w-4 h-4 mr-2')"></span>
|
||||
Back to Account
|
||||
</a>
|
||||
@@ -26,7 +26,7 @@
|
||||
<span x-html="$icon('gift', 'w-16 h-16 mx-auto text-gray-300 dark:text-gray-600')"></span>
|
||||
<h2 class="mt-4 text-xl font-semibold text-gray-900 dark:text-white">Join Our Rewards Program!</h2>
|
||||
<p class="mt-2 text-gray-600 dark:text-gray-400">Earn points on every purchase and redeem for rewards.</p>
|
||||
<a href="{{ base_url }}storefront/loyalty/join"
|
||||
<a href="{{ base_url }}loyalty/join"
|
||||
class="mt-6 inline-flex items-center px-6 py-3 text-sm font-medium text-white rounded-lg"
|
||||
style="background-color: var(--color-primary)">
|
||||
<span x-html="$icon('plus', 'w-5 h-5 mr-2')"></span>
|
||||
@@ -125,7 +125,7 @@
|
||||
<div>
|
||||
<div class="flex items-center justify-between mb-4">
|
||||
<h2 class="text-xl font-semibold text-gray-900 dark:text-white">Recent Activity</h2>
|
||||
<a href="{{ base_url }}storefront/account/loyalty/history"
|
||||
<a href="{{ base_url }}account/loyalty/history"
|
||||
class="text-sm font-medium hover:underline" style="color: var(--color-primary)">
|
||||
View All
|
||||
</a>
|
||||
|
||||
@@ -68,12 +68,12 @@
|
||||
|
||||
<!-- Actions -->
|
||||
<div class="space-y-3">
|
||||
<a href="{{ base_url }}storefront/account/loyalty"
|
||||
<a href="{{ base_url }}account/loyalty"
|
||||
class="block w-full py-3 px-4 text-white font-semibold rounded-lg transition-colors text-center"
|
||||
style="background-color: var(--color-primary)">
|
||||
View My Loyalty Dashboard
|
||||
</a>
|
||||
<a href="{{ base_url }}storefront"
|
||||
<a href="{{ base_url }}"
|
||||
class="block w-full py-3 px-4 text-gray-700 dark:text-gray-300 font-medium rounded-lg border border-gray-300 dark:border-gray-600 hover:bg-gray-50 dark:hover:bg-gray-700 transition-colors text-center">
|
||||
Continue Shopping
|
||||
</a>
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
<div class="max-w-4xl mx-auto px-4 sm:px-6 lg:px-8 py-8">
|
||||
<!-- Page Header -->
|
||||
<div class="mb-8">
|
||||
<a href="{{ base_url }}storefront/account/loyalty" class="inline-flex items-center text-sm text-gray-600 dark:text-gray-400 hover:text-primary mb-4">
|
||||
<a href="{{ base_url }}account/loyalty" class="inline-flex items-center text-sm text-gray-600 dark:text-gray-400 hover:text-primary mb-4">
|
||||
<span x-html="$icon('arrow-left', 'w-4 h-4 mr-2')"></span>
|
||||
Back to Loyalty
|
||||
</a>
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
<nav class="flex mb-4" aria-label="Breadcrumb">
|
||||
<ol class="inline-flex items-center space-x-1 md:space-x-3">
|
||||
<li class="inline-flex items-center">
|
||||
<a href="{{ base_url }}storefront/account/dashboard"
|
||||
<a href="{{ base_url }}account/dashboard"
|
||||
class="inline-flex items-center text-sm font-medium text-gray-700 hover:text-primary dark:text-gray-400 dark:hover:text-white"
|
||||
style="--hover-color: var(--color-primary)">
|
||||
<span class="w-4 h-4 mr-2" x-html="$icon('home', 'w-4 h-4')"></span>
|
||||
@@ -292,7 +292,7 @@ function shopMessages() {
|
||||
try {
|
||||
const token = localStorage.getItem('customer_token');
|
||||
if (!token) {
|
||||
window.location.href = '{{ base_url }}storefront/account/login?next=' + encodeURIComponent(window.location.pathname);
|
||||
window.location.href = '{{ base_url }}account/login?next=' + encodeURIComponent(window.location.pathname);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -313,7 +313,7 @@ function shopMessages() {
|
||||
if (response.status === 401) {
|
||||
localStorage.removeItem('customer_token');
|
||||
localStorage.removeItem('customer_user');
|
||||
window.location.href = '{{ base_url }}storefront/account/login?next=' + encodeURIComponent(window.location.pathname);
|
||||
window.location.href = '{{ base_url }}account/login?next=' + encodeURIComponent(window.location.pathname);
|
||||
return;
|
||||
}
|
||||
throw new Error('Failed to load conversations');
|
||||
@@ -335,7 +335,7 @@ function shopMessages() {
|
||||
try {
|
||||
const token = localStorage.getItem('customer_token');
|
||||
if (!token) {
|
||||
window.location.href = '{{ base_url }}storefront/account/login?next=' + encodeURIComponent(window.location.pathname);
|
||||
window.location.href = '{{ base_url }}account/login?next=' + encodeURIComponent(window.location.pathname);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -357,7 +357,7 @@ function shopMessages() {
|
||||
});
|
||||
|
||||
// Update URL without reload
|
||||
const url = `{{ base_url }}storefront/account/messages/${conversationId}`;
|
||||
const url = `{{ base_url }}account/messages/${conversationId}`;
|
||||
history.pushState({}, '', url);
|
||||
} catch (error) {
|
||||
console.error('Error loading conversation:', error);
|
||||
@@ -404,7 +404,7 @@ function shopMessages() {
|
||||
this.loadConversations();
|
||||
|
||||
// Update URL
|
||||
history.pushState({}, '', '{{ base_url }}storefront/account/messages');
|
||||
history.pushState({}, '', '{{ base_url }}account/messages');
|
||||
},
|
||||
|
||||
async sendReply() {
|
||||
@@ -415,7 +415,7 @@ function shopMessages() {
|
||||
try {
|
||||
const token = localStorage.getItem('customer_token');
|
||||
if (!token) {
|
||||
window.location.href = '{{ base_url }}storefront/account/login?next=' + encodeURIComponent(window.location.pathname);
|
||||
window.location.href = '{{ base_url }}account/login?next=' + encodeURIComponent(window.location.pathname);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -11,11 +11,11 @@
|
||||
<nav class="mb-6" aria-label="Breadcrumb">
|
||||
<ol class="flex items-center space-x-2 text-sm text-gray-500 dark:text-gray-400">
|
||||
<li>
|
||||
<a href="{{ base_url }}storefront/account/dashboard" class="hover:text-primary">My Account</a>
|
||||
<a href="{{ base_url }}account/dashboard" class="hover:text-primary">My Account</a>
|
||||
</li>
|
||||
<li class="flex items-center">
|
||||
<span class="h-4 w-4 mx-2" x-html="$icon('chevron-right', 'h-4 w-4')"></span>
|
||||
<a href="{{ base_url }}storefront/account/orders" class="hover:text-primary">Orders</a>
|
||||
<a href="{{ base_url }}account/orders" class="hover:text-primary">Orders</a>
|
||||
</li>
|
||||
<li class="flex items-center">
|
||||
<span class="h-4 w-4 mx-2" x-html="$icon('chevron-right', 'h-4 w-4')"></span>
|
||||
@@ -36,7 +36,7 @@
|
||||
<div class="ml-3">
|
||||
<h3 class="text-lg font-medium text-red-800 dark:text-red-200">Error loading order</h3>
|
||||
<p class="mt-1 text-sm text-red-700 dark:text-red-300" x-text="error"></p>
|
||||
<a href="{{ base_url }}storefront/account/orders"
|
||||
<a href="{{ base_url }}account/orders"
|
||||
class="mt-4 inline-flex items-center px-4 py-2 border border-transparent rounded-md shadow-sm text-sm font-medium text-white bg-red-600 hover:bg-red-700">
|
||||
Back to Orders
|
||||
</a>
|
||||
@@ -314,7 +314,7 @@
|
||||
<p class="text-sm text-gray-600 dark:text-gray-300 mb-4">
|
||||
If you have any questions about your order, please contact us.
|
||||
</p>
|
||||
<a href="{{ base_url }}storefront/account/messages"
|
||||
<a href="{{ base_url }}account/messages"
|
||||
class="inline-flex items-center px-4 py-2 border border-transparent rounded-md shadow-sm text-sm font-medium text-white transition-colors"
|
||||
style="background-color: var(--color-primary)">
|
||||
<span class="h-4 w-4 mr-2" x-html="$icon('chat-bubble-left', 'h-4 w-4')"></span>
|
||||
@@ -326,7 +326,7 @@
|
||||
|
||||
<!-- Back Button -->
|
||||
<div class="mt-8">
|
||||
<a href="{{ base_url }}storefront/account/orders"
|
||||
<a href="{{ base_url }}account/orders"
|
||||
class="inline-flex items-center text-sm font-medium text-gray-600 dark:text-gray-400 hover:text-primary">
|
||||
<span class="h-4 w-4 mr-2" x-html="$icon('chevron-left', 'h-4 w-4')"></span>
|
||||
Back to Orders
|
||||
@@ -375,7 +375,7 @@ function shopOrderDetailPage() {
|
||||
try {
|
||||
const token = localStorage.getItem('customer_token');
|
||||
if (!token) {
|
||||
window.location.href = '{{ base_url }}storefront/account/login?next=' + encodeURIComponent(window.location.pathname);
|
||||
window.location.href = '{{ base_url }}account/login?next=' + encodeURIComponent(window.location.pathname);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -389,7 +389,7 @@ function shopOrderDetailPage() {
|
||||
if (response.status === 401) {
|
||||
localStorage.removeItem('customer_token');
|
||||
localStorage.removeItem('customer_user');
|
||||
window.location.href = '{{ base_url }}storefront/account/login?next=' + encodeURIComponent(window.location.pathname);
|
||||
window.location.href = '{{ base_url }}account/login?next=' + encodeURIComponent(window.location.pathname);
|
||||
return;
|
||||
}
|
||||
if (response.status === 404) {
|
||||
@@ -501,7 +501,7 @@ function shopOrderDetailPage() {
|
||||
try {
|
||||
const token = localStorage.getItem('customer_token');
|
||||
if (!token) {
|
||||
window.location.href = '{{ base_url }}storefront/account/login?next=' + encodeURIComponent(window.location.pathname);
|
||||
window.location.href = '{{ base_url }}account/login?next=' + encodeURIComponent(window.location.pathname);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -516,7 +516,7 @@ function shopOrderDetailPage() {
|
||||
if (response.status === 401) {
|
||||
localStorage.removeItem('customer_token');
|
||||
localStorage.removeItem('customer_user');
|
||||
window.location.href = '{{ base_url }}storefront/account/login?next=' + encodeURIComponent(window.location.pathname);
|
||||
window.location.href = '{{ base_url }}account/login?next=' + encodeURIComponent(window.location.pathname);
|
||||
return;
|
||||
}
|
||||
if (response.status === 404) {
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
<nav class="mb-6" aria-label="Breadcrumb">
|
||||
<ol class="flex items-center space-x-2 text-sm text-gray-500 dark:text-gray-400">
|
||||
<li>
|
||||
<a href="{{ base_url }}storefront/account/dashboard" class="hover:text-primary">My Account</a>
|
||||
<a href="{{ base_url }}account/dashboard" class="hover:text-primary">My Account</a>
|
||||
</li>
|
||||
<li class="flex items-center">
|
||||
<span class="h-4 w-4 mx-2" x-html="$icon('chevron-right', 'h-4 w-4')"></span>
|
||||
@@ -45,7 +45,7 @@
|
||||
<span class="mx-auto h-12 w-12 text-gray-400 block" x-html="$icon('shopping-bag', 'h-12 w-12 mx-auto')"></span>
|
||||
<h3 class="mt-4 text-lg font-medium text-gray-900 dark:text-white">No orders yet</h3>
|
||||
<p class="mt-2 text-gray-500 dark:text-gray-400">Start shopping to see your orders here.</p>
|
||||
<a href="{{ base_url }}storefront/products"
|
||||
<a href="{{ base_url }}products"
|
||||
class="mt-6 inline-flex items-center px-4 py-2 border border-transparent rounded-md shadow-sm text-sm font-medium text-white bg-primary hover:bg-primary-dark transition-colors"
|
||||
style="background-color: var(--color-primary)">
|
||||
Browse Products
|
||||
@@ -79,7 +79,7 @@
|
||||
<span x-text="getStatusLabel(order.status)"></span>
|
||||
</span>
|
||||
<!-- View Details Button -->
|
||||
<a :href="'{{ base_url }}storefront/account/orders/' + order.id"
|
||||
<a :href="'{{ base_url }}account/orders/' + order.id"
|
||||
class="inline-flex items-center px-3 py-1.5 border border-gray-300 dark:border-gray-600 rounded-md text-sm font-medium text-gray-700 dark:text-gray-300 bg-white dark:bg-gray-700 hover:bg-gray-50 dark:hover:bg-gray-600 transition-colors">
|
||||
View Details
|
||||
<span class="ml-2 h-4 w-4" x-html="$icon('chevron-right', 'h-4 w-4')"></span>
|
||||
@@ -167,7 +167,7 @@ function shopOrdersPage() {
|
||||
try {
|
||||
const token = localStorage.getItem('customer_token');
|
||||
if (!token) {
|
||||
window.location.href = '{{ base_url }}storefront/account/login?next=' + encodeURIComponent(window.location.pathname);
|
||||
window.location.href = '{{ base_url }}account/login?next=' + encodeURIComponent(window.location.pathname);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -182,7 +182,7 @@ function shopOrdersPage() {
|
||||
if (response.status === 401) {
|
||||
localStorage.removeItem('customer_token');
|
||||
localStorage.removeItem('customer_user');
|
||||
window.location.href = '{{ base_url }}storefront/account/login?next=' + encodeURIComponent(window.location.pathname);
|
||||
window.location.href = '{{ base_url }}account/login?next=' + encodeURIComponent(window.location.pathname);
|
||||
return;
|
||||
}
|
||||
throw new Error('Failed to load orders');
|
||||
|
||||
Reference in New Issue
Block a user