feat(loyalty): align program view, edit, and analytics pages across all frontends
Some checks failed
Some checks failed
Standardize naming (Program for view/edit, Analytics for stats), create shared read-only program-view partial, fix admin edit field population bug (14 missing fields), add store Program menu item, and rename merchant Overview→Program, Settings→Analytics. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -3,7 +3,9 @@
|
||||
Loyalty Merchant Page Routes (HTML rendering).
|
||||
|
||||
Merchant portal pages for:
|
||||
- Loyalty overview (aggregate stats across all stores)
|
||||
- Loyalty program (read-only view)
|
||||
- Loyalty program edit
|
||||
- Loyalty analytics (aggregate stats across all stores)
|
||||
|
||||
Authentication: merchant_token cookie or Authorization header.
|
||||
|
||||
@@ -60,23 +62,22 @@ def _get_merchant_context(
|
||||
|
||||
|
||||
# ============================================================================
|
||||
# LOYALTY OVERVIEW
|
||||
# LOYALTY PROGRAM (Read-only view)
|
||||
# ============================================================================
|
||||
|
||||
|
||||
@router.get("/overview", response_class=HTMLResponse, include_in_schema=False)
|
||||
async def merchant_loyalty_overview(
|
||||
@router.get("/program", response_class=HTMLResponse, include_in_schema=False)
|
||||
async def merchant_loyalty_program(
|
||||
request: Request,
|
||||
current_user: UserContext = Depends(get_current_merchant_from_cookie_or_header),
|
||||
merchant: Merchant = Depends(get_merchant_for_current_user_page),
|
||||
db: Session = Depends(get_db),
|
||||
):
|
||||
"""
|
||||
Render merchant loyalty overview page.
|
||||
Render merchant loyalty program view page.
|
||||
|
||||
Shows aggregate loyalty program stats across all merchant stores.
|
||||
Shows read-only program configuration with link to edit.
|
||||
"""
|
||||
# Get merchant stats server-side
|
||||
merchant_id = merchant.id
|
||||
stats = {}
|
||||
try:
|
||||
@@ -95,25 +96,25 @@ async def merchant_loyalty_overview(
|
||||
merchant_id=merchant_id,
|
||||
)
|
||||
return templates.TemplateResponse(
|
||||
"loyalty/merchant/overview.html",
|
||||
"loyalty/merchant/program.html",
|
||||
context,
|
||||
)
|
||||
|
||||
|
||||
# ============================================================================
|
||||
# LOYALTY SETTINGS
|
||||
# LOYALTY PROGRAM EDIT
|
||||
# ============================================================================
|
||||
|
||||
|
||||
@router.get("/settings", response_class=HTMLResponse, include_in_schema=False)
|
||||
async def merchant_loyalty_settings(
|
||||
@router.get("/program/edit", response_class=HTMLResponse, include_in_schema=False)
|
||||
async def merchant_loyalty_program_edit(
|
||||
request: Request,
|
||||
current_user: UserContext = Depends(get_current_merchant_from_cookie_or_header),
|
||||
merchant: Merchant = Depends(get_merchant_for_current_user_page),
|
||||
db: Session = Depends(get_db),
|
||||
):
|
||||
"""
|
||||
Render merchant loyalty settings page.
|
||||
Render merchant loyalty program edit page.
|
||||
|
||||
Allows merchant to create, configure, and manage their loyalty program.
|
||||
"""
|
||||
@@ -124,6 +125,46 @@ async def merchant_loyalty_settings(
|
||||
merchant_id=merchant.id,
|
||||
)
|
||||
return templates.TemplateResponse(
|
||||
"loyalty/merchant/settings.html",
|
||||
"loyalty/merchant/program-edit.html",
|
||||
context,
|
||||
)
|
||||
|
||||
|
||||
# ============================================================================
|
||||
# LOYALTY ANALYTICS
|
||||
# ============================================================================
|
||||
|
||||
|
||||
@router.get("/analytics", response_class=HTMLResponse, include_in_schema=False)
|
||||
async def merchant_loyalty_analytics(
|
||||
request: Request,
|
||||
current_user: UserContext = Depends(get_current_merchant_from_cookie_or_header),
|
||||
merchant: Merchant = Depends(get_merchant_for_current_user_page),
|
||||
db: Session = Depends(get_db),
|
||||
):
|
||||
"""
|
||||
Render merchant loyalty analytics page.
|
||||
|
||||
Shows aggregate loyalty program stats across all merchant stores.
|
||||
"""
|
||||
merchant_id = merchant.id
|
||||
stats = {}
|
||||
try:
|
||||
stats = program_service.get_merchant_stats(db, merchant_id)
|
||||
except Exception:
|
||||
logger.warning(
|
||||
f"Failed to load loyalty stats for merchant {merchant_id}",
|
||||
exc_info=True,
|
||||
)
|
||||
|
||||
context = _get_merchant_context(
|
||||
request,
|
||||
db,
|
||||
current_user,
|
||||
loyalty_stats=stats,
|
||||
merchant_id=merchant_id,
|
||||
)
|
||||
return templates.TemplateResponse(
|
||||
"loyalty/merchant/analytics.html",
|
||||
context,
|
||||
)
|
||||
|
||||
@@ -5,8 +5,9 @@ Loyalty Store Page Routes (HTML rendering).
|
||||
Store pages for:
|
||||
- Loyalty terminal (primary daily interface for staff)
|
||||
- Loyalty members management
|
||||
- Program settings
|
||||
- Stats dashboard
|
||||
- Program view (read-only)
|
||||
- Program edit (settings)
|
||||
- Analytics dashboard
|
||||
|
||||
Routes follow the standard store convention: /loyalty/...
|
||||
so they match the menu URLs in definition.py.
|
||||
@@ -183,49 +184,49 @@ async def store_loyalty_card_detail(
|
||||
|
||||
|
||||
# ============================================================================
|
||||
# STATS DASHBOARD
|
||||
# PROGRAM VIEW (Read-only)
|
||||
# ============================================================================
|
||||
|
||||
|
||||
@router.get(
|
||||
"/loyalty/stats",
|
||||
"/loyalty/program",
|
||||
response_class=HTMLResponse,
|
||||
include_in_schema=False,
|
||||
)
|
||||
async def store_loyalty_stats(
|
||||
async def store_loyalty_program(
|
||||
request: Request,
|
||||
store_code: str = Depends(get_resolved_store_code),
|
||||
current_user: User = Depends(get_current_store_from_cookie_or_header),
|
||||
db: Session = Depends(get_db),
|
||||
):
|
||||
"""
|
||||
Render loyalty statistics dashboard.
|
||||
Shows store's loyalty program metrics and trends.
|
||||
Render loyalty program view page (read-only).
|
||||
Shows program configuration. Edit button shown to merchant owners only.
|
||||
"""
|
||||
return templates.TemplateResponse(
|
||||
"loyalty/store/stats.html",
|
||||
"loyalty/store/program.html",
|
||||
get_store_context(request, db, current_user, store_code),
|
||||
)
|
||||
|
||||
|
||||
# ============================================================================
|
||||
# SETTINGS (Merchant Owner)
|
||||
# PROGRAM EDIT (Merchant Owner)
|
||||
# ============================================================================
|
||||
|
||||
|
||||
@router.get(
|
||||
"/loyalty/settings",
|
||||
"/loyalty/program/edit",
|
||||
response_class=HTMLResponse,
|
||||
include_in_schema=False,
|
||||
)
|
||||
async def store_loyalty_settings(
|
||||
async def store_loyalty_program_edit(
|
||||
request: Request,
|
||||
store_code: str = Depends(get_resolved_store_code),
|
||||
current_user: User = Depends(get_current_store_from_cookie_or_header),
|
||||
db: Session = Depends(get_db),
|
||||
):
|
||||
"""
|
||||
Render loyalty program settings page.
|
||||
Render loyalty program edit page.
|
||||
Allows merchant owners to create or edit their loyalty program.
|
||||
"""
|
||||
return templates.TemplateResponse(
|
||||
@@ -234,6 +235,32 @@ async def store_loyalty_settings(
|
||||
)
|
||||
|
||||
|
||||
# ============================================================================
|
||||
# ANALYTICS DASHBOARD
|
||||
# ============================================================================
|
||||
|
||||
|
||||
@router.get(
|
||||
"/loyalty/analytics",
|
||||
response_class=HTMLResponse,
|
||||
include_in_schema=False,
|
||||
)
|
||||
async def store_loyalty_analytics(
|
||||
request: Request,
|
||||
store_code: str = Depends(get_resolved_store_code),
|
||||
current_user: User = Depends(get_current_store_from_cookie_or_header),
|
||||
db: Session = Depends(get_db),
|
||||
):
|
||||
"""
|
||||
Render loyalty analytics dashboard.
|
||||
Shows store's loyalty program metrics and trends.
|
||||
"""
|
||||
return templates.TemplateResponse(
|
||||
"loyalty/store/analytics.html",
|
||||
get_store_context(request, db, current_user, store_code),
|
||||
)
|
||||
|
||||
|
||||
# ============================================================================
|
||||
# ENROLLMENT
|
||||
# ============================================================================
|
||||
|
||||
Reference in New Issue
Block a user