import React, { useState, useEffect, useRef } from "react"; import { useParams, useNavigate, useSearchParams } from "react-router-dom"; import { Item } from "../types"; import { useAuth } from "../contexts/AuthContext"; import { itemAPI, rentalAPI } from "../services/api"; import EmbeddedStripeCheckout from "../components/EmbeddedStripeCheckout"; const RentItem: React.FC = () => { const { id } = useParams<{ id: string }>(); const navigate = useNavigate(); const { user } = useAuth(); const [searchParams] = useSearchParams(); const [item, setItem] = useState(null); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); const [formData, setFormData] = useState({ deliveryMethod: "pickup" as "pickup" | "delivery", deliveryAddress: "", }); const [manualSelection, setManualSelection] = useState({ startDate: searchParams.get("startDate") || "", startTime: searchParams.get("startTime") || "09:00", endDate: searchParams.get("endDate") || "", endTime: searchParams.get("endTime") || "17:00", }); const [totalCost, setTotalCost] = useState(0); const [completed, setCompleted] = useState(false); const convertToUTC = (dateString: string, timeString: string): string => { if (!dateString || !timeString) { throw new Error("Date and time are required"); } // Create date in user's local timezone const localDateTime = new Date(`${dateString}T${timeString}`); // Return UTC ISO string return localDateTime.toISOString(); }; const formatDate = (dateString: string) => { if (!dateString) return ""; // Use safe date parsing to avoid timezone issues const [year, month, day] = dateString.split("-"); const date = new Date(parseInt(year), parseInt(month) - 1, parseInt(day)); return date.toLocaleDateString(); }; const formatTime = (timeString: string) => { if (!timeString) return ""; const [hour, minute] = timeString.split(":"); const hour12 = parseInt(hour) === 0 ? 12 : parseInt(hour) > 12 ? parseInt(hour) - 12 : parseInt(hour); const period = parseInt(hour) < 12 ? "AM" : "PM"; return `${hour12}:${minute} ${period}`; }; const calculateTotalCost = () => { if (!item || !manualSelection.startDate || !manualSelection.endDate) { setTotalCost(0); return; } const startDateTime = new Date( `${manualSelection.startDate}T${manualSelection.startTime}` ); const endDateTime = new Date( `${manualSelection.endDate}T${manualSelection.endTime}` ); const diffMs = endDateTime.getTime() - startDateTime.getTime(); const diffHours = Math.ceil(diffMs / (1000 * 60 * 60)); const diffDays = Math.ceil(diffMs / (1000 * 60 * 60 * 24)); let cost = 0; if (item.pricePerHour && diffHours <= 24) { cost = diffHours * Number(item.pricePerHour); } else if (item.pricePerDay) { cost = diffDays * Number(item.pricePerDay); } setTotalCost(cost); }; useEffect(() => { fetchItem(); }, [id]); useEffect(() => { calculateTotalCost(); }, [item, manualSelection]); const fetchItem = async () => { try { const response = await itemAPI.getItem(id!); setItem(response.data); // Check if item is available if (!response.data.availability) { setError("This item is not available for rent"); } // Check if user is trying to rent their own item if (response.data.ownerId === user?.id) { setError("You cannot rent your own item"); } } catch (err: any) { setError(err.response?.data?.message || "Failed to fetch item"); } finally { setLoading(false); } }; const getRentalData = () => { try { const startDateTime = convertToUTC( manualSelection.startDate, manualSelection.startTime ); const endDateTime = convertToUTC( manualSelection.endDate, manualSelection.endTime ); return { itemId: id, startDateTime, endDateTime, deliveryMethod: formData.deliveryMethod, deliveryAddress: formData.deliveryAddress, totalAmount: totalCost, }; } catch (error: any) { setError(error.message); return null; } }; const handleFreeBorrow = async () => { const rentalData = getRentalData(); if (!rentalData) return; try { setError(null); await rentalAPI.createRental(rentalData); setCompleted(true); } catch (error: any) { setError( error.response?.data?.error || "Failed to create rental request" ); } }; const handleChange = ( e: React.ChangeEvent< HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement > ) => { const { name, value } = e.target; setFormData((prev) => ({ ...prev, [name]: value })); }; if (loading) { return (
Loading...
); } if ( !item || error === "You cannot rent your own item" || error === "This item is not available for rent" ) { return (
{error || "Item not found"}
); } return (

Renting {item.name}

{error && (
{error}
)}
{completed ? (

Rental Request Sent!

Your rental request has been submitted to the owner. You'll only be charged if they approve your request.

) : (
{totalCost === 0 ? "Complete Your Borrow Request" : "Complete Your Rental Request"}
{totalCost > 0 && (

Add your payment method to complete your rental request. You'll only be charged if the owner approves your request.

)} {!manualSelection.startDate || !manualSelection.endDate || !getRentalData() ? (
Please complete the rental dates and details above to proceed with{" "} {totalCost === 0 ? "your borrow request" : "payment setup"} .
) : totalCost === 0 ? ( <>
) : ( <> setCompleted(true)} onError={(error) => setError(error)} />
)}
)}
{item.images && item.images[0] && ( {item.name} )}
{item.name}

{item.city && item.state ? `${item.city}, ${item.state}` : ""}


{/* Pricing */}
{totalCost === 0 ? (
Free to Borrow
) : ( <> {item.pricePerHour && Number(item.pricePerHour) > 0 && (
${Math.floor(Number(item.pricePerHour))}/Hour
)} {item.pricePerDay && Number(item.pricePerDay) > 0 && (
${Math.floor(Number(item.pricePerDay))}/Day
)} )}
{/* Selected Dates */} {manualSelection.startDate && manualSelection.endDate && (
Check-in:{" "} {formatDate(manualSelection.startDate)} at{" "} {formatTime(manualSelection.startTime)}
Check-out:{" "} {formatDate(manualSelection.endDate)} at{" "} {formatTime(manualSelection.endTime)}
)} {/* Total Cost */} {totalCost > 0 && ( <>
Total: ${totalCost}
)}
); }; export default RentItem;