Compare commits
3 Commits
72c5943c57
...
b773f30e0d
| Author | SHA1 | Date | |
|---|---|---|---|
| b773f30e0d | |||
| 47642d4903 | |||
| 6824c7248b |
@@ -1,13 +1,16 @@
|
|||||||
|
|
||||||
import React from 'react';
|
import React, { useState } from 'react';
|
||||||
import { motion } from 'framer-motion';
|
import { motion } from 'framer-motion';
|
||||||
import { CalendarOutlined, RightOutlined } from '@ant-design/icons';
|
import { CalendarOutlined } from '@ant-design/icons';
|
||||||
import { useNavigate } from 'react-router-dom';
|
import { useNavigate } from 'react-router-dom';
|
||||||
import styles from './activity.module.less';
|
import styles from './activity.module.less';
|
||||||
import { hoverScale, imageFadeIn } from '../../animation';
|
import { hoverScale } from '../../animation';
|
||||||
|
|
||||||
const ActivityCard = ({ activity, index }) => {
|
//
|
||||||
|
const ActivityCard = ({ activity }) => {
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
const [isLoaded, setIsLoaded] = useState(false);
|
||||||
|
const [hasError, setHasError] = useState(false);
|
||||||
|
|
||||||
const handleCardClick = () => {
|
const handleCardClick = () => {
|
||||||
navigate(`/activity/${activity.id}`);
|
navigate(`/activity/${activity.id}`);
|
||||||
@@ -17,7 +20,6 @@ const ActivityCard = ({ activity, index }) => {
|
|||||||
const now = new Date();
|
const now = new Date();
|
||||||
const start = new Date(startTime);
|
const start = new Date(startTime);
|
||||||
if (now < start) return '即将开始';
|
if (now < start) return '即将开始';
|
||||||
// Simple logic, can be enhanced
|
|
||||||
return '报名中';
|
return '报名中';
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -27,6 +29,10 @@ const ActivityCard = ({ activity, index }) => {
|
|||||||
return date.toLocaleDateString('zh-CN', { month: 'long', day: 'numeric' });
|
return date.toLocaleDateString('zh-CN', { month: 'long', day: 'numeric' });
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const imgSrc = hasError
|
||||||
|
? 'https://via.placeholder.com/600x400?text=No+Image'
|
||||||
|
: (activity.display_banner_url || activity.banner_url || activity.cover_image || 'https://via.placeholder.com/600x400');
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<motion.div
|
<motion.div
|
||||||
className={styles.activityCard}
|
className={styles.activityCard}
|
||||||
@@ -37,13 +43,31 @@ const ActivityCard = ({ activity, index }) => {
|
|||||||
style={{ willChange: 'transform' }}
|
style={{ willChange: 'transform' }}
|
||||||
>
|
>
|
||||||
<div className={styles.imageContainer}>
|
<div className={styles.imageContainer}>
|
||||||
|
{/* Placeholder / Skeleton Background */}
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
position: 'absolute',
|
||||||
|
top: 0,
|
||||||
|
left: 0,
|
||||||
|
width: '100%',
|
||||||
|
height: '100%',
|
||||||
|
backgroundColor: '#f0f0f0',
|
||||||
|
opacity: isLoaded ? 0 : 1,
|
||||||
|
transition: 'opacity 0.5s ease'
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
|
||||||
<motion.img
|
<motion.img
|
||||||
src={activity.display_banner_url || activity.banner_url || activity.cover_image || 'https://via.placeholder.com/600x400'}
|
src={imgSrc}
|
||||||
alt={activity.title}
|
alt={activity.title}
|
||||||
variants={imageFadeIn}
|
initial={{ opacity: 0 }}
|
||||||
initial="hidden"
|
animate={{ opacity: isLoaded ? 1 : 0 }}
|
||||||
whileInView="visible"
|
transition={{ duration: 0.5 }}
|
||||||
viewport={{ once: true }}
|
onLoad={() => setIsLoaded(true)}
|
||||||
|
onError={() => {
|
||||||
|
setHasError(true);
|
||||||
|
setIsLoaded(true); // Show placeholder image
|
||||||
|
}}
|
||||||
loading="lazy"
|
loading="lazy"
|
||||||
/>
|
/>
|
||||||
<div className={styles.overlay}>
|
<div className={styles.overlay}>
|
||||||
|
|||||||
Reference in New Issue
Block a user