diff --git a/backend/main.py b/backend/main.py index 0f96223..98cff08 100644 --- a/backend/main.py +++ b/backend/main.py @@ -94,6 +94,30 @@ def read_shop(shop_id: int, db: Session = Depends(get_db)): raise HTTPException(status_code=404, detail="Shop not found") return shop +@app.put("/shops/{shop_id}", response_model=schemas.Shop) +def update_shop(shop_id: int, shop_update: schemas.ShopUpdate, db: Session = Depends(get_db)): + shop = db.query(models.Shop).filter(models.Shop.id == shop_id).first() + if shop is None: + raise HTTPException(status_code=404, detail="Shop not found") + + update_data = shop_update.dict() + for field, value in update_data.items(): + setattr(shop, field, value) + + db.commit() + db.refresh(shop) + return shop + +@app.delete("/shops/{shop_id}") +def delete_shop(shop_id: int, db: Session = Depends(get_db)): + shop = db.query(models.Shop).filter(models.Shop.id == shop_id).first() + if shop is None: + raise HTTPException(status_code=404, detail="Shop not found") + + db.delete(shop) + db.commit() + return {"message": "Shop deleted successfully"} + # Shopping Event endpoints @app.post("/shopping-events/", response_model=schemas.ShoppingEventResponse) def create_shopping_event(event: schemas.ShoppingEventCreate, db: Session = Depends(get_db)): diff --git a/frontend/src/components/AddShopModal.tsx b/frontend/src/components/AddShopModal.tsx new file mode 100644 index 0000000..0ed1571 --- /dev/null +++ b/frontend/src/components/AddShopModal.tsx @@ -0,0 +1,193 @@ +import React, { useState, useEffect } from 'react'; +import { shopApi } from '../services/api'; +import { Shop } from '../types'; + +interface AddShopModalProps { + isOpen: boolean; + onClose: () => void; + onShopAdded: () => void; + editShop?: Shop | null; +} + +interface ShopFormData { + name: string; + city: string; + address?: string; +} + +const AddShopModal: React.FC = ({ isOpen, onClose, onShopAdded, editShop }) => { + const [formData, setFormData] = useState({ + name: '', + city: '', + address: '' + }); + const [loading, setLoading] = useState(false); + const [error, setError] = useState(''); + + const isEditMode = !!editShop; + + // Initialize form data when editing + useEffect(() => { + if (editShop) { + setFormData({ + name: editShop.name, + city: editShop.city, + address: editShop.address || '' + }); + } else { + setFormData({ + name: '', + city: '', + address: '' + }); + } + setError(''); + }, [editShop, isOpen]); + + const handleSubmit = async (e: React.FormEvent) => { + e.preventDefault(); + if (!formData.name.trim() || !formData.city.trim()) { + setError('Please fill in all required fields'); + return; + } + + try { + setLoading(true); + setError(''); + + const trimmedAddress = formData.address?.trim(); + const shopData = { + name: formData.name.trim(), + city: formData.city.trim(), + address: trimmedAddress && trimmedAddress.length > 0 ? trimmedAddress : null + }; + + if (isEditMode && editShop) { + await shopApi.update(editShop.id, shopData); + } else { + await shopApi.create(shopData); + } + + // Reset form + setFormData({ + name: '', + city: '', + address: '' + }); + + onShopAdded(); + onClose(); + } catch (err) { + setError(`Failed to ${isEditMode ? 'update' : 'add'} shop. Please try again.`); + console.error(`Error ${isEditMode ? 'updating' : 'adding'} shop:`, err); + } finally { + setLoading(false); + } + }; + + const handleChange = (e: React.ChangeEvent) => { + const { name, value } = e.target; + setFormData(prev => ({ + ...prev, + [name]: value + })); + }; + + if (!isOpen) return null; + + return ( +
+
+
+
+

+ {isEditMode ? 'Edit Shop' : 'Add New Shop'} +

+ +
+ + {error && ( +
+ {error} +
+ )} + +
+
+ + +
+ +
+ + +
+ +
+ +