You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
6.2 KiB
6.2 KiB
Phase 6: Products (Display & List)
Status: ✅ Done Progress: 10/10 tasks (100%) Started: 2025-11-04 Completed: 2025-11-04 Assigned to: -
Overview
Implement product display functionality: API endpoints for fetching products, product list/detail pages, and UI components for displaying Makerspace annual passes.
Goal: Users can browse and view Makerspace-Jahreskarten products.
Dependencies
- ✅ Phase 1: Foundation must be completed
- ✅ Phase 2: Database must be completed (products table needed)
- ⚠️ Optional: Phase 3: Authentication (for future protected features)
Tasks
API Endpoints
-
Create /api/products/index.get.ts endpoint
- Query products from DB (Drizzle)
- Filter by: active=true, category (optional)
- Sort by: name, price
- Return: Array of products
- Example:
export default defineEventHandler(async (event) => { const { category } = getQuery(event) const products = await db.query.products.findMany({ where: and( eq(products.active, true), category ? eq(products.category, category) : undefined ), orderBy: products.name, }) return products })
-
Create /api/products/[id].get.ts endpoint
- Validate ID (Zod: UUID)
- Query product by ID
- Return 404 if not found
- Return: Product object
- See: CLAUDE.md: API Route Example
UI Components
-
Create ProductCard component
- File:
components/Product/ProductCard.vue - Props: product (object)
- Display: Image, name, price, short description
- Button: "In den Warenkorb" (Add to Cart)
- Styling: shadcn-nuxt Card component + Tailwind
- Mobile-first design
- File:
-
Create ProductList component
- File:
components/Product/ProductList.vue - Props: products (array)
- Grid layout: 1 col (mobile), 2 cols (tablet), 3 cols (desktop)
- Uses: ProductCard for each product
- Empty state: "Keine Produkte verfügbar"
- File:
-
Create ProductDetail component
- File:
components/Product/ProductDetail.vue - Props: product (object)
- Display: Large image, full description, price, stock status
- Button: "In den Warenkorb"
- Breadcrumb: Home > Produkte > [Product Name]
- File:
Pages
-
Create products index page
- File:
pages/produkte/index.vue(German route) - Fetches products from API
- Uses: ProductList component
- Title: "Makerspace-Jahreskarten"
- SEO meta tags
- File:
-
Create ProductDetail page
- File:
pages/produkte/[id].vue - Fetches product by ID from API
- Uses: ProductDetail component
- 404 page if product not found
- SEO meta tags with product data
- File:
Asset Handling
- Add product images handling
- Create
/public/images/products/folder - Add placeholder image for products without image
- Document image requirements (size, format)
- Optimize images (use Nuxt Image module if needed)
- Create
Testing
-
Test product display
- Seed database with sample products (manual or seed script)
- Visit /produkte page
- Verify products display correctly
- Verify responsive design (mobile, tablet, desktop)
- Click product to view detail page
- Verify product detail displays correctly
-
Optimize product queries
- Add indexes to products table if needed (active, category)
- Test query performance with 100+ products
- Add pagination if needed (future enhancement)
-
Document product schema
- Document product data structure in code comments
- Document how images are stored/referenced
- Document category values (e.g., "makerspace-jahreskarte")
Acceptance Criteria
- /api/products endpoint returns all active products
- /api/products/[id] endpoint returns product by ID
- ProductCard component displays product correctly
- ProductList component shows products in grid layout
- ProductDetail component shows full product info
- /produkte page lists all products
- /produkte/[id] page shows product detail
- Images display correctly (or placeholder if missing)
- Responsive design works on mobile/tablet/desktop
- Product data structure is documented
Notes
Implementation Summary (Completed 2025-11-04)
Files Created (7):
server/api/products/index.get.ts- Product list API with role-based filteringserver/api/products/[id].get.ts- Product detail API with UUID validationapp/components/Product/ProductCard.vue- Product card component (109 lines)app/components/Product/ProductGrid.vue- Product grid layout (67 lines)app/pages/products/index.vue- Product list page (137 lines)app/pages/products/[id].vue- Product detail page with cart integration (236 lines)- Demo pages:
/internal/products-demo.vue,/internal/product-detail-demo.vue
Key Features Implemented:
- ✅ Role-based Visibility: Products filtered by user's approved roles (per CLAUDE.md)
- ✅ Cart Integration: Functional "Add to Cart" on detail page with toast notifications
- ✅ Responsive Design: Mobile-first with glassmorphism effects
- ✅ Advanced UI: Badges, discount percentages, hover effects (image zoom, scale)
- ✅ Database Optimization: Indexes on
active,category,nav_product_id - ✅ English URLs:
/productsinstead of/produkte(CLAUDE.md requirement)
Technical Highlights:
- Unauthenticated users see NO products (security by default)
- Category filtering via query parameter (comma-separated)
- Stock validation on add-to-cart
- Toast notifications using vue-sonner
- Cart sidebar auto-open on item add
- Proper error handling (404, 500) with user-friendly messages
Notes:
- MVP Scope: Only Makerspace-Jahreskarten products for now
- Images: Using placeholder
/img/makerspace-jk-2025.jpg(DB supports unique images viaimageUrlfield) - Pagination: Not needed for MVP (< 10 products expected)
- Filters: Category filter implemented in API, can be extended in UI if needed
Blockers
- None currently (can use mock products if NAV ERP sync not ready)