condition check gallery

This commit is contained in:
jackiettran
2025-12-16 13:50:23 -05:00
parent 372ab093ef
commit 27a7b641dd
8 changed files with 421 additions and 64 deletions

View File

@@ -2,13 +2,14 @@ import React, { useState, useEffect } from "react";
import { Link, useNavigate } from "react-router-dom";
import { useAuth } from "../contexts/AuthContext";
import api from "../services/api";
import { Item, Rental } from "../types";
import { Item, Rental, ConditionCheck } from "../types";
import { rentalAPI, conditionCheckAPI } from "../services/api";
import { getPublicImageUrl } from "../services/uploadService";
import ReviewRenterModal from "../components/ReviewRenterModal";
import RentalCancellationModal from "../components/RentalCancellationModal";
import DeclineRentalModal from "../components/DeclineRentalModal";
import ConditionCheckModal from "../components/ConditionCheckModal";
import ConditionCheckViewerModal from "../components/ConditionCheckViewerModal";
import ReturnStatusModal from "../components/ReturnStatusModal";
const Owning: React.FC = () => {
@@ -63,6 +64,11 @@ const Owning: React.FC = () => {
checkType: string;
} | null>(null);
const [availableChecks, setAvailableChecks] = useState<any[]>([]);
const [conditionChecks, setConditionChecks] = useState<ConditionCheck[]>([]);
const [showConditionCheckViewer, setShowConditionCheckViewer] =
useState(false);
const [selectedConditionCheck, setSelectedConditionCheck] =
useState<ConditionCheck | null>(null);
const [showReturnStatusModal, setShowReturnStatusModal] = useState(false);
const [rentalForReturn, setRentalForReturn] = useState<Rental | null>(null);
@@ -72,6 +78,12 @@ const Owning: React.FC = () => {
fetchAvailableChecks();
}, [user]);
useEffect(() => {
if (ownerRentals.length > 0) {
fetchConditionChecks();
}
}, [ownerRentals]);
const fetchListings = async () => {
if (!user) return;
@@ -145,6 +157,28 @@ const Owning: React.FC = () => {
}
};
const fetchConditionChecks = async () => {
try {
const allChecks: ConditionCheck[] = [];
for (const rental of ownerRentals) {
try {
const response = await conditionCheckAPI.getConditionChecks(
rental.id
);
if (response.data.conditionChecks) {
allChecks.push(...response.data.conditionChecks);
}
} catch (err) {
// Skip rentals with no condition checks
}
}
setConditionChecks(allChecks);
} catch (err) {
console.error("Failed to fetch condition checks:", err);
setConditionChecks([]);
}
};
// Owner functionality handlers
const handleAcceptRental = async (rentalId: string) => {
try {
@@ -252,7 +286,12 @@ const Owning: React.FC = () => {
const handleConditionCheckSuccess = () => {
fetchAvailableChecks();
alert("Condition check submitted successfully!");
fetchConditionChecks();
};
const handleViewConditionCheck = (check: ConditionCheck) => {
setSelectedConditionCheck(check);
setShowConditionCheckViewer(true);
};
const getAvailableChecksForRental = (rentalId: string) => {
@@ -263,6 +302,11 @@ const Owning: React.FC = () => {
);
};
const getCompletedChecksForRental = (rentalId: string) => {
if (!Array.isArray(conditionChecks)) return [];
return conditionChecks.filter((check) => check.rentalId === rentalId);
};
// Filter owner rentals - exclude cancelled (shown in Rental History)
const allOwnerRentals = ownerRentals
.filter((r) => ["pending", "confirmed", "active"].includes(r.status))
@@ -307,14 +351,19 @@ const Owning: React.FC = () => {
{allOwnerRentals.map((rental) => (
<div key={rental.id} className="col-md-6 col-lg-4 mb-4">
<div className="card h-100">
{rental.item?.imageFilenames && rental.item.imageFilenames[0] && (
<img
src={getPublicImageUrl(rental.item.imageFilenames[0])}
className="card-img-top"
alt={rental.item.name}
style={{ height: "200px", objectFit: "contain", backgroundColor: "#f8f9fa" }}
/>
)}
{rental.item?.imageFilenames &&
rental.item.imageFilenames[0] && (
<img
src={getPublicImageUrl(rental.item.imageFilenames[0])}
className="card-img-top"
alt={rental.item.name}
style={{
height: "200px",
objectFit: "contain",
backgroundColor: "#f8f9fa",
}}
/>
)}
<div className="card-body">
<h5 className="card-title text-dark">
{rental.item ? rental.item.name : "Item Unavailable"}
@@ -472,6 +521,34 @@ const Owning: React.FC = () => {
)}
</div>
{/* Condition Check Status */}
{getCompletedChecksForRental(rental.id).length > 0 && (
<div className="mb-2">
{getCompletedChecksForRental(rental.id).map(
(check) => (
<button
key={`${rental.id}-${check.checkType}-status`}
className="btn btn-link text-success small p-0 text-decoration-none d-block"
onClick={() => handleViewConditionCheck(check)}
>
{check.checkType === "pre_rental_owner"
? "Pre-Rental Condition"
: check.checkType === "rental_start_renter"
? "Rental Start Condition"
: check.checkType === "rental_end_renter"
? "Rental End Condition"
: "Post-Rental Condition"}
<small className="text-muted ms-2">
{new Date(
check.createdAt
).toLocaleDateString()}
</small>
</button>
)
)}
</div>
)}
{/* Condition Check Buttons */}
{getAvailableChecksForRental(rental.id).map((check) => (
<button
@@ -483,8 +560,8 @@ const Owning: React.FC = () => {
>
<i className="bi bi-camera me-2" />
{check.checkType === "pre_rental_owner"
? "Submit Pre-Rental Check"
: "Submit Post-Rental Check"}
? "Submit Pre-Rental Condition"
: "Submit Post-Rental Condition"}
</button>
))}
</div>
@@ -533,7 +610,11 @@ const Owning: React.FC = () => {
src={getPublicImageUrl(item.imageFilenames[0])}
className="card-img-top"
alt={item.name}
style={{ height: "200px", objectFit: "contain", backgroundColor: "#f8f9fa" }}
style={{
height: "200px",
objectFit: "contain",
backgroundColor: "#f8f9fa",
}}
/>
)}
<div className="card-body">
@@ -712,6 +793,16 @@ const Owning: React.FC = () => {
onSubmitSuccess={handleReturnStatusMarked}
/>
)}
{/* Condition Check Viewer Modal */}
<ConditionCheckViewerModal
show={showConditionCheckViewer}
onHide={() => {
setShowConditionCheckViewer(false);
setSelectedConditionCheck(null);
}}
conditionCheck={selectedConditionCheck}
/>
</div>
);
};