Spaces:
Sleeping
Sleeping
| import { useState } from 'react'; | |
| import { X } from 'lucide-react'; | |
| const CreatePackageModal = ({ isOpen, onClose, onSave, editingPackage }) => { | |
| const [formData, setFormData] = useState( | |
| editingPackage || { | |
| name: '', | |
| description: '', | |
| price: 0, | |
| priceUnit: 'session', | |
| duration: 2, | |
| deliverables: { | |
| numPhotos: 100, | |
| numEdited: 10, | |
| numLocations: 1, | |
| includesAlbum: false, | |
| }, | |
| } | |
| ); | |
| const handleChange = (e) => { | |
| const { name, value, type, checked } = e.target; | |
| if (name.includes('deliverables.')) { | |
| const key = name.split('.')[1]; | |
| setFormData({ | |
| ...formData, | |
| deliverables: { | |
| ...formData.deliverables, | |
| [key]: type === 'checkbox' ? checked : parseInt(value) || value, | |
| }, | |
| }); | |
| } else { | |
| setFormData({ | |
| ...formData, | |
| [name]: type === 'number' ? parseFloat(value) || 0 : value, | |
| }); | |
| } | |
| }; | |
| const handleSubmit = (e) => { | |
| e.preventDefault(); | |
| onSave(formData); | |
| }; | |
| if (!isOpen) return null; | |
| return ( | |
| <div className="fixed inset-0 bg-black/50 flex items-center justify-center z-50 p-4"> | |
| <div className="bg-white rounded-lg max-w-md w-full max-h-[90vh] overflow-y-auto"> | |
| <div className="flex items-center justify-between p-6 border-b"> | |
| <h2 className="text-xl font-bold"> | |
| {editingPackage ? 'Edit Package' : 'Create New Package'} | |
| </h2> | |
| <button onClick={onClose} className="text-gray-500 hover:text-gray-700"> | |
| <X size={20} /> | |
| </button> | |
| </div> | |
| <form onSubmit={handleSubmit} className="p-6 space-y-4"> | |
| <div> | |
| <label className="block text-sm font-semibold text-gray-700 mb-1"> | |
| Package Name * | |
| </label> | |
| <input | |
| type="text" | |
| name="name" | |
| value={formData.name} | |
| onChange={handleChange} | |
| placeholder="e.g., Basic, Premium" | |
| required | |
| className="w-full border border-gray-300 rounded-lg px-3 py-2 focus:ring-2 focus:ring-blue-500 focus:border-transparent" | |
| /> | |
| </div> | |
| <div> | |
| <label className="block text-sm font-semibold text-gray-700 mb-1"> | |
| Description | |
| </label> | |
| <textarea | |
| name="description" | |
| value={formData.description} | |
| onChange={handleChange} | |
| placeholder="Describe what's included" | |
| rows="2" | |
| className="w-full border border-gray-300 rounded-lg px-3 py-2 focus:ring-2 focus:ring-blue-500 focus:border-transparent" | |
| /> | |
| </div> | |
| <div className="grid grid-cols-2 gap-4"> | |
| <div> | |
| <label className="block text-sm font-semibold text-gray-700 mb-1"> | |
| Price (₹) * | |
| </label> | |
| <input | |
| type="number" | |
| name="price" | |
| value={formData.price} | |
| onChange={handleChange} | |
| required | |
| className="w-full border border-gray-300 rounded-lg px-3 py-2" | |
| /> | |
| </div> | |
| <div> | |
| <label className="block text-sm font-semibold text-gray-700 mb-1"> | |
| Unit | |
| </label> | |
| <select | |
| name="priceUnit" | |
| value={formData.priceUnit} | |
| onChange={handleChange} | |
| className="w-full border border-gray-300 rounded-lg px-3 py-2" | |
| > | |
| <option value="hourly">Per Hour</option> | |
| <option value="session">Per Session</option> | |
| <option value="daily">Per Day</option> | |
| </select> | |
| </div> | |
| </div> | |
| <div> | |
| <label className="block text-sm font-semibold text-gray-700 mb-1"> | |
| Duration (hours) | |
| </label> | |
| <input | |
| type="number" | |
| name="duration" | |
| value={formData.duration} | |
| onChange={handleChange} | |
| className="w-full border border-gray-300 rounded-lg px-3 py-2" | |
| /> | |
| </div> | |
| <div className="border-t pt-4"> | |
| <h3 className="font-semibold text-gray-700 mb-3">Deliverables</h3> | |
| <div className="space-y-3"> | |
| <div> | |
| <label className="block text-sm text-gray-700 mb-1"> | |
| Number of Photos | |
| </label> | |
| <input | |
| type="number" | |
| name="deliverables.numPhotos" | |
| value={formData.deliverables.numPhotos} | |
| onChange={handleChange} | |
| className="w-full border border-gray-300 rounded-lg px-3 py-2" | |
| /> | |
| </div> | |
| <div> | |
| <label className="block text-sm text-gray-700 mb-1"> | |
| Edited Photos | |
| </label> | |
| <input | |
| type="number" | |
| name="deliverables.numEdited" | |
| value={formData.deliverables.numEdited} | |
| onChange={handleChange} | |
| className="w-full border border-gray-300 rounded-lg px-3 py-2" | |
| /> | |
| </div> | |
| <div> | |
| <label className="block text-sm text-gray-700 mb-1"> | |
| Locations | |
| </label> | |
| <input | |
| type="number" | |
| name="deliverables.numLocations" | |
| value={formData.deliverables.numLocations} | |
| onChange={handleChange} | |
| className="w-full border border-gray-300 rounded-lg px-3 py-2" | |
| /> | |
| </div> | |
| <label className="flex items-center gap-2 text-sm"> | |
| <input | |
| type="checkbox" | |
| name="deliverables.includesAlbum" | |
| checked={formData.deliverables.includesAlbum} | |
| onChange={handleChange} | |
| className="w-4 h-4" | |
| /> | |
| <span className="text-gray-700">Include Album Book</span> | |
| </label> | |
| </div> | |
| </div> | |
| <div className="flex gap-3 pt-4"> | |
| <button | |
| type="button" | |
| onClick={onClose} | |
| className="flex-1 py-2 px-4 border border-gray-300 rounded-lg text-gray-700 hover:bg-gray-50 font-medium" | |
| > | |
| Cancel | |
| </button> | |
| <button | |
| type="submit" | |
| className="flex-1 py-2 px-4 bg-blue-600 text-white rounded-lg hover:bg-blue-700 font-medium" | |
| > | |
| {editingPackage ? 'Update' : 'Create'} Package | |
| </button> | |
| </div> | |
| </form> | |
| </div> | |
| </div> | |
| ); | |
| }; | |
| export default CreatePackageModal; | |