import React, { useState, useEffect } from 'react'; import { useParams, useNavigate } from 'react-router-dom'; import { Item, Rental } from '../types'; import { useAuth } from '../contexts/AuthContext'; import { itemAPI, rentalAPI } from '../services/api'; import AvailabilityCalendar from '../components/AvailabilityCalendar'; import AddressAutocomplete from '../components/AddressAutocomplete'; interface ItemFormData { name: string; description: string; tags: string[]; pickUpAvailable: boolean; localDeliveryAvailable: boolean; localDeliveryRadius?: number; shippingAvailable: boolean; inPlaceUseAvailable: boolean; pricePerHour?: number; pricePerDay?: number; replacementCost: number; location: string; latitude?: number; longitude?: number; rules?: string; minimumRentalDays: number; needsTraining: boolean; availability: boolean; unavailablePeriods?: Array<{ id: string; startDate: Date; endDate: Date; startTime?: string; endTime?: string; }>; } const EditItem: React.FC = () => { const { id } = useParams<{ id: string }>(); const navigate = useNavigate(); const { user } = useAuth(); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); const [success, setSuccess] = useState(false); const [tagInput, setTagInput] = useState(""); const [imageFiles, setImageFiles] = useState([]); const [imagePreviews, setImagePreviews] = useState([]); const [priceType, setPriceType] = useState<"hour" | "day">("day"); const [acceptedRentals, setAcceptedRentals] = useState([]); const [formData, setFormData] = useState({ name: '', description: '', tags: [], pickUpAvailable: false, localDeliveryAvailable: false, shippingAvailable: false, inPlaceUseAvailable: false, pricePerHour: undefined, pricePerDay: undefined, replacementCost: 0, location: '', rules: '', minimumRentalDays: 1, needsTraining: false, availability: true, unavailablePeriods: [], }); useEffect(() => { fetchItem(); fetchAcceptedRentals(); }, [id]); const fetchItem = async () => { try { const response = await itemAPI.getItem(id!); const item: Item = response.data; if (item.ownerId !== user?.id) { setError('You are not authorized to edit this item'); return; } // Set the price type based on available pricing if (item.pricePerHour) { setPriceType('hour'); } else if (item.pricePerDay) { setPriceType('day'); } // Convert item data to form data format setFormData({ name: item.name, description: item.description, tags: item.tags || [], pickUpAvailable: item.pickUpAvailable || false, localDeliveryAvailable: item.localDeliveryAvailable || false, localDeliveryRadius: item.localDeliveryRadius || 25, shippingAvailable: item.shippingAvailable || false, inPlaceUseAvailable: item.inPlaceUseAvailable || false, pricePerHour: item.pricePerHour, pricePerDay: item.pricePerDay, replacementCost: item.replacementCost, location: item.location, latitude: item.latitude, longitude: item.longitude, rules: item.rules || '', minimumRentalDays: item.minimumRentalDays, needsTraining: item.needsTraining || false, availability: item.availability, unavailablePeriods: item.unavailablePeriods || [], }); // Set existing images as previews if (item.images && item.images.length > 0) { setImagePreviews(item.images); } } catch (err: any) { setError(err.response?.data?.message || 'Failed to fetch item'); } finally { setLoading(false); } }; const fetchAcceptedRentals = async () => { try { const response = await rentalAPI.getMyListings(); const rentals: Rental[] = response.data; // Filter for accepted rentals for this specific item const itemRentals = rentals.filter(rental => rental.itemId === id && ['confirmed', 'active'].includes(rental.status) ); setAcceptedRentals(itemRentals); } catch (err) { console.error('Error fetching rentals:', err); } }; const handleChange = ( e: React.ChangeEvent< HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement > ) => { const { name, value, type } = e.target; if (type === "checkbox") { const checked = (e.target as HTMLInputElement).checked; setFormData((prev) => ({ ...prev, [name]: checked })); } else if (type === "number") { setFormData((prev) => ({ ...prev, [name]: value ? parseFloat(value) : undefined, })); } else { setFormData((prev) => ({ ...prev, [name]: value })); } }; const handleSubmit = async (e: React.FormEvent) => { e.preventDefault(); setError(null); try { // Use existing image previews (which includes both old and new images) const imageUrls = imagePreviews; await itemAPI.updateItem(id!, { ...formData, images: imageUrls, isPortable: formData.pickUpAvailable || formData.shippingAvailable, }); setSuccess(true); setTimeout(() => { navigate(`/items/${id}`); }, 1500); } catch (err: any) { setError(err.response?.data?.message || 'Failed to update item'); } }; const addTag = () => { if (tagInput.trim() && !formData.tags.includes(tagInput.trim())) { setFormData((prev) => ({ ...prev, tags: [...prev.tags, tagInput.trim()], })); setTagInput(""); } }; const removeTag = (tag: string) => { setFormData((prev) => ({ ...prev, tags: prev.tags.filter((t) => t !== tag), })); }; const handleImageChange = (e: React.ChangeEvent) => { const files = Array.from(e.target.files || []); // Limit to 5 images total if (imagePreviews.length + files.length > 5) { setError("You can upload a maximum of 5 images"); return; } const newImageFiles = [...imageFiles, ...files]; setImageFiles(newImageFiles); // Create previews files.forEach((file) => { const reader = new FileReader(); reader.onloadend = () => { setImagePreviews((prev) => [...prev, reader.result as string]); }; reader.readAsDataURL(file); }); }; const removeImage = (index: number) => { setImagePreviews((prev) => prev.filter((_, i) => i !== index)); }; if (loading) { return (
Loading...
); } if (error && error.includes('authorized')) { return (
{error}
); } return (

Edit Listing

{error && (
{error}
)} {success && (
Item updated successfully! Redirecting...
)}
= 5} />
Upload up to 5 images of your item
{imagePreviews.length > 0 && (
{imagePreviews.map((preview, index) => (
{`Preview
))}
)}