# app/modules/customers/routes/pages/storefront.py """ Customers Storefront Page Routes (HTML rendering). Storefront (customer shop) pages for customer account: - Registration - Login - Forgot password - Reset password - Account dashboard - Profile management - Addresses - Settings """ import logging from fastapi import APIRouter, Depends, Request from fastapi.responses import HTMLResponse, RedirectResponse 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.templates_config import templates logger = logging.getLogger(__name__) router = APIRouter() # ============================================================================ # CUSTOMER ACCOUNT - PUBLIC ROUTES (No Authentication) # ============================================================================ @router.get("/account/register", response_class=HTMLResponse, include_in_schema=False) async def shop_register_page(request: Request, db: Session = Depends(get_db)): """ Render customer registration page. No authentication required. """ logger.debug( "[STOREFRONT] shop_register_page REACHED", extra={ "path": request.url.path, "store": getattr(request.state, "store", "NOT SET"), "context": getattr(request.state, "context_type", "NOT SET"), }, ) return templates.TemplateResponse( "customers/storefront/register.html", get_storefront_context(request, db=db) ) @router.get("/account/login", response_class=HTMLResponse, include_in_schema=False) async def shop_login_page(request: Request, db: Session = Depends(get_db)): """ Render customer login page. No authentication required. """ logger.debug( "[STOREFRONT] shop_login_page REACHED", extra={ "path": request.url.path, "store": getattr(request.state, "store", "NOT SET"), "context": getattr(request.state, "context_type", "NOT SET"), }, ) return templates.TemplateResponse( "customers/storefront/login.html", get_storefront_context(request, db=db) ) @router.get( "/account/forgot-password", response_class=HTMLResponse, include_in_schema=False ) async def shop_forgot_password_page(request: Request, db: Session = Depends(get_db)): """ Render forgot password page. Allows customers to reset their password. """ logger.debug( "[STOREFRONT] shop_forgot_password_page REACHED", extra={ "path": request.url.path, "store": getattr(request.state, "store", "NOT SET"), "context": getattr(request.state, "context_type", "NOT SET"), }, ) return templates.TemplateResponse( "customers/storefront/forgot-password.html", get_storefront_context(request, db=db) ) @router.get( "/account/reset-password", response_class=HTMLResponse, include_in_schema=False ) async def shop_reset_password_page( request: Request, token: str = None, db: Session = Depends(get_db) ): """ Render reset password page. User lands here after clicking the reset link in their email. Token is passed as query parameter. """ logger.debug( "[STOREFRONT] shop_reset_password_page REACHED", extra={ "path": request.url.path, "store": getattr(request.state, "store", "NOT SET"), "context": getattr(request.state, "context_type", "NOT SET"), "has_token": bool(token), }, ) return templates.TemplateResponse( "customers/storefront/reset-password.html", get_storefront_context(request, db=db) ) # ============================================================================ # CUSTOMER ACCOUNT - ROOT REDIRECT # ============================================================================ @router.get("/account", response_class=RedirectResponse, include_in_schema=False) @router.get("/account/", response_class=RedirectResponse, include_in_schema=False) async def shop_account_root(request: Request): """ Redirect /storefront/account or /storefront/account/ to dashboard. """ logger.debug( "[STOREFRONT] shop_account_root REACHED", extra={ "path": request.url.path, "store": getattr(request.state, "store", "NOT SET"), "context": getattr(request.state, "context_type", "NOT SET"), }, ) # Get base_url from context for proper redirect store = getattr(request.state, "store", None) store_context = getattr(request.state, "store_context", None) access_method = ( store_context.get("detection_method", "unknown") if store_context else "unknown" ) base_url = "/" if access_method == "path" and store: 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}account/dashboard", status_code=302) # ============================================================================ # CUSTOMER ACCOUNT - AUTHENTICATED ROUTES # ============================================================================ @router.get( "/account/dashboard", response_class=HTMLResponse, include_in_schema=False ) async def shop_account_dashboard_page( request: Request, current_customer: Customer = Depends(get_current_customer_from_cookie_or_header), db: Session = Depends(get_db), ): """ Render customer account dashboard. Shows account overview, recent orders, and quick links. Requires customer authentication. """ logger.debug( "[STOREFRONT] shop_account_dashboard_page REACHED", extra={ "path": request.url.path, "store": getattr(request.state, "store", "NOT SET"), "context": getattr(request.state, "context_type", "NOT SET"), }, ) return templates.TemplateResponse( "customers/storefront/dashboard.html", get_storefront_context(request, db=db, user=current_customer), ) @router.get("/account/profile", response_class=HTMLResponse, include_in_schema=False) async def shop_profile_page( request: Request, current_customer: Customer = Depends(get_current_customer_from_cookie_or_header), db: Session = Depends(get_db), ): """ Render customer profile page. Edit personal information and preferences. Requires customer authentication. """ logger.debug( "[STOREFRONT] shop_profile_page REACHED", extra={ "path": request.url.path, "store": getattr(request.state, "store", "NOT SET"), "context": getattr(request.state, "context_type", "NOT SET"), }, ) return templates.TemplateResponse( "customers/storefront/profile.html", get_storefront_context(request, db=db, user=current_customer), ) @router.get( "/account/addresses", response_class=HTMLResponse, include_in_schema=False ) async def shop_addresses_page( request: Request, current_customer: Customer = Depends(get_current_customer_from_cookie_or_header), db: Session = Depends(get_db), ): """ Render customer addresses management page. Manage shipping and billing addresses. Requires customer authentication. """ logger.debug( "[STOREFRONT] shop_addresses_page REACHED", extra={ "path": request.url.path, "store": getattr(request.state, "store", "NOT SET"), "context": getattr(request.state, "context_type", "NOT SET"), }, ) return templates.TemplateResponse( "customers/storefront/addresses.html", get_storefront_context(request, db=db, user=current_customer), ) @router.get("/account/settings", response_class=HTMLResponse, include_in_schema=False) async def shop_settings_page( request: Request, current_customer: Customer = Depends(get_current_customer_from_cookie_or_header), db: Session = Depends(get_db), ): """ Render customer account settings page. Configure notifications, privacy, and preferences. Requires customer authentication. """ logger.debug( "[STOREFRONT] shop_settings_page REACHED", extra={ "path": request.url.path, "store": getattr(request.state, "store", "NOT SET"), "context": getattr(request.state, "context_type", "NOT SET"), }, ) return templates.TemplateResponse( "customers/storefront/settings.html", get_storefront_context(request, db=db, user=current_customer), )