fromis_9/frontend/src/pages/mobile/schedule/Birthday.jsx

142 lines
5.3 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 { ChevronLeft } from 'lucide-react';
import { fetchApi } from '@/api';
/**
* Mobile 생일 페이지
*/
function MobileBirthday() {
const { memberName, year } = useParams();
// URL 디코딩
const decodedMemberName = decodeURIComponent(memberName || '');
// 멤버 정보 조회
const {
data: member,
isLoading: memberLoading,
error,
} = useQuery({
queryKey: ['member', decodedMemberName],
queryFn: () => fetchApi(`/members/${encodeURIComponent(decodedMemberName)}`),
enabled: !!decodedMemberName,
});
if (!decodedMemberName || error) {
return (
<div className="min-h-screen flex items-center justify-center bg-gray-50 px-6">
<div className="text-center">
<h1 className="text-xl font-bold text-gray-900 mb-2">멤버를 찾을 없습니다</h1>
<Link to="/schedule" className="text-primary">
일정으로 돌아가기
</Link>
</div>
</div>
);
}
if (memberLoading) {
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>
);
}
// 생일 계산
const birthDate = member?.birth_date ? new Date(member.birth_date) : null;
const birthdayThisYear = birthDate ? new Date(parseInt(year), birthDate.getMonth(), birthDate.getDate()) : null;
return (
<div className="min-h-screen bg-gradient-to-b from-pink-50 to-purple-50">
{/* 헤더 */}
<div className="sticky top-0 bg-white/80 backdrop-blur-sm border-b border-gray-100 z-10">
<div className="flex items-center h-14 px-4">
<Link to="/schedule" className="p-2 -ml-2 rounded-lg active:bg-gray-100">
<ChevronLeft size={24} />
</Link>
<div className="flex-1 text-center">
<span className="text-sm font-medium bg-gradient-to-r from-pink-500 via-purple-500 to-indigo-500 bg-clip-text text-transparent">
HAPPY {member?.name_en} DAY
</span>
</div>
<div className="w-10" />
</div>
</div>
<div className="px-4 py-6">
{/* 헤더 카드 */}
<motion.div
initial={{ opacity: 0, y: 10 }}
animate={{ opacity: 1, y: 0 }}
transition={{ delay: 0.1 }}
className="relative overflow-hidden bg-gradient-to-br from-pink-400 via-purple-400 to-indigo-400 rounded-2xl shadow-xl mb-6"
>
{/* 배경 장식 */}
<div className="absolute inset-0 overflow-hidden">
<div className="absolute -top-8 -right-8 w-24 h-24 bg-white/10 rounded-full" />
<div className="absolute -bottom-8 -left-8 w-32 h-32 bg-white/10 rounded-full" />
<div className="absolute top-4 right-6 text-2xl"></div>
<div className="absolute bottom-4 left-10 text-xl">🎉</div>
<div className="absolute top-1/2 right-4 text-lg">🎈</div>
</div>
<div className="relative p-5">
<div className="flex items-center gap-4 mb-4">
{/* 멤버 사진 */}
{member?.image_url && (
<div className="w-20 h-20 rounded-full border-3 border-white/50 shadow-lg overflow-hidden bg-white flex-shrink-0">
<img src={member.image_url} alt={member.name} className="w-full h-full object-cover" />
</div>
)}
{/* 내용 */}
<div className="flex-1 text-white">
<div className="flex items-center gap-2 mb-1">
<span className="text-3xl">🎂</span>
<h1 className="font-bold text-xl tracking-wide">HAPPY {member?.name_en} DAY</h1>
</div>
<p className="text-white/80 text-sm">
{year} {birthdayThisYear?.getMonth() + 1} {birthdayThisYear?.getDate()}
</p>
</div>
</div>
{/* 년도 뱃지 */}
<div className="bg-white/20 backdrop-blur-sm rounded-xl px-4 py-2 inline-flex items-center gap-2">
<span className="text-white/70 text-xs font-medium">YEAR</span>
<span className="text-white text-xl font-bold">{year}</span>
</div>
</div>
</motion.div>
{/* 생일카페 섹션 */}
<motion.div
initial={{ opacity: 0, y: 10 }}
animate={{ opacity: 1, y: 0 }}
transition={{ delay: 0.2 }}
className="bg-white rounded-2xl shadow-md p-5"
>
<h2 className="text-lg font-bold text-gray-900 mb-4 flex items-center gap-2">
<span></span>
생일카페
</h2>
{/* 준비 중 메시지 */}
<div className="text-center py-8">
<div className="text-5xl mb-3">🎁</div>
<p className="text-gray-500 text-sm">
{year} {decodedMemberName} 생일카페 정보가 준비 중입니다
</p>
<p className="text-gray-400 text-xs mt-1">생일카페 정보가 등록되면 이곳에 표시됩니다</p>
</div>
</motion.div>
</div>
</div>
);
}
export default MobileBirthday;