replaced vague notes with specific intended use, also fixed modal on top of modal for reviews

This commit is contained in:
jackiettran
2025-11-25 16:40:42 -05:00
parent 13268784fd
commit 8de814fdee
16 changed files with 282 additions and 85 deletions

View File

@@ -24,7 +24,6 @@ const ReturnStatusModal: React.FC<ReturnStatusModalProps> = ({
lost: false,
});
const [actualReturnDateTime, setActualReturnDateTime] = useState("");
const [notes, setNotes] = useState("");
const [conditionNotes, setConditionNotes] = useState("");
const [photos, setPhotos] = useState<File[]>([]);
const [processing, setProcessing] = useState(false);
@@ -56,7 +55,6 @@ const ReturnStatusModal: React.FC<ReturnStatusModalProps> = ({
lost: false,
});
setActualReturnDateTime("");
setNotes("");
setConditionNotes("");
setPhotos([]);
setError(null);
@@ -71,13 +69,13 @@ const ReturnStatusModal: React.FC<ReturnStatusModalProps> = ({
// Create blob URLs for photo previews and clean them up
const photoBlobUrls = useMemo(() => {
return photos.map(photo => URL.createObjectURL(photo));
return photos.map((photo) => URL.createObjectURL(photo));
}, [photos]);
// Cleanup blob URLs when photos change or component unmounts
useEffect(() => {
return () => {
photoBlobUrls.forEach(url => URL.revokeObjectURL(url));
photoBlobUrls.forEach((url) => URL.revokeObjectURL(url));
};
}, [photoBlobUrls]);
@@ -202,6 +200,7 @@ const ReturnStatusModal: React.FC<ReturnStatusModalProps> = ({
);
if (!hasSelection) {
setError("Please select at least one return status option");
setProcessing(false);
return;
}
@@ -316,7 +315,6 @@ const ReturnStatusModal: React.FC<ReturnStatusModalProps> = ({
const data: any = {
status: primaryStatus,
statusOptions, // Send all selected options
notes: notes.trim() || undefined,
};
if (statusOptions.returned_late) {
@@ -346,7 +344,6 @@ const ReturnStatusModal: React.FC<ReturnStatusModalProps> = ({
lost: false,
});
setActualReturnDateTime("");
setNotes("");
setConditionNotes("");
setPhotos([]);
setError(null);
@@ -950,7 +947,7 @@ const ReturnStatusModal: React.FC<ReturnStatusModalProps> = ({
>
<span className="visually-hidden">Loading...</span>
</div>
Processing...
Submitting...
</>
) : (
"Submit"

View File

@@ -69,6 +69,18 @@ const ReviewItemModal: React.FC<ReviewItemModalProps> = ({
if (!show) return null;
// Show success modal instead of review modal after successful submission
if (showSuccessModal) {
return (
<SuccessModal
show={true}
onClose={handleSuccessModalClose}
title="Thank you for your review!"
message={successMessage}
/>
);
}
return (
<div
className="modal d-block"
@@ -212,13 +224,6 @@ const ReviewItemModal: React.FC<ReviewItemModalProps> = ({
</form>
</div>
</div>
<SuccessModal
show={showSuccessModal}
onClose={handleSuccessModalClose}
title="Thank you for your review!"
message={successMessage}
/>
</div>
);
};

View File

@@ -69,6 +69,18 @@ const ReviewRenterModal: React.FC<ReviewRenterModalProps> = ({
if (!show) return null;
// Show success modal instead of review modal after successful submission
if (showSuccessModal) {
return (
<SuccessModal
show={true}
onClose={handleSuccessModalClose}
title="Thank you for your review!"
message={successMessage}
/>
);
}
return (
<div
className="modal d-block"
@@ -212,13 +224,6 @@ const ReviewRenterModal: React.FC<ReviewRenterModalProps> = ({
</form>
</div>
</div>
<SuccessModal
show={showSuccessModal}
onClose={handleSuccessModalClose}
title="Thank you for your review!"
message={successMessage}
/>
</div>
);
};

View File

@@ -359,6 +359,14 @@ const Owning: React.FC = () => {
<strong>Total:</strong> ${rental.totalAmount}
</p>
{rental.intendedUse && rental.status === "pending" && (
<div className="alert alert-light mt-2 mb-2 p-2 small">
<strong>Intended Use:</strong>
<br />
{rental.intendedUse}
</div>
)}
{rental.status === "cancelled" &&
rental.refundAmount !== undefined && (
<div className="alert alert-info mt-2 mb-2 p-2 small">
@@ -620,9 +628,7 @@ const Owning: React.FC = () => {
onClick={() => toggleAvailability(item)}
className="btn btn-sm btn-outline-info"
>
{item.isAvailable
? "Mark Unavailable"
: "Mark Available"}
{item.isAvailable ? "Mark Unavailable" : "Mark Available"}
</button>
<button
onClick={() => handleDelete(item.id)}

View File

@@ -17,6 +17,7 @@ const RentItem: React.FC = () => {
const [formData, setFormData] = useState({
deliveryMethod: "pickup" as "pickup" | "delivery",
deliveryAddress: "",
intendedUse: "",
});
const [manualSelection, setManualSelection] = useState({
@@ -143,6 +144,7 @@ const RentItem: React.FC = () => {
endDateTime,
deliveryMethod: formData.deliveryMethod,
deliveryAddress: formData.deliveryAddress,
intendedUse: formData.intendedUse || undefined,
totalAmount: totalCost,
};
} catch (error: any) {
@@ -261,6 +263,26 @@ const RentItem: React.FC = () => {
</p>
)}
<div className="mb-3">
<label htmlFor="intendedUse" className="form-label">
What will you use this for?{" "}
<span className="text-muted">(Optional)</span>
</label>
<textarea
id="intendedUse"
name="intendedUse"
className="form-control"
rows={3}
value={formData.intendedUse}
onChange={handleChange}
placeholder="Let the owner know how you plan to use their item..."
maxLength={500}
/>
<div className="form-text">
{formData.intendedUse.length}/500 characters
</div>
</div>
{!manualSelection.startDate ||
!manualSelection.endDate ||
!getRentalData() ? (

View File

@@ -232,7 +232,7 @@ export const rentalAPI = {
// Return status marking
markReturn: (
id: string,
data: { status: string; actualReturnDateTime?: string; notes?: string }
data: { status: string; actualReturnDateTime?: string }
) => api.post(`/rentals/${id}/mark-return`, data),
reportDamage: (id: string, data: any) =>
api.post(`/rentals/${id}/report-damage`, data),

View File

@@ -152,7 +152,7 @@ export interface Rental {
stripeTransferId?: string;
deliveryMethod: "pickup" | "delivery";
deliveryAddress?: string;
notes?: string;
intendedUse?: string;
rating?: number;
review?: string;
declineReason?: string;