reviews and review history
This commit is contained in:
229
frontend/src/components/ReviewDetailsModal.tsx
Normal file
229
frontend/src/components/ReviewDetailsModal.tsx
Normal 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;
|
||||
Reference in New Issue
Block a user