All files / components/Property PropertyCard.tsx

100% Statements 9/9
100% Branches 14/14
100% Functions 3/3
100% Lines 9/9

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118                          1x 4x 4x   4x 1x     4x 1x 1x     4x                                                                                                                                                                                      
import React from 'react';
import { FC, MouseEvent } from 'react';
import { Property } from '../../types/property';
import { useNavigate } from 'react-router-dom';
import { ROUTES } from '../../config/routes';
import { FaBed, FaBath, FaRulerCombined, FaHome } from 'react-icons/fa';
import { getFullImageUrl } from '../../config/api';
import { useAuth } from '../../context/AuthContext';
 
interface PropertyCardProps {
    property: Property;
}
 
const PropertyCard: FC<PropertyCardProps> = ({ property }) => {
    const navigate = useNavigate();
    const { isAdmin } = useAuth();
 
    const handleViewDetails = () => {
        navigate(ROUTES.PROPERTIES.DETAILS(property.id!));
    };
 
    const handleEdit = (e: MouseEvent) => {
        e.stopPropagation();
        navigate(ROUTES.PROPERTIES.EDIT(property.id!));
    };
 
    return (
        <div 
            onClick={handleViewDetails}
            data-testid="property-card"
            className="bg-white rounded-xl overflow-hidden shadow-none border-2 border-[#e5e5e5] hover:border-[#00deb6] transition-colors duration-300 cursor-pointer flex flex-col h-[500px]"
        >
            {/* Image Section */}
            <div className="relative h-48 bg-gray-200 flex-shrink-0">
                {property.images && property.images.length > 0 ? (
                    <img
                        src={getFullImageUrl(property.images[0].url)}
                        alt={property.address}
                        className="w-full h-full object-cover rounded-t-xl"
                    />
                ) : (
                    <div data-testid="property-placeholder" className="flex items-center justify-center h-full bg-gray-200 rounded-t-xl">
                        <FaHome className="text-4xl text-gray-400" />
                    </div>
                )}
                {isAdmin && (
                    <div className="absolute top-4 right-4">
                        <button
                            onClick={handleEdit}
                            className="bg-white text-[#262637] px-4 py-2 rounded-full text-sm font-medium border-2 border-[#e5e5e5] hover:border-[#00deb6] transition-colors duration-200"
                        >
                            Edit
                        </button>
                    </div>
                )}
            </div>
 
            {/* Content Section */}
            <div className="p-4 flex flex-col flex-grow">
                <div className="mb-2">
                    <h3 className="text-xl font-bold text-[#262637] mb-2 line-clamp-1">{property.address}</h3>
                    <p className="text-2xl font-bold text-[#00deb6]">
                        £{property.price.toLocaleString()}
                    </p>
                </div>
 
                {/* Property Features */}
                <div className="grid grid-cols-3 gap-4 py-4 border-t border-gray-100">
                    <div className="text-center">
                        {property.bedrooms && (
                            <div className="flex items-center justify-center text-[#666666]">
                                <FaBed className="mr-1" />
                                <span>{property.bedrooms}</span>
                            </div>
                        )}
                    </div>
                    <div className="text-center">
                        {property.bathrooms && (
                            <div className="flex items-center justify-center text-[#666666]">
                                <FaBath className="mr-1" />
                                <span>{property.bathrooms}</span>
                            </div>
                        )}
                    </div>
                    <div className="text-center">
                        {property.squareFootage && (
                            <div className="flex items-center justify-center text-[#666666]">
                                <FaRulerCombined className="mr-1" />
                                <span>{property.squareFootage.toLocaleString()}</span>
                            </div>
                        )}
                    </div>
                </div>
 
                {/* Description Preview */}
                {property.description && (
                    <div className="mt-4 border-t border-gray-100 pt-4 flex-grow">
                        <p className="text-[#666666] text-sm line-clamp-2">
                            {property.description}
                        </p>
                    </div>
                )}
 
                {/* View Details Button */}
                <div className="mt-auto pt-4">
                    <button
                        onClick={handleViewDetails}
                        className="w-full bg-[#00deb6] text-white px-4 py-2 rounded-xl hover:bg-[#00c5a0] transition-colors duration-200"
                    >
                        View Details
                    </button>
                </div>
            </div>
        </div>
    );
};
 
export default PropertyCard;