fromis_9/frontend/src/pages/pc/Schedule.jsx

127 lines
6.1 KiB
React
Raw Normal View History

import { motion } from 'framer-motion';
import { Calendar, Clock, MapPin, Users } from 'lucide-react';
import { schedules } from '../../data/dummy';
function Schedule() {
// 스케줄을 날짜별로 그룹핑
const groupedSchedules = schedules.reduce((acc, schedule) => {
const date = schedule.date;
if (!acc[date]) {
acc[date] = [];
}
acc[date].push(schedule);
return acc;
}, {});
const formatDate = (dateStr) => {
const date = new Date(dateStr);
const days = ['일', '월', '화', '수', '목', '금', '토'];
return {
month: date.getMonth() + 1,
day: date.getDate(),
weekday: days[date.getDay()],
};
};
return (
<div className="py-16">
<div className="max-w-7xl mx-auto px-6">
{/* 헤더 */}
<div className="text-center mb-12">
<motion.h1
initial={{ opacity: 0, y: -20 }}
animate={{ opacity: 1, y: 0 }}
className="text-4xl font-bold mb-4"
>
스케줄
</motion.h1>
<motion.p
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
transition={{ delay: 0.2 }}
className="text-gray-500"
>
프로미스나인의 다가오는 일정을 확인하세요
</motion.p>
</div>
{/* 스케줄 타임라인 */}
<div className="max-w-4xl mx-auto">
{Object.entries(groupedSchedules).map(([date, daySchedules], groupIndex) => {
const formatted = formatDate(date);
return (
<motion.div
key={date}
initial={{ opacity: 0, x: -30 }}
animate={{ opacity: 1, x: 0 }}
transition={{ delay: groupIndex * 0.1 }}
className="relative pl-24 pb-12 last:pb-0"
>
{/* 타임라인 라인 */}
<div className="absolute left-[44px] top-0 bottom-0 w-0.5 bg-gray-200" />
{/* 날짜 원 */}
<div className="absolute left-0 top-0 w-[88px] flex items-start">
<div className="w-12 h-12 rounded-full bg-primary text-white flex flex-col items-center justify-center text-sm font-bold">
<span className="text-xs">{formatted.month}</span>
<span>{formatted.day}</span>
</div>
<span className="ml-2 mt-3 text-sm text-gray-400">{formatted.weekday}</span>
</div>
{/* 스케줄 카드들 */}
<div className="space-y-4">
{daySchedules.map((schedule, index) => (
<div
key={schedule.id}
className="bg-white rounded-2xl p-6 shadow-md hover:shadow-lg transition-shadow"
>
<h3 className="font-bold text-lg mb-3">{schedule.title}</h3>
<div className="flex flex-wrap gap-4 text-sm text-gray-500">
<div className="flex items-center gap-1">
<Clock size={14} className="text-primary" />
<span>{schedule.time}</span>
</div>
<div className="flex items-center gap-1">
<MapPin size={14} className="text-primary" />
<span>{schedule.platform}</span>
</div>
<div className="flex items-center gap-1">
<Users size={14} className="text-primary" />
<span>{schedule.members.join(', ')}</span>
</div>
</div>
</div>
))}
</div>
</motion.div>
);
})}
</div>
{/* 빈 스케줄 메시지 (스케줄이 없을 때) */}
{Object.keys(groupedSchedules).length === 0 && (
<div className="text-center py-20">
<Calendar size={64} className="mx-auto text-gray-300 mb-4" />
<p className="text-gray-500">예정된 스케줄이 없습니다.</p>
</div>
)}
{/* 안내 */}
<motion.div
initial={{ opacity: 0, y: 30 }}
animate={{ opacity: 1, y: 0 }}
transition={{ delay: 0.5 }}
className="mt-12 bg-gray-50 rounded-2xl p-6 text-center text-sm text-gray-500"
>
<p>스케줄은 DC Inside 갤러리에서 자동으로 수집됩니다.</p>
<p className="mt-1">일정은 변경될 있으니 공식 채널을 확인해 주세요.</p>
</motion.div>
</div>
</div>
);
}
export default Schedule;