fix: loyalty module end-to-end — merchant route, store menus, sidebar, API error handling
Some checks failed
Some checks failed
- Add merchant loyalty overview route and template (was 404)
- Fix store loyalty route paths to match menu URLs (/{store_code}/loyalty/...)
- Add loyalty rewards card to storefront account dashboard
- Fix merchant overview to resolve merchant via get_merchant_for_current_user_page
- Fix store login to use store's primary platform for JWT token (interim fix)
- Fix apiClient to attach status/errorCode to thrown errors (fixes error.status
checks in 12+ JS files — loyalty settings, terminal, email templates, etc.)
- Hide "Add Product" sidebar button when catalog module is not enabled
- Add proposal doc for proper platform detection in store login flow
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -7,12 +7,15 @@ Store pages for:
|
||||
- Loyalty members management
|
||||
- Program settings
|
||||
- Stats dashboard
|
||||
|
||||
Routes follow the standard store convention: /{store_code}/loyalty/...
|
||||
so they match the menu URLs in definition.py.
|
||||
"""
|
||||
|
||||
import logging
|
||||
|
||||
from fastapi import APIRouter, Depends, Path, Request
|
||||
from fastapi.responses import HTMLResponse
|
||||
from fastapi.responses import HTMLResponse, RedirectResponse
|
||||
from sqlalchemy.orm import Session
|
||||
|
||||
from app.api.deps import get_current_store_from_cookie_or_header, get_db
|
||||
@@ -27,8 +30,9 @@ logger = logging.getLogger(__name__)
|
||||
router = APIRouter()
|
||||
|
||||
# Route configuration for module route discovery
|
||||
# No custom prefix — routes include /loyalty/ in their paths to follow
|
||||
# the standard store convention: /store/{store_code}/loyalty/...
|
||||
ROUTE_CONFIG = {
|
||||
"prefix": "/loyalty",
|
||||
"tags": ["store-loyalty"],
|
||||
}
|
||||
|
||||
@@ -76,13 +80,37 @@ def get_store_context(
|
||||
return context
|
||||
|
||||
|
||||
# ============================================================================
|
||||
# LOYALTY ROOT (Redirect to Terminal)
|
||||
# ============================================================================
|
||||
|
||||
|
||||
@router.get(
|
||||
"/{store_code}/loyalty",
|
||||
response_class=RedirectResponse,
|
||||
include_in_schema=False,
|
||||
)
|
||||
async def store_loyalty_root(
|
||||
store_code: str = Path(..., description="Store code"),
|
||||
current_user: User = Depends(get_current_store_from_cookie_or_header),
|
||||
):
|
||||
"""
|
||||
Redirect loyalty root to the terminal (primary daily interface).
|
||||
Menu item "Dashboard" points here.
|
||||
"""
|
||||
return RedirectResponse(
|
||||
url=f"/store/{store_code}/loyalty/terminal",
|
||||
status_code=302,
|
||||
)
|
||||
|
||||
|
||||
# ============================================================================
|
||||
# LOYALTY TERMINAL (Primary Daily Interface)
|
||||
# ============================================================================
|
||||
|
||||
|
||||
@router.get(
|
||||
"/{store_code}/terminal",
|
||||
"/{store_code}/loyalty/terminal",
|
||||
response_class=HTMLResponse,
|
||||
include_in_schema=False,
|
||||
)
|
||||
@@ -108,7 +136,7 @@ async def store_loyalty_terminal(
|
||||
|
||||
|
||||
@router.get(
|
||||
"/{store_code}/cards",
|
||||
"/{store_code}/loyalty/cards",
|
||||
response_class=HTMLResponse,
|
||||
include_in_schema=False,
|
||||
)
|
||||
@@ -129,7 +157,7 @@ async def store_loyalty_cards(
|
||||
|
||||
|
||||
@router.get(
|
||||
"/{store_code}/cards/{card_id}",
|
||||
"/{store_code}/loyalty/cards/{card_id}",
|
||||
response_class=HTMLResponse,
|
||||
include_in_schema=False,
|
||||
)
|
||||
@@ -156,7 +184,7 @@ async def store_loyalty_card_detail(
|
||||
|
||||
|
||||
@router.get(
|
||||
"/{store_code}/settings",
|
||||
"/{store_code}/loyalty/settings",
|
||||
response_class=HTMLResponse,
|
||||
include_in_schema=False,
|
||||
)
|
||||
@@ -182,7 +210,7 @@ async def store_loyalty_settings(
|
||||
|
||||
|
||||
@router.get(
|
||||
"/{store_code}/stats",
|
||||
"/{store_code}/loyalty/stats",
|
||||
response_class=HTMLResponse,
|
||||
include_in_schema=False,
|
||||
)
|
||||
@@ -208,7 +236,7 @@ async def store_loyalty_stats(
|
||||
|
||||
|
||||
@router.get(
|
||||
"/{store_code}/enroll",
|
||||
"/{store_code}/loyalty/enroll",
|
||||
response_class=HTMLResponse,
|
||||
include_in_schema=False,
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user