getting to payment screen. Bug fixes and formatting changes for item detail
This commit is contained in:
81
frontend/src/components/ItemCard.tsx
Normal file
81
frontend/src/components/ItemCard.tsx
Normal file
@@ -0,0 +1,81 @@
|
||||
import React from 'react';
|
||||
import { Link } from 'react-router-dom';
|
||||
import { Item } from '../types';
|
||||
|
||||
interface ItemCardProps {
|
||||
item: Item;
|
||||
variant?: 'compact' | 'standard';
|
||||
}
|
||||
|
||||
const ItemCard: React.FC<ItemCardProps> = ({
|
||||
item,
|
||||
variant = 'standard'
|
||||
}) => {
|
||||
const isCompact = variant === 'compact';
|
||||
|
||||
const getPriceDisplay = () => {
|
||||
if (item.pricePerDay !== undefined) {
|
||||
return Number(item.pricePerDay) === 0
|
||||
? "Free to Borrow"
|
||||
: `$${Math.floor(Number(item.pricePerDay))}/Day`;
|
||||
} else if (item.pricePerHour !== undefined) {
|
||||
return Number(item.pricePerHour) === 0
|
||||
? "Free to Borrow"
|
||||
: `$${Math.floor(Number(item.pricePerHour))}/Hour`;
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
const getLocationDisplay = () => {
|
||||
return item.city && item.state
|
||||
? `${item.city}, ${item.state}`
|
||||
: item.location;
|
||||
};
|
||||
|
||||
return (
|
||||
<Link to={`/items/${item.id}`} className="text-decoration-none">
|
||||
<div className="card h-100" style={{ cursor: 'pointer' }}>
|
||||
{item.images && item.images[0] ? (
|
||||
<img
|
||||
src={item.images[0]}
|
||||
className="card-img-top"
|
||||
alt={item.name}
|
||||
style={{
|
||||
height: isCompact ? '150px' : '200px',
|
||||
objectFit: 'cover'
|
||||
}}
|
||||
/>
|
||||
) : (
|
||||
<div
|
||||
className="card-img-top bg-light d-flex align-items-center justify-content-center"
|
||||
style={{ height: isCompact ? '150px' : '200px' }}
|
||||
>
|
||||
<i className="bi bi-image text-muted" style={{ fontSize: '2rem' }}></i>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div className={`card-body ${isCompact ? 'p-2' : ''}`}>
|
||||
{isCompact ? (
|
||||
<h6 className="card-title text-truncate mb-1 text-dark">{item.name}</h6>
|
||||
) : (
|
||||
<h5 className="card-title text-dark">{item.name}</h5>
|
||||
)}
|
||||
|
||||
<div className={isCompact ? "mb-1" : "mb-3"}>
|
||||
<div className="text-primary">
|
||||
<strong className={isCompact ? "small" : ""}>
|
||||
{getPriceDisplay()}
|
||||
</strong>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className={`text-muted small ${isCompact ? 'mb-1' : 'mb-2'}`}>
|
||||
<i className="bi bi-geo-alt"></i> {getLocationDisplay()}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Link>
|
||||
);
|
||||
};
|
||||
|
||||
export default ItemCard;
|
||||
@@ -1,6 +1,6 @@
|
||||
import React, { useState, useEffect } from "react";
|
||||
import { Rental } from "../types";
|
||||
import { rentalAPI } from "../services/api";
|
||||
import { itemAPI } from "../services/api";
|
||||
|
||||
interface ItemReviewsProps {
|
||||
itemId: string;
|
||||
@@ -17,26 +17,11 @@ const ItemReviews: React.FC<ItemReviewsProps> = ({ itemId }) => {
|
||||
|
||||
const fetchReviews = async () => {
|
||||
try {
|
||||
// Fetch all rentals for this item
|
||||
const response = await rentalAPI.getMyListings();
|
||||
const allRentals: Rental[] = response.data;
|
||||
|
||||
// Filter for completed rentals with reviews for this specific item
|
||||
const itemReviews = allRentals.filter(
|
||||
(rental) =>
|
||||
rental.itemId === itemId &&
|
||||
rental.status === "completed" &&
|
||||
rental.rating &&
|
||||
rental.review
|
||||
);
|
||||
|
||||
setReviews(itemReviews);
|
||||
|
||||
// Calculate average rating
|
||||
if (itemReviews.length > 0) {
|
||||
const sum = itemReviews.reduce((acc, r) => acc + (r.rating || 0), 0);
|
||||
setAverageRating(sum / itemReviews.length);
|
||||
}
|
||||
const response = await itemAPI.getItemReviews(itemId);
|
||||
const { reviews, averageRating } = response.data;
|
||||
|
||||
setReviews(reviews);
|
||||
setAverageRating(averageRating);
|
||||
} catch (error) {
|
||||
console.error("Failed to fetch reviews:", error);
|
||||
} finally {
|
||||
|
||||
Reference in New Issue
Block a user