feat: Implement quick import feature for recipes
- Added QuickImportController and QuickImportService to handle recipe imports from URLs and file paths. - Created QuickImportModule to encapsulate the quick import functionality. - Developed frontend ImportFilePage for users to upload files or enter URLs for recipe import. - Integrated API proxy to communicate with the backend for quick import requests. - Implemented WriteRecipePage for users to manually input recipes with Markdown support. - Added page routing for the new import and write recipe functionalities.
This commit is contained in:
+83
-47
@@ -52,10 +52,11 @@ Recipe App är en fullstack-applikation för hantering av hemmavaror, recept och
|
||||
| | `actions.ts` | Server actions för inventarie |
|
||||
| **Recept** | `app/recipes/page.tsx` | Lista recept |
|
||||
| | `RecipePreview.tsx` | Receptförhandsvisning med inventariestatus |
|
||||
| **Skapa recept** | `app/recipes/create/page.tsx` | Receptkreation (manual form) |
|
||||
| | `app/recipes/create/CreateRecipePage.tsx` | Komponenter för receptskapande |
|
||||
| **Importera recept** | `app/recipes/import/page.tsx` | Startpunkt för Markdown-import |
|
||||
| | `app/recipes/import/ImportRecipePage.tsx` | 3-stegsvyn för Markdown-import |
|
||||
| **Lägg till recept** | `app/recipes/create/page.tsx` | Meny för receptskaping (val mellan två vägar) |
|
||||
| **Skriv in recept** | `app/recipes/write/page.tsx` | Startpunkt för Markdown-inmatning |
|
||||
| | `app/recipes/write/WriteRecipePage.tsx` | Komponenter för receptskapande (Markdown-baserat, 3-steg) |
|
||||
| **Importera från fil** | `app/recipes/import/page.tsx` | Startpunkt för fil/länk-import |
|
||||
| | `app/recipes/import/ImportFilePage.tsx` | Komponenter för fil-/länk-import (PDF, URL, etc) |
|
||||
| **Recipe detail** | `app/recipes/[id]/` | Enskilt recept (detaljer, redigering) |
|
||||
| **Admin: Produkter** | `app/admin/products/page.tsx` | Produktadmin-panel |
|
||||
| | `AdminProductList.tsx` | Lista produkter, sök, sortera |
|
||||
@@ -67,7 +68,7 @@ Recipe App är en fullstack-applikation för hantering av hemmavaror, recept och
|
||||
|
||||
| Route | Metod | Syfte |
|
||||
|-------|-------|-------|
|
||||
| `/api/parse-markdown-proxy` | POST | Proxies `POST /api/recipes/parse-markdown` (Markdown-tolkning) |
|
||||
| `/api/parse-markdown-proxy` | POST | Proxies `POST /api/recipes/parse-markdown` (Markdown-tolkning för skriv-in-recept) |
|
||||
| `/api/inventory-history-proxy` | GET | Proxies konsumtionshistorik |
|
||||
| `/api/recipe-preview-proxy` | GET | Proxies receptförhandsvisning |
|
||||
| `/api/admin/merge-preview-proxy` | GET | Proxies produktmerge-preview |
|
||||
@@ -126,6 +127,10 @@ backend/src/
|
||||
│ ├── update-product.dto.ts
|
||||
│ ├── merge-products.dto.ts
|
||||
│ └── update-canonical-name.dto.ts
|
||||
├── quick-import/ # NYT: Snabbimport-modul
|
||||
│ ├── quick-import.controller.ts # POST /api/quick-import
|
||||
│ ├── quick-import.service.ts # ICA-skrapning, PDF-stöd
|
||||
│ └── quick-import.module.ts # Module definition
|
||||
└── recipes/
|
||||
├── recipes.controller.ts # Recept endpoints
|
||||
├── recipes.service.ts # Recept + Markdown-parsing
|
||||
@@ -205,6 +210,8 @@ GET /api/inventory/:id/consumption-history Konsumtionshistorik
|
||||
|
||||
### 🍽️ Recept-endpoints
|
||||
```
|
||||
POST /api/quick-import SNITT: Snabbimport (ICA-skrapning)
|
||||
Body: { input: string (URL eller filsökväg) }
|
||||
POST /api/recipes/parse-markdown Tolka Markdown-recept (matchningslogik)
|
||||
GET /api/recipes Lista alla recept
|
||||
POST /api/recipes Skapa nytt recept
|
||||
@@ -329,15 +336,61 @@ model RecipeIngredient {
|
||||
|
||||
---
|
||||
|
||||
## Receptimport via Markdown — Detaljerad arkitektur
|
||||
## Receptimport och receptskaping — Detaljerad arkitektur
|
||||
|
||||
### Syfte
|
||||
### Syfte och struktur
|
||||
|
||||
Användaren kan importera ett recept skrivet i Markdown-format istället för att fylla i formularet manuellt. Systemet:
|
||||
1. Tolkar Markdown-format (namn, beskrivning, ingredienser, instruktioner)
|
||||
2. Matchar varje ingrediens mot produktdatabasen (intelligenta matchningar)
|
||||
3. Låter användaren granska förslag och välja rätt produkt
|
||||
4. Sparar receptet med valida ingredienser
|
||||
Recipe App erbjuder tre vägar för att lägga till recept:
|
||||
|
||||
1. **Snabbimport** — Klistra in ICA-länk för automatisk skrapning (ny feature)
|
||||
2. **Skriv in recept** (`/recipes/write`) — Markdown-baserad inmatning där användaren skriver receptet i enkelt format
|
||||
3. **Importera från fil** (`/recipes/import`) — Ladda upp PDF, länk eller andra receptkällor (under utveckling)
|
||||
|
||||
Alla vägar möjliggör automatisk matchning av ingredienser mot databasen.
|
||||
|
||||
### Strukturöversikt
|
||||
|
||||
#### Snabbimport-fältet
|
||||
|
||||
**Frontend: `/recipes/create/page.tsx`**
|
||||
- Ovanför de två huvudvalen visas ett gult inmatningsfält för snabbimport
|
||||
- Användaren klistrar in en ICA-receptlänk eller filsökväg
|
||||
- Vid submit:
|
||||
1. Frontend skickar till `/api/quick-import-proxy`
|
||||
2. Proxy proxiar till backend `POST /api/quick-import`
|
||||
3. Backend returnerar Markdown-text
|
||||
4. Frontend sparar i `sessionStorage('recipeMarkdown')`
|
||||
5. Omdirigera till `/recipes/write` med förifylld Markdown
|
||||
|
||||
**Backend: `QuickImportService` (ny modul)**
|
||||
- Ansvarig för ICA-skrapning, PDF-tolkning, URL-validering
|
||||
- **Huvudmetod:** `importFromInput(input: string)` — Detekterar input-typ och delegerar
|
||||
- **ICA-specifik:**
|
||||
- Validerar URL (måste vara ICA.se)
|
||||
- Fetchar HTML via `fetch()`
|
||||
- Parsar HTML med regex för: receptnamn, ingredienser, instruktioner
|
||||
- Konverterar till Markdown-format
|
||||
- **Felhantering:** Specifika felmeddelanden per scenario
|
||||
- **PDF-support:** Stubben för framtida integration (throwError: "PDF-import är under utveckling")
|
||||
- **Error-strategi:**
|
||||
- `400 Bad Request` — Tomt input, inte URL/fil
|
||||
- `400 Bad Request` — Länken är inte från ICA.se
|
||||
- `503 Service Unavailable` — Network-fel vid hämtning (HTTP-fel från ICA)
|
||||
- `400 Bad Request` — HTML-parsing misslyckades (receptnamn/ingredienser inte hittade)
|
||||
|
||||
**API-endpoint:**
|
||||
```
|
||||
POST /api/quick-import
|
||||
Input: { input: string }
|
||||
Output: { markdown: string, source: 'ica' | 'pdf' | 'other' }
|
||||
```
|
||||
|
||||
**Proxy-route (Next.js):**
|
||||
- `/api/quick-import-proxy` — Proxies till backend
|
||||
- Hanterar error-konvertering (BE HTTP → FE error message)
|
||||
- Returnerar Markdown eller JSON-error
|
||||
|
||||
### Markdown-format och parsningsregler
|
||||
|
||||
### Markdown-format och parsningsregler
|
||||
|
||||
@@ -486,44 +539,27 @@ Top 5: Max 5 förslag per ingrediens
|
||||
}
|
||||
```
|
||||
|
||||
#### 3. Frontend: `/recipes/import` page
|
||||
#### 3. Frontend: Receptskapsidor
|
||||
|
||||
**Komponenter:**
|
||||
- `ImportRecipePage.tsx` — Main client component (3-steps state machine)
|
||||
- Använder `/api/parse-markdown-proxy` för backend-anrop (Next.js proxy)
|
||||
**Huvudmeny: `/recipes/create/page.tsx`**
|
||||
- Presenterar två val-kort (card-baserad UI)
|
||||
- "Skriv in recept" → `/recipes/write`
|
||||
- "Importera från fil/länk" → `/recipes/import`
|
||||
|
||||
**Steg 1: Klistra in Markdown**
|
||||
- `<textarea>` för råtext
|
||||
- Knapp: "Tolka recept" → POST /api/parse-markdown-proxy
|
||||
- Error handling med svenska meddelanden
|
||||
**Skriv in recept: `/recipes/write/WriteRecipePage.tsx`**
|
||||
- Main client component (3-steps state machine)
|
||||
- Samma logik som tidigare `ImportRecipePage`
|
||||
- **Steg 1:** Markdown-inmatning
|
||||
- **Steg 2:** Granska ingredienser, välj produkter
|
||||
- **Steg 3:** Spara recept
|
||||
- Använder `/api/parse-markdown-proxy` för backend-anrop
|
||||
|
||||
**Steg 2: Granska och välj**
|
||||
- Redigerbara fält: namn, beskrivning, instruktioner
|
||||
- För varje ingrediens:
|
||||
- Visar föreslagna produkter (top 5, prioriterad ordning)
|
||||
- Fallback: Dropdown med alla produkter i DB
|
||||
- Redigerbara fält: quantity, unit, note
|
||||
- Visuell markering (gul ram) för ingredienser utan vald produkt
|
||||
- Knapp: "Ta bort ingrediens"
|
||||
- Validering: Minst 1 ingrediens måste ha vald produkt
|
||||
|
||||
**Steg 3: Spara**
|
||||
- POST /api/recipes med:
|
||||
```json
|
||||
{
|
||||
"name": "...",
|
||||
"description": "... " eller undefined,
|
||||
"instructions": "..." eller undefined,
|
||||
"ingredients": [
|
||||
{ "productId": 12, "quantity": 500, "unit": "g", "note": "vispgrädde" },
|
||||
{ "productId": 34, "quantity": 1, "unit": "st", "note": undefined }
|
||||
]
|
||||
}
|
||||
```
|
||||
- Efter framgång: navigera till receptlistan
|
||||
|
||||
**Enhetsstöd i UI:**
|
||||
- Dropdown-alternativ: g, kg, hg, ml, dl, l, st, tsk, msk
|
||||
**Importera från fil: `/recipes/import/ImportFilePage.tsx`**
|
||||
- Tabs/toggle mellan två metoder:
|
||||
1. **Fil-upload** — Dra-och-släpp eller välja PDF/TXT/DOCX
|
||||
2. **URL-import** — Ange länk till receptsida
|
||||
- Placeholder för framtida integration
|
||||
- Visar tips för att använda "Skriv in recept" tills dessa funktioner är klara
|
||||
|
||||
#### 4. API-proxy-route (Next.js)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user