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

@@ -1,9 +1,2 @@
# app/modules/marketplace/routes/pages/__init__.py
"""
Marketplace module page routes (HTML rendering).
Provides Jinja2 template rendering for marketplace management.
Note: Page routes can be added here as needed.
"""
__all__ = []
"""Marketplace module page routes."""

View File

@@ -0,0 +1,243 @@
# app/modules/marketplace/routes/pages/admin.py
"""
Marketplace Admin Page Routes (HTML rendering).
Admin pages for marketplace management:
- Import history
- Background tasks
- Marketplace integration
- Letzshop management
- Marketplace products
"""
from fastapi import APIRouter, Depends, Path, Request
from fastapi.responses import HTMLResponse
from sqlalchemy.orm import Session
from app.api.deps import get_db, require_menu_access
from app.core.config import settings
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()
# ============================================================================
# IMPORT MANAGEMENT ROUTES
# ============================================================================
@router.get("/imports", response_class=HTMLResponse, include_in_schema=False)
async def admin_imports_page(
request: Request,
current_user: User = Depends(require_menu_access("imports", FrontendType.ADMIN)),
db: Session = Depends(get_db),
):
"""
Render imports management page.
Shows import history and status.
"""
return templates.TemplateResponse(
"marketplace/admin/imports.html",
get_admin_context(request, current_user),
)
@router.get("/background-tasks", response_class=HTMLResponse, include_in_schema=False)
async def admin_background_tasks_page(
request: Request,
current_user: User = Depends(
require_menu_access("background-tasks", FrontendType.ADMIN)
),
db: Session = Depends(get_db),
):
"""
Render background tasks monitoring page.
Shows running and completed background tasks across the system.
"""
return templates.TemplateResponse(
"marketplace/admin/background-tasks.html",
get_admin_context(request, current_user, flower_url=settings.flower_url),
)
@router.get("/marketplace", response_class=HTMLResponse, include_in_schema=False)
async def admin_marketplace_page(
request: Request,
current_user: User = Depends(
require_menu_access("marketplace-letzshop", FrontendType.ADMIN)
),
db: Session = Depends(get_db),
):
"""
Render marketplace import management page.
Allows admins to import products for any vendor and monitor all imports.
"""
return templates.TemplateResponse(
"marketplace/admin/marketplace.html",
get_admin_context(request, current_user),
)
# ============================================================================
# MARKETPLACE INTEGRATION ROUTES
# ============================================================================
@router.get(
"/marketplace/letzshop", response_class=HTMLResponse, include_in_schema=False
)
async def admin_marketplace_letzshop_page(
request: Request,
current_user: User = Depends(
require_menu_access("marketplace-letzshop", FrontendType.ADMIN)
),
db: Session = Depends(get_db),
):
"""
Render unified Letzshop management page.
Combines products (import/export), orders, and settings management.
Admin can select a vendor and manage their Letzshop integration.
"""
return templates.TemplateResponse(
"marketplace/admin/marketplace-letzshop.html",
get_admin_context(request, current_user),
)
@router.get(
"/letzshop/orders/{order_id}",
response_class=HTMLResponse,
include_in_schema=False,
)
async def admin_letzshop_order_detail_page(
request: Request,
order_id: int = Path(..., description="Letzshop order ID"),
current_user: User = Depends(
require_menu_access("marketplace-letzshop", FrontendType.ADMIN)
),
db: Session = Depends(get_db),
):
"""
Render detailed Letzshop order page.
Shows full order information with shipping address, billing address,
product details, and order history.
"""
return templates.TemplateResponse(
"marketplace/admin/letzshop-order-detail.html",
get_admin_context(request, current_user, order_id=order_id),
)
@router.get(
"/letzshop/products/{product_id}",
response_class=HTMLResponse,
include_in_schema=False,
)
async def admin_letzshop_product_detail_page(
request: Request,
product_id: int = Path(..., description="Marketplace Product ID"),
current_user: User = Depends(
require_menu_access("marketplace-letzshop", FrontendType.ADMIN)
),
db: Session = Depends(get_db),
):
"""
Render Letzshop product detail page.
Shows full product information from the marketplace.
"""
return templates.TemplateResponse(
"marketplace/admin/marketplace-product-detail.html",
get_admin_context(
request,
current_user,
product_id=product_id,
back_url="/admin/marketplace/letzshop",
),
)
# ============================================================================
# LETZSHOP VENDOR DIRECTORY
# ============================================================================
@router.get(
"/letzshop/vendor-directory",
response_class=HTMLResponse,
include_in_schema=False,
)
async def admin_letzshop_vendor_directory_page(
request: Request,
current_user: User = Depends(
require_menu_access("marketplace-letzshop", FrontendType.ADMIN)
),
db: Session = Depends(get_db),
):
"""
Render Letzshop vendor directory management page.
Allows admins to:
- View cached Letzshop vendors
- Trigger manual sync from Letzshop API
- Create platform vendors from cached Letzshop vendors
"""
return templates.TemplateResponse(
"marketplace/admin/letzshop-vendor-directory.html",
get_admin_context(request, current_user),
)
# ============================================================================
# MARKETPLACE PRODUCTS ROUTES
# ============================================================================
@router.get(
"/marketplace-products", response_class=HTMLResponse, include_in_schema=False
)
async def admin_marketplace_products_page(
request: Request,
current_user: User = Depends(
require_menu_access("marketplace-letzshop", FrontendType.ADMIN)
),
db: Session = Depends(get_db),
):
"""
Render marketplace products page.
Browse the master product repository imported from external sources.
"""
return templates.TemplateResponse(
"marketplace/admin/marketplace-products.html",
get_admin_context(request, current_user),
)
@router.get(
"/marketplace-products/{product_id}",
response_class=HTMLResponse,
include_in_schema=False,
)
async def admin_marketplace_product_detail_page(
request: Request,
product_id: int = Path(..., description="Marketplace Product ID"),
current_user: User = Depends(
require_menu_access("marketplace-letzshop", FrontendType.ADMIN)
),
db: Session = Depends(get_db),
):
"""
Render marketplace product detail page.
Shows full product information from the master repository.
"""
return templates.TemplateResponse(
"marketplace/admin/marketplace-product-detail.html",
get_admin_context(
request,
current_user,
product_id=product_id,
back_url="/admin/marketplace-products",
),
)

View File

@@ -0,0 +1,41 @@
# app/modules/marketplace/routes/pages/public.py
"""
Marketplace Public Page Routes (HTML rendering).
Public (unauthenticated) pages:
- Find shop (Letzshop vendor browser)
"""
from fastapi import APIRouter, Depends, Request
from fastapi.responses import HTMLResponse
from sqlalchemy.orm import Session
from app.core.database import get_db
from app.modules.core.utils.page_context import get_public_context
from app.templates_config import templates
router = APIRouter()
# ============================================================================
# FIND YOUR SHOP (LETZSHOP VENDOR BROWSER)
# ============================================================================
@router.get("/find-shop", response_class=HTMLResponse, name="platform_find_shop")
async def find_shop_page(
request: Request,
db: Session = Depends(get_db),
):
"""
Letzshop vendor browser page.
Allows vendors to search for and claim their Letzshop shop.
"""
context = get_public_context(request, db)
context["page_title"] = "Find Your Letzshop Shop"
return templates.TemplateResponse(
"marketplace/public/find-shop.html",
context,
)

View File

@@ -0,0 +1,146 @@
# app/modules/marketplace/routes/pages/vendor.py
"""
Marketplace Vendor Page Routes (HTML rendering).
Vendor pages for marketplace management:
- Onboarding wizard
- Dashboard
- Marketplace imports
- Letzshop integration
"""
from fastapi import APIRouter, Depends, Path, Request
from fastapi.responses import HTMLResponse, RedirectResponse
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.modules.marketplace.services.onboarding_service import OnboardingService
from app.templates_config import templates
from models.database.user import User
router = APIRouter()
# ============================================================================
# ONBOARDING WIZARD
# ============================================================================
@router.get(
"/{vendor_code}/onboarding", response_class=HTMLResponse, include_in_schema=False
)
async def vendor_onboarding_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 vendor onboarding wizard.
Mandatory 4-step wizard that must be completed before accessing dashboard:
1. Company Profile Setup
2. Letzshop API Configuration
3. Product & Order Import Configuration
4. Order Sync (historical import)
If onboarding is already completed, redirects to dashboard.
"""
onboarding_service = OnboardingService(db)
if onboarding_service.is_completed(current_user.token_vendor_id):
return RedirectResponse(
url=f"/vendor/{vendor_code}/dashboard",
status_code=302,
)
return templates.TemplateResponse(
"marketplace/vendor/onboarding.html",
get_vendor_context(request, db, current_user, vendor_code),
)
# ============================================================================
# VENDOR DASHBOARD
# ============================================================================
@router.get(
"/{vendor_code}/dashboard", response_class=HTMLResponse, include_in_schema=False
)
async def vendor_dashboard_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 vendor dashboard.
Redirects to onboarding if not completed.
JavaScript will:
- Load vendor info via API
- Load dashboard stats via API
- Load recent orders via API
- Handle all interactivity
"""
onboarding_service = OnboardingService(db)
if not onboarding_service.is_completed(current_user.token_vendor_id):
return RedirectResponse(
url=f"/vendor/{vendor_code}/onboarding",
status_code=302,
)
return templates.TemplateResponse(
"core/vendor/dashboard.html",
get_vendor_context(request, db, current_user, vendor_code),
)
# ============================================================================
# MARKETPLACE IMPORTS
# ============================================================================
@router.get(
"/{vendor_code}/marketplace", response_class=HTMLResponse, include_in_schema=False
)
async def vendor_marketplace_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 marketplace import page.
JavaScript loads import jobs and products via API.
"""
return templates.TemplateResponse(
"marketplace/vendor/marketplace.html",
get_vendor_context(request, db, current_user, vendor_code),
)
# ============================================================================
# LETZSHOP INTEGRATION
# ============================================================================
@router.get(
"/{vendor_code}/letzshop", response_class=HTMLResponse, include_in_schema=False
)
async def vendor_letzshop_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 Letzshop integration page.
JavaScript loads orders, credentials status, and handles fulfillment operations.
"""
return templates.TemplateResponse(
"marketplace/vendor/letzshop.html",
get_vendor_context(request, db, current_user, vendor_code),
)