email plus return item statuses
This commit is contained in:
@@ -3,9 +3,11 @@ import { Link, useNavigate } from "react-router-dom";
|
||||
import { useAuth } from "../contexts/AuthContext";
|
||||
import api from "../services/api";
|
||||
import { Item, Rental } from "../types";
|
||||
import { rentalAPI } from "../services/api";
|
||||
import { rentalAPI, conditionCheckAPI } from "../services/api";
|
||||
import ReviewRenterModal from "../components/ReviewRenterModal";
|
||||
import RentalCancellationModal from "../components/RentalCancellationModal";
|
||||
import ConditionCheckModal from "../components/ConditionCheckModal";
|
||||
import ReturnStatusModal from "../components/ReturnStatusModal";
|
||||
|
||||
const MyListings: React.FC = () => {
|
||||
// Helper function to format time
|
||||
@@ -24,8 +26,17 @@ const MyListings: React.FC = () => {
|
||||
|
||||
// Helper function to format date and time together
|
||||
const formatDateTime = (dateTimeString: string) => {
|
||||
const date = new Date(dateTimeString).toLocaleDateString();
|
||||
return date;
|
||||
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();
|
||||
@@ -42,12 +53,28 @@ const MyListings: React.FC = () => {
|
||||
const [rentalToCancel, setRentalToCancel] = useState<Rental | null>(null);
|
||||
const [isProcessingPayment, setIsProcessingPayment] = useState<string>("");
|
||||
const [processingSuccess, setProcessingSuccess] = useState<string>("");
|
||||
const [showConditionCheckModal, setShowConditionCheckModal] = useState(false);
|
||||
const [conditionCheckData, setConditionCheckData] = useState<{
|
||||
rental: Rental;
|
||||
checkType: string;
|
||||
} | null>(null);
|
||||
const [availableChecks, setAvailableChecks] = useState<any[]>([]);
|
||||
const [conditionChecks, setConditionChecks] = useState<any[]>([]);
|
||||
const [showReturnStatusModal, setShowReturnStatusModal] = useState(false);
|
||||
const [rentalForReturn, setRentalForReturn] = useState<Rental | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
fetchMyListings();
|
||||
fetchOwnerRentals();
|
||||
fetchAvailableChecks();
|
||||
}, [user]);
|
||||
|
||||
useEffect(() => {
|
||||
if (ownerRentals.length > 0) {
|
||||
fetchConditionChecks();
|
||||
}
|
||||
}, [ownerRentals]);
|
||||
|
||||
const fetchMyListings = async () => {
|
||||
if (!user) return;
|
||||
|
||||
@@ -108,6 +135,44 @@ const MyListings: React.FC = () => {
|
||||
}
|
||||
};
|
||||
|
||||
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 owner rentals
|
||||
const allChecks: any[] = [];
|
||||
for (const rental of ownerRentals) {
|
||||
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([]);
|
||||
}
|
||||
};
|
||||
|
||||
// Owner functionality handlers
|
||||
const handleAcceptRental = async (rentalId: string) => {
|
||||
try {
|
||||
@@ -127,6 +192,7 @@ const MyListings: React.FC = () => {
|
||||
}
|
||||
|
||||
fetchOwnerRentals();
|
||||
fetchAvailableChecks(); // Refresh available checks after rental confirmation
|
||||
} catch (err: any) {
|
||||
console.error("Failed to accept rental request:", err);
|
||||
|
||||
@@ -155,21 +221,27 @@ const MyListings: React.FC = () => {
|
||||
}
|
||||
};
|
||||
|
||||
const handleCompleteClick = async (rental: Rental) => {
|
||||
try {
|
||||
await rentalAPI.markAsCompleted(rental.id);
|
||||
const handleCompleteClick = (rental: Rental) => {
|
||||
setRentalForReturn(rental);
|
||||
setShowReturnStatusModal(true);
|
||||
};
|
||||
|
||||
setSelectedRentalForReview(rental);
|
||||
setShowReviewRenterModal(true);
|
||||
const handleReturnStatusMarked = async (updatedRental: Rental) => {
|
||||
// Update the rental in the list
|
||||
setOwnerRentals((prev) =>
|
||||
prev.map((rental) =>
|
||||
rental.id === updatedRental.id ? updatedRental : rental
|
||||
)
|
||||
);
|
||||
|
||||
fetchOwnerRentals();
|
||||
} catch (err: any) {
|
||||
console.error("Error marking rental as completed:", err);
|
||||
alert(
|
||||
"Failed to mark rental as completed: " +
|
||||
(err.response?.data?.error || err.message)
|
||||
);
|
||||
}
|
||||
// Close the return status modal
|
||||
setShowReturnStatusModal(false);
|
||||
setRentalForReturn(null);
|
||||
|
||||
// Show review modal (rental is already marked as completed by return status endpoint)
|
||||
setSelectedRentalForReview(updatedRental);
|
||||
setShowReviewRenterModal(true);
|
||||
fetchOwnerRentals();
|
||||
};
|
||||
|
||||
const handleReviewRenterSuccess = () => {
|
||||
@@ -192,6 +264,35 @@ const MyListings: React.FC = () => {
|
||||
setRentalToCancel(null);
|
||||
};
|
||||
|
||||
const handleConditionCheck = (rental: Rental, checkType: string) => {
|
||||
setConditionCheckData({ rental, checkType });
|
||||
setShowConditionCheckModal(true);
|
||||
};
|
||||
|
||||
const handleConditionCheckSuccess = () => {
|
||||
fetchAvailableChecks();
|
||||
fetchConditionChecks();
|
||||
alert("Condition check submitted successfully!");
|
||||
};
|
||||
|
||||
const getAvailableChecksForRental = (rentalId: string) => {
|
||||
if (!Array.isArray(availableChecks)) return [];
|
||||
return availableChecks.filter(
|
||||
(check) =>
|
||||
check.rentalId === rentalId && check.checkType === "pre_rental_owner" // Only pre-rental; post-rental is in return modal
|
||||
);
|
||||
};
|
||||
|
||||
const getCompletedChecksForRental = (rentalId: string) => {
|
||||
if (!Array.isArray(conditionChecks)) return [];
|
||||
return conditionChecks.filter(
|
||||
(check) =>
|
||||
check.rentalId === rentalId &&
|
||||
(check.checkType === "pre_rental_owner" ||
|
||||
check.checkType === "post_rental_owner")
|
||||
);
|
||||
};
|
||||
|
||||
// Filter owner rentals
|
||||
const allOwnerRentals = ownerRentals
|
||||
.filter((r) =>
|
||||
@@ -331,73 +432,115 @@ const MyListings: React.FC = () => {
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div className="d-flex gap-2 mt-3">
|
||||
{rental.status === "pending" && (
|
||||
<>
|
||||
<button
|
||||
className="btn btn-sm btn-success"
|
||||
onClick={() => handleAcceptRental(rental.id)}
|
||||
disabled={isProcessingPayment === rental.id}
|
||||
>
|
||||
{isProcessingPayment === rental.id ? (
|
||||
<>
|
||||
<div
|
||||
className="spinner-border spinner-border-sm me-2"
|
||||
role="status"
|
||||
>
|
||||
<span className="visually-hidden">
|
||||
Loading...
|
||||
</span>
|
||||
</div>
|
||||
Processing Payment...
|
||||
</>
|
||||
) : processingSuccess === rental.id ? (
|
||||
<>
|
||||
<i className="bi bi-check-circle me-1"></i>
|
||||
Payment Success!
|
||||
</>
|
||||
) : (
|
||||
"Accept"
|
||||
)}
|
||||
</button>
|
||||
<button
|
||||
className="btn btn-sm btn-danger"
|
||||
onClick={() => handleRejectRental(rental.id)}
|
||||
>
|
||||
Reject
|
||||
</button>
|
||||
<button
|
||||
className="btn btn-sm btn-outline-danger"
|
||||
onClick={() => handleCancelClick(rental)}
|
||||
>
|
||||
Cancel
|
||||
</button>
|
||||
</>
|
||||
)}
|
||||
{rental.status === "confirmed" && (
|
||||
<>
|
||||
<div className="d-flex flex-column gap-2 mt-3">
|
||||
<div className="d-flex gap-2">
|
||||
{rental.status === "pending" && (
|
||||
<>
|
||||
<button
|
||||
className="btn btn-sm btn-success"
|
||||
onClick={() => handleAcceptRental(rental.id)}
|
||||
disabled={isProcessingPayment === rental.id}
|
||||
>
|
||||
{isProcessingPayment === rental.id ? (
|
||||
<>
|
||||
<div
|
||||
className="spinner-border spinner-border-sm me-2"
|
||||
role="status"
|
||||
>
|
||||
<span className="visually-hidden">
|
||||
Loading...
|
||||
</span>
|
||||
</div>
|
||||
Processing Payment...
|
||||
</>
|
||||
) : processingSuccess === rental.id ? (
|
||||
<>
|
||||
<i className="bi bi-check-circle me-1"></i>
|
||||
Payment Success!
|
||||
</>
|
||||
) : (
|
||||
"Accept"
|
||||
)}
|
||||
</button>
|
||||
<button
|
||||
className="btn btn-sm btn-danger"
|
||||
onClick={() => handleRejectRental(rental.id)}
|
||||
>
|
||||
Reject
|
||||
</button>
|
||||
<button
|
||||
className="btn btn-sm btn-outline-danger"
|
||||
onClick={() => handleCancelClick(rental)}
|
||||
>
|
||||
Cancel
|
||||
</button>
|
||||
</>
|
||||
)}
|
||||
{rental.status === "confirmed" && (
|
||||
<>
|
||||
<button
|
||||
className="btn btn-sm btn-success"
|
||||
onClick={() => handleCompleteClick(rental)}
|
||||
>
|
||||
Complete
|
||||
</button>
|
||||
<button
|
||||
className="btn btn-sm btn-outline-danger"
|
||||
onClick={() => handleCancelClick(rental)}
|
||||
>
|
||||
Cancel
|
||||
</button>
|
||||
</>
|
||||
)}
|
||||
{rental.status === "active" && (
|
||||
<button
|
||||
className="btn btn-sm btn-success"
|
||||
onClick={() => handleCompleteClick(rental)}
|
||||
>
|
||||
Complete
|
||||
</button>
|
||||
<button
|
||||
className="btn btn-sm btn-outline-danger"
|
||||
onClick={() => handleCancelClick(rental)}
|
||||
>
|
||||
Cancel
|
||||
</button>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* Condition Check Status */}
|
||||
{getCompletedChecksForRental(rental.id).length > 0 && (
|
||||
<div className="mb-2">
|
||||
{getCompletedChecksForRental(rental.id).map(
|
||||
(check) => (
|
||||
<div
|
||||
key={`${rental.id}-${check.checkType}-status`}
|
||||
className="text-success small"
|
||||
>
|
||||
<i className="bi bi-camera-fill me-1"></i>
|
||||
{check.checkType === "pre_rental_owner"
|
||||
? "Pre-Rental Check Completed"
|
||||
: "Post-Rental Check Completed"}
|
||||
<small className="text-muted ms-2">
|
||||
{new Date(
|
||||
check.createdAt
|
||||
).toLocaleDateString()}
|
||||
</small>
|
||||
</div>
|
||||
)
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
{rental.status === "active" && (
|
||||
|
||||
{/* Condition Check Buttons */}
|
||||
{getAvailableChecksForRental(rental.id).map((check) => (
|
||||
<button
|
||||
className="btn btn-sm btn-success"
|
||||
onClick={() => handleCompleteClick(rental)}
|
||||
key={`${rental.id}-${check.checkType}`}
|
||||
className="btn btn-sm btn-outline-primary"
|
||||
onClick={() =>
|
||||
handleConditionCheck(rental, check.checkType)
|
||||
}
|
||||
>
|
||||
Complete
|
||||
<i className="bi bi-camera me-2" />
|
||||
{check.checkType === "pre_rental_owner"
|
||||
? "Submit Pre-Rental Check"
|
||||
: "Submit Post-Rental Check"}
|
||||
</button>
|
||||
)}
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -572,6 +715,35 @@ const MyListings: React.FC = () => {
|
||||
onCancellationComplete={handleCancellationComplete}
|
||||
/>
|
||||
)}
|
||||
|
||||
{/* Condition Check Modal */}
|
||||
{conditionCheckData && (
|
||||
<ConditionCheckModal
|
||||
show={showConditionCheckModal}
|
||||
onHide={() => {
|
||||
setShowConditionCheckModal(false);
|
||||
setConditionCheckData(null);
|
||||
}}
|
||||
rentalId={conditionCheckData.rental.id}
|
||||
checkType={conditionCheckData.checkType}
|
||||
itemName={conditionCheckData.rental.item?.name || "Item"}
|
||||
onSuccess={handleConditionCheckSuccess}
|
||||
/>
|
||||
)}
|
||||
|
||||
{/* Return Status Modal */}
|
||||
{rentalForReturn && (
|
||||
<ReturnStatusModal
|
||||
show={showReturnStatusModal}
|
||||
onHide={() => {
|
||||
setShowReturnStatusModal(false);
|
||||
setRentalForReturn(null);
|
||||
}}
|
||||
rental={rentalForReturn}
|
||||
onReturnMarked={handleReturnStatusMarked}
|
||||
onSubmitSuccess={handleReturnStatusMarked}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
import React, { useState, useEffect } from "react";
|
||||
import { Link } from "react-router-dom";
|
||||
import { useAuth } from "../contexts/AuthContext";
|
||||
import { rentalAPI } from "../services/api";
|
||||
import { rentalAPI, conditionCheckAPI } from "../services/api";
|
||||
import { Rental } from "../types";
|
||||
import ReviewItemModal from "../components/ReviewModal";
|
||||
import RentalCancellationModal from "../components/RentalCancellationModal";
|
||||
import ConditionCheckModal from "../components/ConditionCheckModal";
|
||||
|
||||
const MyRentals: React.FC = () => {
|
||||
// Helper function to format time
|
||||
@@ -21,6 +22,21 @@ const MyRentals: React.FC = () => {
|
||||
}
|
||||
};
|
||||
|
||||
// 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 [rentals, setRentals] = useState<Rental[]>([]);
|
||||
const [loading, setLoading] = useState(true);
|
||||
@@ -29,11 +45,25 @@ const MyRentals: React.FC = () => {
|
||||
const [selectedRental, setSelectedRental] = useState<Rental | null>(null);
|
||||
const [showCancelModal, setShowCancelModal] = useState(false);
|
||||
const [rentalToCancel, setRentalToCancel] = useState<Rental | null>(null);
|
||||
const [showConditionCheckModal, setShowConditionCheckModal] = useState(false);
|
||||
const [conditionCheckData, setConditionCheckData] = useState<{
|
||||
rental: Rental;
|
||||
checkType: string;
|
||||
} | null>(null);
|
||||
const [availableChecks, setAvailableChecks] = useState<any[]>([]);
|
||||
const [conditionChecks, setConditionChecks] = useState<any[]>([]);
|
||||
|
||||
useEffect(() => {
|
||||
fetchRentals();
|
||||
fetchAvailableChecks();
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
if (rentals.length > 0) {
|
||||
fetchConditionChecks();
|
||||
}
|
||||
}, [rentals]);
|
||||
|
||||
const fetchRentals = async () => {
|
||||
try {
|
||||
const response = await rentalAPI.getMyRentals();
|
||||
@@ -45,6 +75,44 @@ const MyRentals: React.FC = () => {
|
||||
}
|
||||
};
|
||||
|
||||
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);
|
||||
@@ -71,6 +139,37 @@ const MyRentals: React.FC = () => {
|
||||
alert("Thank you for your review!");
|
||||
};
|
||||
|
||||
const handleConditionCheck = (rental: Rental, checkType: string) => {
|
||||
setConditionCheckData({ rental, checkType });
|
||||
setShowConditionCheckModal(true);
|
||||
};
|
||||
|
||||
const handleConditionCheckSuccess = () => {
|
||||
fetchAvailableChecks();
|
||||
fetchConditionChecks();
|
||||
alert("Condition check submitted successfully!");
|
||||
};
|
||||
|
||||
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 - only show active rentals (pending, confirmed, active)
|
||||
const renterActiveRentals = rentals.filter((r) =>
|
||||
["pending", "confirmed", "active"].includes(r.status)
|
||||
@@ -164,21 +263,13 @@ const MyRentals: React.FC = () => {
|
||||
</span>
|
||||
</div>
|
||||
|
||||
{rental.status === "pending" && (
|
||||
<div className="alert alert-info mt-2 mb-2 p-2 small">
|
||||
You'll only be charged if the owner approves your
|
||||
request.
|
||||
</div>
|
||||
)}
|
||||
|
||||
<p className="mb-1 text-dark">
|
||||
<strong>Rental Period:</strong>
|
||||
<br />
|
||||
<strong>Start:</strong>{" "}
|
||||
{new Date(rental.startDateTime).toLocaleString()}
|
||||
{formatDateTime(rental.startDateTime)}
|
||||
<br />
|
||||
<strong>End:</strong>{" "}
|
||||
{new Date(rental.endDateTime).toLocaleString()}
|
||||
<strong>End:</strong> {formatDateTime(rental.endDateTime)}
|
||||
</p>
|
||||
|
||||
<p className="mb-1 text-dark">
|
||||
@@ -237,26 +328,70 @@ const MyRentals: React.FC = () => {
|
||||
</>
|
||||
)}
|
||||
|
||||
<div className="d-flex gap-2 mt-3">
|
||||
{(rental.status === "pending" ||
|
||||
rental.status === "confirmed") && (
|
||||
<button
|
||||
className="btn btn-sm btn-danger"
|
||||
onClick={() => handleCancelClick(rental)}
|
||||
>
|
||||
Cancel
|
||||
</button>
|
||||
)}
|
||||
{rental.status === "active" &&
|
||||
!rental.itemRating &&
|
||||
!rental.itemReviewSubmittedAt && (
|
||||
<div className="d-flex flex-column gap-2 mt-3">
|
||||
<div className="d-flex gap-2">
|
||||
{(rental.status === "pending" ||
|
||||
rental.status === "confirmed") && (
|
||||
<button
|
||||
className="btn btn-sm btn-primary"
|
||||
onClick={() => handleReviewClick(rental)}
|
||||
className="btn btn-sm btn-danger"
|
||||
onClick={() => handleCancelClick(rental)}
|
||||
>
|
||||
Review
|
||||
Cancel
|
||||
</button>
|
||||
)}
|
||||
{rental.status === "active" &&
|
||||
!rental.itemRating &&
|
||||
!rental.itemReviewSubmittedAt && (
|
||||
<button
|
||||
className="btn btn-sm btn-primary"
|
||||
onClick={() => handleReviewClick(rental)}
|
||||
>
|
||||
Review
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* Condition Check Status */}
|
||||
{getCompletedChecksForRental(rental.id).length > 0 && (
|
||||
<div className="mb-2">
|
||||
{getCompletedChecksForRental(rental.id).map(
|
||||
(check) => (
|
||||
<div
|
||||
key={`${rental.id}-${check.checkType}-status`}
|
||||
className="text-success small"
|
||||
>
|
||||
<i className="bi bi-camera-fill me-1"></i>
|
||||
{check.checkType === "rental_start_renter"
|
||||
? "Start Check Completed"
|
||||
: "End Check Completed"}
|
||||
<small className="text-muted ms-2">
|
||||
{new Date(
|
||||
check.createdAt
|
||||
).toLocaleDateString()}
|
||||
</small>
|
||||
</div>
|
||||
)
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Condition Check Buttons */}
|
||||
{getAvailableChecksForRental(rental.id).map((check) => (
|
||||
<button
|
||||
key={`${rental.id}-${check.checkType}`}
|
||||
className="btn btn-sm btn-outline-primary"
|
||||
onClick={() =>
|
||||
handleConditionCheck(rental, check.checkType)
|
||||
}
|
||||
>
|
||||
<i className="bi bi-camera me-2" />
|
||||
{check.checkType === "rental_start_renter"
|
||||
? "Submit Start Check"
|
||||
: "Submit End Check"}
|
||||
</button>
|
||||
))}
|
||||
|
||||
{/* Review Status */}
|
||||
{rental.itemReviewSubmittedAt &&
|
||||
!rental.itemReviewVisible && (
|
||||
<div className="text-info small">
|
||||
@@ -311,6 +446,21 @@ const MyRentals: React.FC = () => {
|
||||
onCancellationComplete={handleCancellationComplete}
|
||||
/>
|
||||
)}
|
||||
|
||||
{/* Condition Check Modal */}
|
||||
{conditionCheckData && (
|
||||
<ConditionCheckModal
|
||||
show={showConditionCheckModal}
|
||||
onHide={() => {
|
||||
setShowConditionCheckModal(false);
|
||||
setConditionCheckData(null);
|
||||
}}
|
||||
rentalId={conditionCheckData.rental.id}
|
||||
checkType={conditionCheckData.checkType}
|
||||
itemName={conditionCheckData.rental.item?.name || "Item"}
|
||||
onSuccess={handleConditionCheckSuccess}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user