Spaces:
Sleeping
Sleeping
| import { useState, useEffect } from 'react'; | |
| import { Plus, Loader2, AlertCircle } from 'lucide-react'; | |
| import api from '../api/api'; | |
| import PackageCard from './PackageCard'; | |
| import CreatePackageModal from './CreatePackageModal'; | |
| const PackagePanel = ({ photographerId }) => { | |
| const [packages, setPackages] = useState([]); | |
| const [loading, setLoading] = useState(true); | |
| const [isModalOpen, setIsModalOpen] = useState(false); | |
| const [editingPackage, setEditingPackage] = useState(null); | |
| useEffect(() => { | |
| fetchPackages(); | |
| }, []); | |
| const fetchPackages = async () => { | |
| try { | |
| const res = await api.get(`/packages/photographer/${photographerId}`); | |
| setPackages(res.data); | |
| } catch (err) { | |
| console.error('Failed to load packages:', err); | |
| } finally { | |
| setLoading(false); | |
| } | |
| }; | |
| const handleSavePackage = async (formData) => { | |
| try { | |
| if (editingPackage) { | |
| const res = await api.put(`/packages/${editingPackage._id}`, formData); | |
| setPackages(packages.map(p => (p._id === res.data._id ? res.data : p))); | |
| } else { | |
| const res = await api.post('/packages', formData); | |
| setPackages([...packages, res.data]); | |
| } | |
| setIsModalOpen(false); | |
| setEditingPackage(null); | |
| } catch (err) { | |
| alert(err.response?.data?.message || 'Failed to save package'); | |
| } | |
| }; | |
| const handleDeletePackage = async (packageId) => { | |
| if (!window.confirm('Are you sure you want to delete this package?')) return; | |
| try { | |
| await api.delete(`/packages/${packageId}`); | |
| setPackages(packages.filter(p => p._id !== packageId)); | |
| } catch (err) { | |
| alert('Failed to delete package'); | |
| } | |
| }; | |
| const handleEdit = (pkg) => { | |
| setEditingPackage(pkg); | |
| setIsModalOpen(true); | |
| }; | |
| if (loading) { | |
| return ( | |
| <div className="flex items-center justify-center py-12"> | |
| <Loader2 className="animate-spin text-blue-600" size={32} /> | |
| </div> | |
| ); | |
| } | |
| return ( | |
| <div> | |
| <div className="flex justify-between items-center mb-6"> | |
| <h2 className="text-2xl font-bold">📦 My Packages</h2> | |
| <button | |
| onClick={() => { | |
| setEditingPackage(null); | |
| setIsModalOpen(true); | |
| }} | |
| className="flex items-center gap-2 bg-blue-600 text-white px-4 py-2 rounded-lg hover:bg-blue-700 font-medium" | |
| > | |
| <Plus size={20} /> Create New | |
| </button> | |
| </div> | |
| {packages.length === 0 ? ( | |
| <div className="bg-amber-50 border border-amber-200 rounded-lg p-6 text-center"> | |
| <AlertCircle className="mx-auto mb-3 text-amber-600" size={32} /> | |
| <p className="text-amber-900 font-semibold mb-3">No packages yet</p> | |
| <p className="text-amber-700 text-sm mb-4"> | |
| Create your first package to let customers book you! | |
| </p> | |
| <button | |
| onClick={() => setIsModalOpen(true)} | |
| className="bg-amber-600 text-white px-4 py-2 rounded-lg hover:bg-amber-700 font-medium" | |
| > | |
| Create First Package | |
| </button> | |
| </div> | |
| ) : ( | |
| <div className="grid grid-cols-1 md:grid-cols-2 gap-6"> | |
| {packages.map(pkg => ( | |
| <PackageCard | |
| key={pkg._id} | |
| pkg={pkg} | |
| bookingCount={pkg.bookingCount} | |
| onEdit={handleEdit} | |
| onDelete={handleDeletePackage} | |
| /> | |
| ))} | |
| </div> | |
| )} | |
| <CreatePackageModal | |
| isOpen={isModalOpen} | |
| onClose={() => { | |
| setIsModalOpen(false); | |
| setEditingPackage(null); | |
| }} | |
| onSave={handleSavePackage} | |
| editingPackage={editingPackage} | |
| /> | |
| </div> | |
| ); | |
| }; | |
| export default PackagePanel; | |