ActivityCard.jsx 4.55 KB
import React from 'react';
import { Link } from 'react-router-dom';
import FrostedGlass from './FrostedGlass';

/**
 * ActivityCard component displays an activity item in the activities list
 * 
 * @param {Object} props - Component props
 * @param {Object} props.activity - Activity data
 * @returns {JSX.Element} ActivityCard component
 */
const ActivityCard = ({ activity }) => {
  // Function to get the appropriate status class
  const getStatusClass = (status) => {
    switch (status) {
      case '活动中':
        return 'bg-blue-100 text-blue-600';
      case '进行中':
        return 'bg-green-100 text-green-600';
      case '即将开始':
        return 'bg-orange-100 text-orange-600';
      case '已结束':
        return 'bg-gray-100 text-gray-600';
      default:
        return 'bg-gray-100 text-gray-600';
    }
  };
  
  return (
    <Link to={`/activities/${activity.id}`}>
      <FrostedGlass className="flex overflow-hidden rounded-xl shadow-sm">
        {/* Activity Image */}
        <div className="w-1/3 h-28 relative">
          <img
            src={activity.imageUrl}
            alt={activity.title}
            className="w-full h-full object-cover"
          />
          {activity.isHot && (
            <div className="absolute top-0 left-0 bg-red-500 text-white text-xs px-2 py-0.5">
              热门
            </div>
          )}
        </div>
        
        {/* Activity Info */}
        <div className="flex-1 p-3 flex flex-col justify-between">
          <div>
            <h3 className="font-medium text-base mb-1 line-clamp-1">{activity.title}</h3>
            
            {/* Status Tags */}
            <div className="flex items-center space-x-2 mb-1">
              <span className={`px-2 py-0.5 rounded-full text-xs ${getStatusClass(activity.status)}`}>
                {activity.status}
              </span>
              {activity.isFree && (
                <span className="px-2 py-0.5 rounded-full text-xs bg-green-100 text-green-600">
                  免费
                </span>
              )}
            </div>
          </div>
          
          {/* Location and Time */}
          <div className="text-xs text-gray-500 space-y-1">
            <div className="flex items-center">
              <svg xmlns="http://www.w3.org/2000/svg" className="h-3.5 w-3.5 mr-1" fill="none" viewBox="0 0 24 24" stroke="currentColor">
                <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M17.657 16.657L13.414 20.9a1.998 1.998 0 01-2.827 0l-4.244-4.243a8 8 0 1111.314 0z" />
                <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M15 11a3 3 0 11-6 0 3 3 0 016 0z" />
              </svg>
              <span>{activity.location}</span>
            </div>
            
            <div className="flex items-center">
              <svg xmlns="http://www.w3.org/2000/svg" className="h-3.5 w-3.5 mr-1" fill="none" viewBox="0 0 24 24" stroke="currentColor">
                <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M8 7V3m8 4V3m-9 8h10M5 21h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z" />
              </svg>
              <span>{activity.period}</span>
            </div>
          </div>
          
          {/* Bottom Info Section */}
          <div className="mt-1 flex items-center justify-between">
            {activity.price ? (
              <div className="flex items-baseline">
                <span className="text-red-500 font-medium">¥{activity.price}</span>
                {activity.originalPrice && (
                  <span className="text-xs text-gray-400 ml-1 line-through">¥{activity.originalPrice}</span>
                )}
              </div>
            ) : (
              <div></div> // Empty div for spacing when no price
            )}
            
            <div className="flex items-center text-xs text-gray-500">
              <svg xmlns="http://www.w3.org/2000/svg" className="h-3.5 w-3.5 mr-1" fill="none" viewBox="0 0 24 24" stroke="currentColor">
                <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M17 20h5v-2a3 3 0 00-5.356-1.857M17 20H7m10 0v-2c0-.656-.126-1.283-.356-1.857M7 20H2v-2a3 3 0 015.356-1.857M7 20v-2c0-.656.126-1.283.356-1.857m0 0a5.002 5.002 0 019.288 0M15 7a3 3 0 11-6 0 3 3 0 016 0zm6 3a2 2 0 11-4 0 2 2 0 014 0zM7 10a2 2 0 11-4 0 2 2 0 014 0z" />
              </svg>
              <span>{activity.participantsCount || '15'}/{activity.maxParticipants || '30'}</span>
            </div>
          </div>
        </div>
      </FrostedGlass>
    </Link>
  );
};

export default ActivityCard;