diff --git a/frontend/src/pages/ShoppingPage.tsx b/frontend/src/pages/ShoppingPage.tsx
index a4071e3..cbd2542 100644
--- a/frontend/src/pages/ShoppingPage.tsx
+++ b/frontend/src/pages/ShoppingPage.tsx
@@ -4,7 +4,7 @@ import type { ShoppingListDetail, ShoppingList, Store, Product } from '../api/sh
import {
fetchLists, createList, fetchListDetail, deleteList,
addItem, updateItem, deleteItem, finishShopping, fetchStores, generateMagicList,
- searchProducts,
+ searchProducts, createProduct,
} from '../api/shopping'
import Modal from '../components/Modal'
import ItemRow from '../components/shopping/ItemRow'
@@ -44,6 +44,7 @@ export default function ShoppingPage() {
const [selectedProduct, setSelectedProduct] = useState(null)
const [newItemQty, setNewItemQty] = useState('')
const [newItemUnit, setNewItemUnit] = useState('')
+ const [addToCatalogue, setAddToCatalogue] = useState(true)
useWakeLock(currentList !== null)
@@ -109,6 +110,7 @@ export default function ShoppingPage() {
setSelectedProduct(null)
setNewItemQty('')
setNewItemUnit('')
+ setAddToCatalogue(true)
setShowAddItemModal(false)
}
@@ -120,13 +122,25 @@ export default function ShoppingPage() {
async function handleAddItem() {
if (!currentList) return
- const hasProduct = selectedProduct !== null
- const customName = hasProduct ? undefined : itemSearch.trim()
- if (!hasProduct && !customName) return
+ const customName = itemSearch.trim()
+ if (!selectedProduct && !customName) return
try {
+ let productId = selectedProduct?.id
+
+ // Article libre + case "Ajouter au catalogue" cochée → créer le produit d'abord
+ if (!selectedProduct && customName && addToCatalogue) {
+ const newProduct = await createProduct({
+ name: customName,
+ default_unit: newItemUnit || undefined,
+ })
+ productId = newProduct.id
+ // Met à jour la liste locale des produits pour les prochains ajouts
+ setProducts(prev => [...prev, newProduct].sort((a, b) => a.name.localeCompare(b.name, 'fr')))
+ }
+
await addItem(currentList.id, {
- product_id: selectedProduct?.id,
- custom_name: customName,
+ product_id: productId,
+ custom_name: !productId ? customName : undefined,
quantity: newItemQty || undefined,
unit: newItemUnit || undefined,
})
@@ -425,7 +439,7 @@ export default function ShoppingPage() {
color: 'var(--ink-4)', fontFamily: 'var(--font-ui)', fontSize: 13,
textAlign: 'center', padding: '12px 16px', margin: 0, ...noSelect,
}}>
- {itemSearch.trim() ? `"${itemSearch}" — sera ajouté comme article libre` : 'Catalogue vide'}
+ {itemSearch.trim() ? `"${itemSearch}" — article libre` : 'Catalogue vide'}
)}
{filteredProducts.map((p, idx) => {
@@ -460,6 +474,21 @@ export default function ShoppingPage() {
})}
+ {/* Case "Ajouter au catalogue" — uniquement si article libre sans correspondance */}
+ {!selectedProduct && itemSearch.trim() && filteredProducts.length === 0 && (
+
+ )}
+
{/* Quantité + Unité */}