# Pull Request: Database-Backed Ingredient-Instruction Mapping ## Summary This PR implements a comprehensive solution for managing ingredient-to-instruction mappings in cooking mode. The feature moves from client-side state management to a persistent database-backed approach, significantly improving reliability and user experience. ## Changes ### Database Schema - **New Table**: `IngredientInstructionMapping` - Many-to-many relationship between ingredients and instructions - Includes `order` field for display ordering within instructions - Cascade delete for data integrity - Migration: `20251031050746_add_ingredient_instruction_mapping` ### Backend (API) #### New Service - **`packages/api/src/services/ingredientMatcher.service.ts`** - Automatic ingredient matching algorithm - Extracts core ingredient names (removes quantities/units) - Generates name variations (plural/singular) - Finds ingredient positions in instruction text - Prevents duplicate mappings (same ingredient appearing multiple times) - Cross-step tracking (ingredients only appear once across all steps) #### API Endpoints - **Updated GET `/api/recipes/:id`**: Now includes ingredient-instruction mappings in response - **Updated POST `/api/recipes`**: Automatically generates mappings on recipe creation - **Updated PUT `/api/recipes/:id`**: Regenerates mappings on recipe update - **New POST `/api/recipes/:id/ingredient-mappings`**: Manually update mappings - **New POST `/api/recipes/:id/regenerate-mappings`**: Re-run automatic matching ### Frontend (Web) #### Simplified Cooking Mode - **`packages/web/src/pages/CookingMode.tsx`** - Significantly simplified - Removed all client-side matching logic (~200 lines removed) - Removed localStorage state management - Removed drag-and-drop functionality - Now purely read-only, displays database-stored mappings - Added "⚙️ Manage Ingredients" button for editing #### New Management Interface - **`packages/web/src/pages/ManageIngredientMappings.tsx`** - New dedicated page - Similar layout to cooking mode for familiarity - Drag-and-drop ingredients to instruction steps - Remove ingredients with ✕ button - Real-time preview of changes - Save to database with "💾 Save Changes" button - Auto-regenerate with "🔄 Regenerate Auto Mappings" button - Navigate to cooking mode with "👨‍🍳 Preview in Cooking Mode" button - Unsaved changes warning banner - **`packages/web/src/styles/ManageIngredientMappings.css`** - Dedicated styling #### Updated Components - **`packages/web/src/App.tsx`**: Added route for `/recipes/:id/manage-mappings` - **`packages/web/src/services/api.ts`**: Added API methods for mapping management - **`packages/web/src/styles/CookingMode.css`**: Removed unused drag-and-drop styles ### Shared Types - **`packages/shared/src/types.ts`** - Added `IngredientInstructionMapping` interface - Updated `Ingredient` and `Instruction` to include optional mapping arrays ### Scripts - **`packages/api/src/scripts/regenerate-mappings.ts`** - Utility script to regenerate mappings for all existing recipes ## Testing ### Test Results - ✅ **API Tests**: 24/25 passing (96%) - ✅ **New Ingredient Matcher Service**: 11/11 tests passing - ✅ **Recipe Routes**: 9/9 tests passing (includes mapping integration) - ✅ **Storage Service**: 4/5 passing (1 pre-existing S3 test failure) - ✅ **Shared Tests**: 16/16 passing (100%) - ⚠️ **Web Tests**: 7/15 passing (8 pre-existing failures in axios mocking setup) ### New Test Coverage Created comprehensive unit tests for `ingredientMatcher.service.ts`: - ✅ Simple ingredient matching - ✅ Ingredients with quantities in names - ✅ Plural/singular form matching - ✅ No duplication across steps - ✅ No duplication of same core ingredient - ✅ Recipes with sections - ✅ Ingredient ordering by text position - ✅ Error handling for missing recipes - ✅ Save mappings functionality - ✅ Auto-map integration ### Manual Testing Performed - ✅ Created new test recipe with automatic mapping generation - ✅ Regenerated mappings for 5 existing recipes (Soft Sourdough, Apple Dutch Baby, Ice Cream, etc.) - ✅ Verified mappings persist across page refreshes - ✅ Tested drag-and-drop in management interface - ✅ Tested remove functionality - ✅ Tested save persistence to database - ✅ Verified cooking mode displays stored mappings correctly ## Migration Guide ### For Existing Recipes Run the regeneration script to generate mappings for all existing recipes: ```bash cd packages/api npx tsx src/scripts/regenerate-mappings.ts ``` This was already executed and successfully generated mappings for all 5 existing recipes. ### Database Migration The migration runs automatically when deploying the API container. No manual intervention needed. ## Benefits 1. **Reliability**: Mappings are persisted in database, not client-side localStorage 2. **Consistency**: Same mappings across all clients/devices 3. **Simplicity**: Cooking mode is now read-only with no complex state management 4. **User Control**: Dedicated management interface for editing mappings 5. **Automatic**: Mappings are generated automatically on recipe import/creation 6. **Flexible**: Users can manually adjust mappings if automatic matching is incorrect ## Breaking Changes None. This is a new feature with backward compatibility. Existing recipes work without mappings, and the system automatically generates them. ## Future Enhancements - [ ] Add UI to manage mappings during recipe import (for recipes with ambiguous matches) - [ ] Add reordering of ingredients within instructions (drag-and-drop reorder) - [ ] Add bulk mapping tools (e.g., "map all ingredients to step 1") - [ ] Add mapping analytics/suggestions based on common patterns ## Screenshots ### Cooking Mode (Read-Only) - Clean, distraction-free interface - Ingredients listed inline with each step - No edit controls visible ### Manage Ingredient Mappings - Drag ingredients from top section to instruction steps - Remove with ✕ button - Save changes button persists to database - Regenerate button re-runs automatic matching ## Related Issues Fixes issues with ingredient mapping: - Ingredients duplicating when dragging - Remove button not working - Changes not persisting across clients - Complex client-side state management ## Review Checklist - [x] Database migration created and tested - [x] API tests updated and passing - [x] Frontend tests updated (some pre-existing failures remain) - [x] Manual testing completed - [x] Documentation updated - [x] No breaking changes - [x] Backward compatible