refactor: migrate templates and static files to self-contained modules

Templates Migration:
- Migrate admin templates to modules (tenancy, billing, monitoring, marketplace, etc.)
- Migrate vendor templates to modules (tenancy, billing, orders, messaging, etc.)
- Migrate storefront templates to modules (catalog, customers, orders, cart, checkout, cms)
- Migrate public templates to modules (billing, marketplace, cms)
- Keep shared templates in app/templates/ (base.html, errors/, partials/, macros/)
- Migrate letzshop partials to marketplace module

Static Files Migration:
- Migrate admin JS to modules: tenancy (23 files), core (5 files), monitoring (1 file)
- Migrate vendor JS to modules: tenancy (4 files), core (2 files)
- Migrate shared JS: vendor-selector.js to core, media-picker.js to cms
- Migrate storefront JS: storefront-layout.js to core
- Keep framework JS in static/ (api-client, utils, money, icons, log-config, lib/)
- Update all template references to use module_static paths

Naming Consistency:
- Rename static/platform/ to static/public/
- Rename app/templates/platform/ to app/templates/public/
- Update all extends and static references

Documentation:
- Update module-system.md with shared templates documentation
- Update frontend-structure.md with new module JS organization

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
2026-02-01 14:34:16 +01:00
parent 843703258f
commit 4e28d91a78
542 changed files with 11603 additions and 9037 deletions

View File

@@ -0,0 +1,2 @@
# app/modules/core/routes/pages/__init__.py
"""Core module page routes."""

View File

@@ -0,0 +1,159 @@
# app/modules/core/routes/pages/admin.py
"""
Core Admin Page Routes (HTML rendering).
Admin pages for core platform functionality:
- Login, logout, authentication
- Dashboard
- Settings
- Feature management
"""
from fastapi import APIRouter, Depends, Request
from fastapi.responses import HTMLResponse, RedirectResponse
from sqlalchemy.orm import Session
from app.api.deps import get_current_admin_optional, get_db, require_menu_access
from app.modules.core.utils.page_context import get_admin_context
from app.templates_config import templates
from models.database.admin_menu_config import FrontendType
from models.database.user import User
router = APIRouter()
# ============================================================================
# PUBLIC ROUTES (No Authentication Required)
# ============================================================================
@router.get("/", response_class=RedirectResponse, include_in_schema=False)
async def admin_root(
current_user: User | None = Depends(get_current_admin_optional),
):
"""
Redirect /admin/ based on authentication status.
- Authenticated admin users -> /admin/dashboard
- Unauthenticated users -> /admin/login
"""
if current_user:
return RedirectResponse(url="/admin/dashboard", status_code=302)
return RedirectResponse(url="/admin/login", status_code=302)
@router.get("/login", response_class=HTMLResponse, include_in_schema=False)
async def admin_login_page(
request: Request,
current_user: User | None = Depends(get_current_admin_optional),
):
"""
Render admin login page.
If user is already authenticated as admin, redirect to dashboard.
Otherwise, show login form.
"""
if current_user:
return RedirectResponse(url="/admin/dashboard", status_code=302)
return templates.TemplateResponse("tenancy/admin/login.html", {"request": request})
@router.get("/select-platform", response_class=HTMLResponse, include_in_schema=False)
async def admin_select_platform_page(
request: Request,
current_user: User | None = Depends(get_current_admin_optional),
):
"""
Render platform selection page for platform admins.
Platform admins with access to multiple platforms must select
which platform they want to manage before accessing the dashboard.
Super admins are redirected to dashboard (they have global access).
"""
if not current_user:
return RedirectResponse(url="/admin/login", status_code=302)
if current_user.is_super_admin:
return RedirectResponse(url="/admin/dashboard", status_code=302)
return templates.TemplateResponse(
"tenancy/admin/select-platform.html",
{"request": request, "user": current_user},
)
# ============================================================================
# AUTHENTICATED ROUTES (Admin Only)
# ============================================================================
@router.get("/dashboard", response_class=HTMLResponse, include_in_schema=False)
async def admin_dashboard_page(
request: Request,
current_user: User = Depends(require_menu_access("dashboard", FrontendType.ADMIN)),
db: Session = Depends(get_db),
):
"""
Render admin dashboard page.
Shows platform statistics and recent activity.
"""
return templates.TemplateResponse(
"core/admin/dashboard.html",
get_admin_context(request, current_user),
)
@router.get("/settings", response_class=HTMLResponse, include_in_schema=False)
async def admin_settings_page(
request: Request,
current_user: User = Depends(require_menu_access("settings", FrontendType.ADMIN)),
db: Session = Depends(get_db),
):
"""
Render admin settings page.
Platform configuration and preferences.
"""
return templates.TemplateResponse(
"core/admin/settings.html",
get_admin_context(request, current_user),
)
@router.get("/my-menu", response_class=HTMLResponse, include_in_schema=False)
async def admin_my_menu_config(
request: Request,
current_user: User = Depends(require_menu_access("my-menu", FrontendType.ADMIN)),
db: Session = Depends(get_db),
):
"""
Render personal menu configuration page for super admins.
Allows super admins to customize their own sidebar menu.
"""
# Only super admins can configure their own menu
if not current_user.is_super_admin:
return RedirectResponse(url="/admin/settings", status_code=302)
return templates.TemplateResponse(
"core/admin/my-menu-config.html",
get_admin_context(request, current_user),
)
@router.get("/features", response_class=HTMLResponse, include_in_schema=False)
async def admin_features_page(
request: Request,
current_user: User = Depends(
require_menu_access("subscription-tiers", FrontendType.ADMIN)
),
db: Session = Depends(get_db),
):
"""
Render feature management page.
Shows all features with tier assignments and allows editing.
"""
return templates.TemplateResponse(
"billing/admin/features.html",
get_admin_context(request, current_user),
)

View File

@@ -0,0 +1,69 @@
# app/modules/core/routes/pages/vendor.py
"""
Core Vendor Page Routes (HTML rendering).
Vendor pages for core functionality:
- Media library
- Notifications
"""
from fastapi import APIRouter, Depends, Path, Request
from fastapi.responses import HTMLResponse
from sqlalchemy.orm import Session
from app.api.deps import get_current_vendor_from_cookie_or_header, get_db
from app.modules.core.utils.page_context import get_vendor_context
from app.templates_config import templates
from models.database.user import User
router = APIRouter()
# ============================================================================
# MEDIA LIBRARY
# ============================================================================
@router.get(
"/{vendor_code}/media", response_class=HTMLResponse, include_in_schema=False
)
async def vendor_media_page(
request: Request,
vendor_code: str = Path(..., description="Vendor code"),
current_user: User = Depends(get_current_vendor_from_cookie_or_header),
db: Session = Depends(get_db),
):
"""
Render media library page.
JavaScript loads media files via API.
"""
return templates.TemplateResponse(
"cms/vendor/media.html",
get_vendor_context(request, db, current_user, vendor_code),
)
# ============================================================================
# NOTIFICATIONS
# ============================================================================
@router.get(
"/{vendor_code}/notifications",
response_class=HTMLResponse,
include_in_schema=False,
)
async def vendor_notifications_page(
request: Request,
vendor_code: str = Path(..., description="Vendor code"),
current_user: User = Depends(get_current_vendor_from_cookie_or_header),
db: Session = Depends(get_db),
):
"""
Render notifications center page.
JavaScript loads notifications via API.
"""
return templates.TemplateResponse(
"messaging/vendor/notifications.html",
get_vendor_context(request, db, current_user, vendor_code),
)