feat(merchant): extract merchant portal as first-class frontend with auth, Tailwind fixes, and Gitea CI
Some checks failed
Some checks failed
- Extract login/dashboard from billing module into core (matching admin pattern) - Add merchant auth API with path-isolated cookies (path=/merchants) - Add merchant base layout with sidebar/header partials and Alpine.js init - Add frontend detection and login redirect for MERCHANT type - Wire merchant token in shared api-client.js (get/clear) - Migrate billing templates to merchant base with dark mode support - Fix Tailwind: rename shop→storefront in sources and config - DRY Makefile tailwind targets with TAILWIND_FRONTENDS loop - Rebuild all Tailwind outputs (production minified) - Add Gitea Actions CI workflow (ruff, pytest, architecture, docs) - Add Gitea deployment documentation Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
93
app/modules/core/routes/pages/merchant.py
Normal file
93
app/modules/core/routes/pages/merchant.py
Normal file
@@ -0,0 +1,93 @@
|
||||
# app/modules/core/routes/pages/merchant.py
|
||||
"""
|
||||
Core Merchant Page Routes (HTML rendering).
|
||||
|
||||
Merchant pages for core functionality:
|
||||
- Login page
|
||||
- Dashboard
|
||||
- Root redirect
|
||||
|
||||
These are core concerns, not billing-specific, matching the admin pattern
|
||||
where login/dashboard live in core (app/modules/core/routes/pages/admin.py).
|
||||
"""
|
||||
|
||||
from fastapi import APIRouter, Depends, Request
|
||||
from fastapi.responses import HTMLResponse, RedirectResponse
|
||||
from sqlalchemy.orm import Session
|
||||
|
||||
from app.api.deps import get_current_merchant_from_cookie_or_header, get_current_merchant_optional, get_db
|
||||
from app.modules.core.utils.page_context import get_context_for_frontend
|
||||
from app.modules.enums import FrontendType
|
||||
from app.templates_config import templates
|
||||
from models.schema.auth import UserContext
|
||||
|
||||
ROUTE_CONFIG = {
|
||||
"prefix": "",
|
||||
}
|
||||
|
||||
router = APIRouter()
|
||||
|
||||
|
||||
# ============================================================================
|
||||
# PUBLIC ROUTES (No Authentication Required)
|
||||
# ============================================================================
|
||||
|
||||
|
||||
@router.get("/", response_class=RedirectResponse, include_in_schema=False)
|
||||
async def merchant_root(
|
||||
current_user: UserContext | None = Depends(get_current_merchant_optional),
|
||||
):
|
||||
"""
|
||||
Redirect /merchants/ based on authentication status.
|
||||
|
||||
- Authenticated merchant users -> /merchants/dashboard
|
||||
- Unauthenticated users -> /merchants/login
|
||||
"""
|
||||
if current_user:
|
||||
return RedirectResponse(url="/merchants/dashboard", status_code=302)
|
||||
|
||||
return RedirectResponse(url="/merchants/login", status_code=302)
|
||||
|
||||
|
||||
@router.get("/login", response_class=HTMLResponse, include_in_schema=False)
|
||||
async def merchant_login_page(
|
||||
request: Request,
|
||||
current_user: UserContext | None = Depends(get_current_merchant_optional),
|
||||
):
|
||||
"""
|
||||
Render merchant login page.
|
||||
|
||||
If user is already authenticated as merchant, redirect to dashboard.
|
||||
Otherwise, show login form.
|
||||
"""
|
||||
if current_user:
|
||||
return RedirectResponse(url="/merchants/dashboard", status_code=302)
|
||||
|
||||
return templates.TemplateResponse("tenancy/merchant/login.html", {"request": request})
|
||||
|
||||
|
||||
# ============================================================================
|
||||
# AUTHENTICATED ROUTES (Merchant Only)
|
||||
# ============================================================================
|
||||
|
||||
|
||||
@router.get("/dashboard", response_class=HTMLResponse, include_in_schema=False)
|
||||
async def merchant_dashboard_page(
|
||||
request: Request,
|
||||
current_user: UserContext = Depends(get_current_merchant_from_cookie_or_header),
|
||||
db: Session = Depends(get_db),
|
||||
):
|
||||
"""
|
||||
Render merchant dashboard page.
|
||||
Shows merchant overview with stores and subscriptions.
|
||||
"""
|
||||
context = get_context_for_frontend(
|
||||
FrontendType.MERCHANT,
|
||||
request,
|
||||
db,
|
||||
user=current_user,
|
||||
)
|
||||
return templates.TemplateResponse(
|
||||
"core/merchant/dashboard.html",
|
||||
context,
|
||||
)
|
||||
Reference in New Issue
Block a user