fromis_9/frontend/src/pages/mobile/public/ScheduleDetail.jsx

120 lines
5 KiB
React
Raw Normal View History

import { useParams, Link } from 'react-router-dom';
import { useQuery } from '@tanstack/react-query';
import { motion } from 'framer-motion';
import { Calendar, ChevronLeft } from 'lucide-react';
import { getSchedule } from '../../../api/public/schedules';
function MobileScheduleDetail() {
const { id } = useParams();
const { data: schedule, isLoading, error } = useQuery({
queryKey: ['schedule', id],
queryFn: () => getSchedule(id),
retry: false,
});
if (isLoading) {
return (
<div className="min-h-screen flex items-center justify-center bg-gray-50">
<div className="w-8 h-8 border-2 border-primary border-t-transparent rounded-full animate-spin" />
</div>
);
}
if (error || !schedule) {
return (
<div className="min-h-screen flex items-center justify-center bg-gradient-to-br from-gray-50 to-gray-100 px-6">
<div className="text-center">
{/* 아이콘 */}
<motion.div
initial={{ opacity: 0, scale: 0.5 }}
animate={{ opacity: 1, scale: 1 }}
transition={{ duration: 0.5, type: "spring", stiffness: 100 }}
className="mb-6"
>
<div className="w-24 h-24 mx-auto bg-gradient-to-br from-primary/10 to-primary/5 rounded-2xl flex items-center justify-center">
<Calendar size={48} className="text-primary/40" />
</div>
</motion.div>
{/* 메시지 */}
<motion.div
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
transition={{ delay: 0.2, duration: 0.5 }}
className="mb-6"
>
<h2 className="text-xl font-bold text-gray-800 mb-2">
일정을 찾을 없습니다
</h2>
<p className="text-gray-500 text-sm leading-relaxed">
요청하신 일정이 존재하지 않거나
<br />
삭제되었을 있습니다.
</p>
</motion.div>
{/* 장식 요소 */}
<motion.div
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
transition={{ delay: 0.4, duration: 0.5 }}
className="flex justify-center gap-1.5 mb-8"
>
{[...Array(5)].map((_, i) => (
<motion.div
key={i}
className="w-1.5 h-1.5 rounded-full bg-primary"
animate={{
y: [0, -6, 0],
opacity: [0.3, 1, 0.3],
}}
transition={{
duration: 1.2,
repeat: Infinity,
delay: i * 0.15,
ease: "easeInOut",
}}
/>
))}
</motion.div>
{/* 버튼들 */}
<motion.div
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
transition={{ delay: 0.5, duration: 0.5 }}
className="flex flex-col gap-3"
>
<button
onClick={() => window.history.back()}
className="flex items-center justify-center gap-2 w-full px-6 py-3 border-2 border-primary text-primary rounded-full font-medium active:bg-primary active:text-white transition-colors"
>
<ChevronLeft size={18} />
이전 페이지
</button>
<Link
to="/schedule"
className="flex items-center justify-center gap-2 w-full px-6 py-3 bg-gradient-to-r from-primary to-primary-dark text-white rounded-full font-medium active:opacity-90 transition-opacity"
>
<Calendar size={18} />
일정 목록
</Link>
</motion.div>
</div>
</div>
);
}
// TODO: 일정 상세 페이지 구현
return (
<div className="min-h-screen bg-gray-50 p-4">
<div className="text-center py-8 text-gray-500">
일정 상세 페이지 준비
</div>
</div>
);
}
export default MobileScheduleDetail;