import React, { useState, useEffect } from "react"; import { Link, useNavigate } from "react-router-dom"; import { useAuth } from "../contexts/AuthContext"; import { rentalAPI, conditionCheckAPI } from "../services/api"; import { getImageUrl } from "../services/uploadService"; import { Rental, ConditionCheck } from "../types"; import ReviewItemModal from "../components/ReviewModal"; import RentalCancellationModal from "../components/RentalCancellationModal"; import ConditionCheckModal from "../components/ConditionCheckModal"; import ConditionCheckViewerModal from "../components/ConditionCheckViewerModal"; const Renting: React.FC = () => { // Helper function to format time const formatTime = (timeString?: string) => { if (!timeString || timeString.trim() === "") return ""; try { const [hour, minute] = timeString.split(":"); const hourNum = parseInt(hour); const hour12 = hourNum === 0 ? 12 : hourNum > 12 ? hourNum - 12 : hourNum; const period = hourNum < 12 ? "AM" : "PM"; return `${hour12}:${minute} ${period}`; } catch (error) { return ""; } }; // Helper function to format date and time together const formatDateTime = (dateTimeString: string) => { const date = new Date(dateTimeString); return date .toLocaleDateString("en-US", { month: "2-digit", day: "2-digit", year: "numeric", hour: "numeric", minute: "2-digit", hour12: true, }) .replace(",", ""); }; const { user } = useAuth(); const navigate = useNavigate(); const [rentals, setRentals] = useState([]); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); const [showReviewModal, setShowReviewModal] = useState(false); const [selectedRental, setSelectedRental] = useState(null); const [showCancelModal, setShowCancelModal] = useState(false); const [rentalToCancel, setRentalToCancel] = useState(null); const [showConditionCheckModal, setShowConditionCheckModal] = useState(false); const [conditionCheckData, setConditionCheckData] = useState<{ rental: Rental; checkType: string; } | null>(null); const [availableChecks, setAvailableChecks] = useState([]); const [conditionChecks, setConditionChecks] = useState([]); const [showConditionCheckViewer, setShowConditionCheckViewer] = useState(false); const [selectedConditionCheck, setSelectedConditionCheck] = useState(null); useEffect(() => { fetchRentals(); fetchAvailableChecks(); }, []); useEffect(() => { if (rentals.length > 0) { fetchConditionChecks(); } }, [rentals]); const fetchRentals = async () => { try { const response = await rentalAPI.getRentals(); setRentals(response.data || []); } catch (err: any) { setError(err.response?.data?.message || "Failed to fetch rentals"); } finally { setLoading(false); } }; const fetchAvailableChecks = async () => { try { const response = await conditionCheckAPI.getAvailableChecks(); const checks = Array.isArray(response.data.availableChecks) ? response.data.availableChecks : []; setAvailableChecks(checks); } catch (err: any) { console.error("Failed to fetch available checks:", err); setAvailableChecks([]); } }; const fetchConditionChecks = async () => { try { // Fetch condition checks for all rentals const allChecks: any[] = []; for (const rental of rentals) { try { const response = await conditionCheckAPI.getConditionChecks( rental.id ); const checks = Array.isArray(response.data.conditionChecks) ? response.data.conditionChecks : []; allChecks.push(...checks); } catch (err) { // Continue even if one rental fails console.error(`Failed to fetch checks for rental ${rental.id}:`, err); } } setConditionChecks(allChecks); } catch (err: any) { console.error("Failed to fetch condition checks:", err); setConditionChecks([]); } }; const handleCancelClick = (rental: Rental) => { setRentalToCancel(rental); setShowCancelModal(true); }; const handleCancellationComplete = (updatedRental: Rental) => { // Update the rental in the list setRentals((prev) => prev.map((rental) => rental.id === updatedRental.id ? updatedRental : rental ) ); setShowCancelModal(false); setRentalToCancel(null); }; const handleReviewClick = (rental: Rental) => { setSelectedRental(rental); setShowReviewModal(true); }; const handleReviewSuccess = () => { fetchRentals(); alert("Thank you for your review!"); }; const handleConditionCheck = (rental: Rental, checkType: string) => { setConditionCheckData({ rental, checkType }); setShowConditionCheckModal(true); }; const handleConditionCheckSuccess = () => { fetchAvailableChecks(); fetchConditionChecks(); }; const handleViewConditionCheck = (check: ConditionCheck) => { setSelectedConditionCheck(check); setShowConditionCheckViewer(true); }; const getAvailableChecksForRental = (rentalId: string) => { if (!Array.isArray(availableChecks)) return []; return availableChecks.filter( (check) => check.rentalId === rentalId && (check.checkType === "rental_start_renter" || check.checkType === "rental_end_renter") ); }; const getCompletedChecksForRental = (rentalId: string) => { if (!Array.isArray(conditionChecks)) return []; return conditionChecks.filter( (check) => check.rentalId === rentalId && (check.checkType === "rental_start_renter" || check.checkType === "rental_end_renter") ); }; // Filter rentals - show only active rentals (declined go to history) // Use displayStatus for filtering as it includes computed "active" status const renterActiveRentals = rentals.filter((r) => ["pending", "confirmed", "active"].includes(r.displayStatus || r.status) ); if (loading) { return (
Loading...
); } if (error) { return (
{error}
); } return (

Rentals

{renterActiveRentals.length === 0 ? (
No Active Rental Requests

You don't have any rental requests at the moment.

Browse Items to Rent
) : (
{renterActiveRentals.map((rental) => (
) => { const target = e.target as HTMLElement; if (!rental.item || target.closest("button")) { e.preventDefault(); } }} >
{rental.item?.imageFilenames && rental.item.imageFilenames[0] && ( {rental.item.name} { const target = e.currentTarget; if (!target.dataset.fallback && rental.item) { target.dataset.fallback = 'true'; target.src = getImageUrl(rental.item.imageFilenames[0], 'original'); } }} style={{ height: "200px", objectFit: "contain", backgroundColor: "#f8f9fa", }} /> )}
{rental.item ? rental.item.name : "Item Unavailable"}
{(rental.displayStatus || rental.status) === "pending" ? "Awaiting Owner Approval" : (rental.displayStatus || rental.status) === "confirmed" ? "Confirmed & Paid" : (rental.displayStatus || rental.status) === "declined" ? "Declined by Owner" : (rental.displayStatus || rental.status).charAt(0).toUpperCase() + (rental.displayStatus || rental.status).slice(1)}

Rental Period:
Start:{" "} {formatDateTime(rental.startDateTime)}
End: {formatDateTime(rental.endDateTime)}

Total: ${rental.totalAmount}

{rental.owner && (

Owner:{" "} navigate(`/users/${rental.ownerId}`)} style={{ cursor: "pointer" }} > {rental.owner.firstName} {rental.owner.lastName}

)} {rental.renterPrivateMessage && rental.renterReviewVisible && (
Private Note from Owner:
{rental.renterPrivateMessage}
)} {rental.status === "declined" && rental.declineReason && (
Decline reason: {rental.declineReason}
)} {rental.status === "cancelled" && ( <> {rental.refundAmount !== undefined && (
Refund: {" "} ${rental.refundAmount?.toFixed(2) || "0.00"} {rental.refundProcessedAt && ( Processed:{" "} {new Date( rental.refundProcessedAt ).toLocaleDateString()} )} {rental.refundReason && ( {rental.refundReason} )}
)} )}
{((rental.displayStatus || rental.status) === "pending" || (rental.displayStatus || rental.status) === "confirmed") && ( )} {(rental.displayStatus || rental.status) === "active" && !rental.itemRating && !rental.itemReviewSubmittedAt && ( )}
{/* Condition Check Status */} {getCompletedChecksForRental(rental.id).length > 0 && (
{getCompletedChecksForRental(rental.id).map( (check) => ( ) )}
)} {/* Condition Check Buttons */} {getAvailableChecksForRental(rental.id).map((check) => ( ))} {/* Review Status */} {rental.itemReviewSubmittedAt && !rental.itemReviewVisible && (
Review Submitted
)} {rental.itemReviewVisible && rental.itemRating && (
Review Published ({rental.itemRating}/5)
)} {rental.status === "completed" && rental.rating && !rental.itemRating && (
Reviewed ({rental.rating}/5)
)}
))}
)} {/* Review Modal */} {selectedRental && ( { setShowReviewModal(false); setSelectedRental(null); }} rental={selectedRental} onSuccess={handleReviewSuccess} /> )} {rentalToCancel && ( { setShowCancelModal(false); setRentalToCancel(null); }} rental={rentalToCancel} onCancellationComplete={handleCancellationComplete} /> )} {/* Condition Check Modal */} {conditionCheckData && ( { setShowConditionCheckModal(false); setConditionCheckData(null); }} rentalId={conditionCheckData.rental.id} checkType={conditionCheckData.checkType} itemName={conditionCheckData.rental.item?.name || "Item"} onSuccess={handleConditionCheckSuccess} /> )} {/* Condition Check Viewer Modal */} { setShowConditionCheckViewer(false); setSelectedConditionCheck(null); }} conditionCheck={selectedConditionCheck} />
); }; export default Renting;