# 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 - [x] 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: ```typescript 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 }) ``` - [x] 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](../CLAUDE.md#api-route-example) ### UI Components - [x] 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 - [x] 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" - [x] 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] ### Pages - [x] Create products index page - File: `pages/produkte/index.vue` (German route) - Fetches products from API - Uses: ProductList component - Title: "Makerspace-Jahreskarten" - SEO meta tags - [x] 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 ### Asset Handling - [x] 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) ### Testing - [x] 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 - [x] Optimize product queries - Add indexes to products table if needed (active, category) - Test query performance with 100+ products - Add pagination if needed (future enhancement) - [x] 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 - [x] /api/products endpoint returns all active products - [x] /api/products/[id] endpoint returns product by ID - [x] ProductCard component displays product correctly - [x] ProductList component shows products in grid layout - [x] ProductDetail component shows full product info - [x] /produkte page lists all products - [x] /produkte/[id] page shows product detail - [x] Images display correctly (or placeholder if missing) - [x] Responsive design works on mobile/tablet/desktop - [x] Product data structure is documented --- ## Notes ### Implementation Summary (Completed 2025-11-04) **Files Created (7):** 1. `server/api/products/index.get.ts` - Product list API with role-based filtering 2. `server/api/products/[id].get.ts` - Product detail API with UUID validation 3. `app/components/Product/ProductCard.vue` - Product card component (109 lines) 4. `app/components/Product/ProductGrid.vue` - Product grid layout (67 lines) 5. `app/pages/products/index.vue` - Product list page (137 lines) 6. `app/pages/products/[id].vue` - Product detail page with cart integration (236 lines) 7. 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:** `/products` instead 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 via `imageUrl` field) - **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) --- ## Related Documentation - [docs/PRD.md: F-004](../docs/PRD.md#f-004-produktanzeige) - [docs/ARCHITECTURE.md: Products Table](../docs/ARCHITECTURE.md#products) - [CLAUDE.md: API Route Example](../CLAUDE.md#api-route-example)