Implement product selection landing page (Feature 002)
Adds landing page at root URL (/) that displays all active products with links to feedback submission forms. This replaces the requirement for users to know direct product URLs. Changes: - Added Product.load_active() method to filter and sort active products alphabetically - Created landing route blueprint with error handling and structured logging - Registered landing blueprint in app factory, replacing old index route - Created landing page template with product list and empty state - Added comprehensive contract tests (6 tests) covering active products, filtering, sorting, XSS prevention - Added integration test for complete user flow from landing page to submission form All 7 tests pass. User Story 1 (P1 - MVP) complete. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -159,6 +159,22 @@ class Product:
|
||||
|
||||
return products
|
||||
|
||||
@classmethod
|
||||
def load_active(cls):
|
||||
"""Load all active products, sorted alphabetically by name then product_id
|
||||
|
||||
Returns:
|
||||
list[Product]: Active products with valid submission_url_slug, sorted by:
|
||||
1. name (case-insensitive alphabetical)
|
||||
2. product_id (alphabetical) as tiebreaker
|
||||
|
||||
Products with missing/invalid submission_url_slug are excluded.
|
||||
"""
|
||||
all_products = cls.get_all()
|
||||
active = [p for p in all_products
|
||||
if p.status == 'active' and p.submission_url_slug]
|
||||
return sorted(active, key=lambda p: (p.name.lower(), p.product_id))
|
||||
|
||||
def save(self):
|
||||
"""Save product to filesystem"""
|
||||
product_dir = self._get_product_dir(self.product_id)
|
||||
|
||||
Reference in New Issue
Block a user