# app/modules/loyalty/routes/pages/storefront.py """ Loyalty Storefront Page Routes (HTML rendering). Customer-facing pages for: - Loyalty dashboard (view points, rewards, history) - Self-service enrollment - Digital card display """ import logging from fastapi import APIRouter, Depends, Query, Request from fastapi.responses import HTMLResponse from sqlalchemy.orm import Session from app.api.deps import get_current_customer_from_cookie_or_header, get_db from app.modules.core.utils.page_context import get_storefront_context from app.modules.customers.models import Customer from app.modules.loyalty.services import program_service from app.templates_config import templates logger = logging.getLogger(__name__) router = APIRouter() # No custom prefix - routes are mounted directly at /storefront/ # Following same pattern as customers module # ============================================================================ # CUSTOMER LOYALTY DASHBOARD (Authenticated) # ============================================================================ @router.get( "/account/loyalty", response_class=HTMLResponse, include_in_schema=False, ) async def customer_loyalty_dashboard( request: Request, current_customer: Customer = Depends(get_current_customer_from_cookie_or_header), db: Session = Depends(get_db), ): """ Render customer loyalty dashboard. Shows points balance, available rewards, and transaction history. """ logger.debug( "[STOREFRONT] customer_loyalty_dashboard REACHED", extra={ "path": request.url.path, "customer_id": current_customer.id if current_customer else None, }, ) context = get_storefront_context(request, db=db) return templates.TemplateResponse( "loyalty/storefront/dashboard.html", context, ) @router.get( "/account/loyalty/history", response_class=HTMLResponse, include_in_schema=False, ) async def customer_loyalty_history( request: Request, current_customer: Customer = Depends(get_current_customer_from_cookie_or_header), db: Session = Depends(get_db), ): """ Render full transaction history page. """ logger.debug( "[STOREFRONT] customer_loyalty_history REACHED", extra={ "path": request.url.path, "customer_id": current_customer.id if current_customer else None, }, ) context = get_storefront_context(request, db=db) return templates.TemplateResponse( "loyalty/storefront/history.html", context, ) # ============================================================================ # SELF-SERVICE ENROLLMENT (Public - No Authentication) # ============================================================================ @router.get( "/loyalty/join", response_class=HTMLResponse, include_in_schema=False, ) async def loyalty_self_enrollment( request: Request, db: Session = Depends(get_db), ): """ Render self-service enrollment page. Public page - customers can sign up via QR code at store counter. """ logger.debug( "[STOREFRONT] loyalty_self_enrollment REACHED", extra={ "path": request.url.path, }, ) store = request.state.store program = program_service.get_active_program_by_store(db, store.id) if store else None context = get_storefront_context(request, db=db, program=program) return templates.TemplateResponse( "loyalty/storefront/enroll.html", context, ) @router.get( "/loyalty/join/success", response_class=HTMLResponse, include_in_schema=False, ) async def loyalty_enrollment_success( request: Request, card: str = Query(None, description="Card number"), already: str = Query(None, description="Already enrolled flag"), db: Session = Depends(get_db), ): """ Render enrollment success page. Shows card number and next steps. """ logger.debug( "[STOREFRONT] loyalty_enrollment_success REACHED", extra={ "path": request.url.path, "card": card, }, ) context = get_storefront_context(request, db=db) context["enrolled_card_number"] = card # Provide merchant locations and cross-location flag server-side so # the template doesn't depend on sessionStorage surviving refreshes. store = getattr(request.state, "store", None) if store: from app.modules.loyalty.services import program_service settings = program_service.get_merchant_settings(db, store.merchant_id) locations = program_service.get_merchant_locations(db, store.merchant_id) context["server_already_enrolled"] = already == "1" context["server_allow_cross_location"] = ( settings.allow_cross_location_redemption if settings else True ) context["server_merchant_locations"] = [ {"id": loc.id, "name": loc.name} for loc in locations ] else: context["server_already_enrolled"] = False context["server_allow_cross_location"] = True context["server_merchant_locations"] = [] return templates.TemplateResponse( "loyalty/storefront/enroll-success.html", context, )