reviews and review history

This commit is contained in:
jackiettran
2025-08-25 16:12:30 -04:00
parent 5d85f77a19
commit 601e11b7e8
7 changed files with 864 additions and 274 deletions

View File

@@ -0,0 +1,229 @@
import React from "react";
import { Rental } from "../types";
import StarRating from "./StarRating";
interface ReviewDetailsModalProps {
show: boolean;
onClose: () => void;
rental: Rental;
userType: "renter" | "owner";
}
const ReviewDetailsModal: React.FC<ReviewDetailsModalProps> = ({
show,
onClose,
rental,
userType,
}) => {
if (!show) return null;
const formatDateTime = (dateString: string, timeString?: string) => {
const date = new Date(dateString).toLocaleDateString();
const formattedTime = timeString
? (() => {
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 {
return "";
}
})()
: "";
return formattedTime ? `${date} at ${formattedTime}` : date;
};
const isRenter = userType === "renter";
return (
<div
className="modal d-block"
tabIndex={-1}
style={{ backgroundColor: "rgba(0,0,0,0.5)" }}
>
<div className="modal-dialog modal-dialog-centered modal-lg">
<div className="modal-content">
<div className="modal-header">
<h5 className="modal-title">Review Details</h5>
<button
type="button"
className="btn-close"
onClick={onClose}
></button>
</div>
<div className="modal-body">
{/* Header with user info */}
{rental.item && (
<div className="mb-4 text-center">
<h6 className="mb-1">{rental.item.name}</h6>
<small className="text-muted">
{formatDateTime(rental.startDate, rental.startTime)} to{" "}
{formatDateTime(rental.endDate, rental.endTime)}
</small>
</div>
)}
{/* What I Sent Section */}
{((isRenter &&
(rental.itemPrivateMessage ||
rental.itemReview ||
rental.itemRating)) ||
(!isRenter &&
(rental.renterPrivateMessage ||
rental.renterReview ||
rental.renterRating))) && (
<div className="mb-4">
<h6 className="text-primary mb-3">
<i className="bi bi-arrow-up-right-circle me-2"></i>
What I Sent
</h6>
{/* My Private Message */}
{((isRenter && rental.itemPrivateMessage) ||
(!isRenter && rental.renterPrivateMessage)) && (
<div className="mb-3">
<small className="text-muted fw-bold">
Private Note to {isRenter ? "Owner" : "Renter"}:
</small>
<div className="border rounded p-2 mt-1">
{isRenter
? rental.itemPrivateMessage
: rental.renterPrivateMessage}
</div>
</div>
)}
{/* My Public Review */}
{((isRenter && (rental.itemReview || rental.itemRating)) ||
(!isRenter &&
(rental.renterReview || rental.renterRating))) && (
<div className="mb-3">
<small className="text-muted fw-bold">
Public Review of {isRenter ? "Item" : "Renter"}:
</small>
<div className="border rounded p-2 mt-1">
{((isRenter && rental.itemRating) ||
(!isRenter && rental.renterRating)) && (
<div className="d-flex align-items-center mb-2">
<StarRating
rating={
isRenter
? rental.itemRating!
: rental.renterRating!
}
size="small"
/>
</div>
)}
{((isRenter && rental.itemReview) ||
(!isRenter && rental.renterReview)) && (
<p className="small mb-0">
{isRenter ? rental.itemReview : rental.renterReview}
</p>
)}
</div>
</div>
)}
</div>
)}
{/* What I Received Section */}
{((isRenter &&
(rental.renterPrivateMessage ||
rental.renterReview ||
rental.renterRating)) ||
(!isRenter &&
(rental.itemPrivateMessage ||
rental.itemReview ||
rental.itemRating))) && (
<div className="mb-4">
<h6 className="text-success mb-3">
<i className="bi bi-arrow-down-left-circle me-2"></i>
What I Received
</h6>
{/* Their Private Message */}
{((isRenter && rental.renterPrivateMessage) ||
(!isRenter && rental.itemPrivateMessage)) && (
<div className="mb-3">
<small className="text-muted fw-bold">
Private Note from {isRenter ? "Owner" : "Renter"}:
</small>
<div className="border rounded p-2 mt-1">
{isRenter
? rental.renterPrivateMessage
: rental.itemPrivateMessage}
</div>
</div>
)}
{/* Their Public Review */}
{((isRenter && (rental.renterReview || rental.renterRating)) ||
(!isRenter && (rental.itemReview || rental.itemRating))) && (
<div className="mb-3">
<small className="text-muted fw-bold">
{isRenter
? "Owner's Review of Me:"
: "Renter's Review of Item:"}
</small>
<div className="border rounded p-2 mt-1">
{((isRenter && rental.renterRating) ||
(!isRenter && rental.itemRating)) && (
<div className="d-flex align-items-center mb-2">
<StarRating
rating={
isRenter
? rental.renterRating!
: rental.itemRating!
}
size="small"
/>
</div>
)}
{((isRenter && rental.renterReview) ||
(!isRenter && rental.itemReview)) && (
<p className="small mb-0">
{isRenter ? rental.renterReview : rental.itemReview}
</p>
)}
</div>
</div>
)}
</div>
)}
{/* Empty state */}
{!rental.itemPrivateMessage &&
!rental.renterPrivateMessage &&
!rental.itemReview &&
!rental.renterReview &&
!rental.itemRating &&
!rental.renterRating && (
<div className="text-center text-muted py-4">
<i
className="bi bi-chat-text mb-3"
style={{ fontSize: "2rem" }}
></i>
<p>No review details available.</p>
</div>
)}
</div>
<div className="modal-footer">
<button
type="button"
className="btn btn-secondary"
onClick={onClose}
>
Close
</button>
</div>
</div>
</div>
</div>
);
};
export default ReviewDetailsModal;