fix: 생일 표시 버그 수정 및 데이트픽커 개선
- 생일이 생년 이전 년도에 표시되는 버그 수정 - 페이지 진입 애니메이션 추가 (사전 관리, 일정 추가) - 데이트픽커 12년 단위 이동으로 변경 - 년도 선택 시 월 선택 화면 전환 제거 - 시작 년도 2025년 고정, 이전 이동 비활성화 - PC/모바일 일정 페이지, 관리자 페이지 모두 적용 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
2576a244c0
commit
1a9fa54981
7 changed files with 39 additions and 26 deletions
|
|
@ -327,6 +327,11 @@ async function handleMonthlySchedules(db, year, month) {
|
|||
// 생일 일정 추가
|
||||
for (const member of birthdays) {
|
||||
const birthDate = new Date(member.birth_date);
|
||||
const birthYear = birthDate.getFullYear();
|
||||
|
||||
// 조회 연도가 생년보다 이전이면 스킵
|
||||
if (year < birthYear) continue;
|
||||
|
||||
const birthdayThisYear = new Date(year, birthDate.getMonth(), birthDate.getDate());
|
||||
const dateKey = birthdayThisYear.toISOString().split('T')[0];
|
||||
|
||||
|
|
|
|||
|
|
@ -40,13 +40,15 @@ function CustomDatePicker({ value, onChange, placeholder = '날짜 선택', show
|
|||
days.push(i);
|
||||
}
|
||||
|
||||
const startYear = Math.floor(year / 10) * 10 - 1;
|
||||
const MIN_YEAR = 2025;
|
||||
const startYear = Math.max(MIN_YEAR, Math.floor(year / 12) * 12 - 1);
|
||||
const years = Array.from({ length: 12 }, (_, i) => startYear + i);
|
||||
const canGoPrevYearRange = startYear > MIN_YEAR;
|
||||
|
||||
const prevMonth = () => setViewDate(new Date(year, month - 1, 1));
|
||||
const nextMonth = () => setViewDate(new Date(year, month + 1, 1));
|
||||
const prevYearRange = () => setViewDate(new Date(year - 10, month, 1));
|
||||
const nextYearRange = () => setViewDate(new Date(year + 10, month, 1));
|
||||
const prevYearRange = () => canGoPrevYearRange && setViewDate(new Date(Math.max(MIN_YEAR, year - 12), month, 1));
|
||||
const nextYearRange = () => setViewDate(new Date(year + 12, month, 1));
|
||||
|
||||
const selectDate = (day) => {
|
||||
const dateStr = `${year}-${String(month + 1).padStart(2, '0')}-${String(day).padStart(2, '0')}`;
|
||||
|
|
@ -57,7 +59,6 @@ function CustomDatePicker({ value, onChange, placeholder = '날짜 선택', show
|
|||
|
||||
const selectYear = (y) => {
|
||||
setViewDate(new Date(y, month, 1));
|
||||
setViewMode('months');
|
||||
};
|
||||
|
||||
const selectMonth = (m) => {
|
||||
|
|
@ -124,7 +125,8 @@ function CustomDatePicker({ value, onChange, placeholder = '날짜 선택', show
|
|||
<button
|
||||
type="button"
|
||||
onClick={viewMode === 'years' ? prevYearRange : prevMonth}
|
||||
className="p-1.5 hover:bg-gray-100 rounded-lg transition-colors"
|
||||
disabled={viewMode === 'years' && !canGoPrevYearRange}
|
||||
className={`p-1.5 rounded-lg transition-colors ${viewMode === 'years' && !canGoPrevYearRange ? 'opacity-30' : 'hover:bg-gray-100'}`}
|
||||
>
|
||||
<ChevronLeft size={20} className="text-gray-600" />
|
||||
</button>
|
||||
|
|
|
|||
|
|
@ -1239,8 +1239,10 @@ function CalendarPicker({
|
|||
}
|
||||
};
|
||||
|
||||
const [yearRangeStart, setYearRangeStart] = useState(Math.floor(year / 12) * 12);
|
||||
const MIN_YEAR = 2025;
|
||||
const [yearRangeStart, setYearRangeStart] = useState(MIN_YEAR);
|
||||
const yearRange = Array.from({ length: 12 }, (_, i) => yearRangeStart + i);
|
||||
const canGoPrevYearRange = yearRangeStart > MIN_YEAR;
|
||||
|
||||
// 배경 스크롤 막기
|
||||
useEffect(() => {
|
||||
|
|
@ -1364,16 +1366,17 @@ function CalendarPicker({
|
|||
>
|
||||
{/* 년도 범위 헤더 */}
|
||||
<div className="flex items-center justify-between mb-3">
|
||||
<button
|
||||
onClick={() => setYearRangeStart(yearRangeStart - 12)}
|
||||
className="p-1"
|
||||
<button
|
||||
onClick={() => canGoPrevYearRange && setYearRangeStart(Math.max(MIN_YEAR, yearRangeStart - 12))}
|
||||
disabled={!canGoPrevYearRange}
|
||||
className={`p-1 ${canGoPrevYearRange ? '' : 'opacity-30'}`}
|
||||
>
|
||||
<ChevronLeft size={18} />
|
||||
</button>
|
||||
<span className="font-semibold text-sm">
|
||||
{yearRangeStart} - {yearRangeStart + 11}
|
||||
</span>
|
||||
<button
|
||||
<button
|
||||
onClick={() => setYearRangeStart(yearRangeStart + 12)}
|
||||
className="p-1"
|
||||
>
|
||||
|
|
|
|||
|
|
@ -273,9 +273,11 @@ function AdminSchedule() {
|
|||
const days = ['일', '월', '화', '수', '목', '금', '토'];
|
||||
const monthNames = ['1월', '2월', '3월', '4월', '5월', '6월', '7월', '8월', '9월', '10월', '11월', '12월'];
|
||||
|
||||
// 년도 범위 (현재 년도 기준 10년 단위 - Schedule.jsx와 동일)
|
||||
const startYear = Math.floor(year / 10) * 10 - 1;
|
||||
// 년도 범위 (2025년부터 시작, 12년 단위)
|
||||
const MIN_YEAR = 2025;
|
||||
const startYear = Math.max(MIN_YEAR, Math.floor(year / 12) * 12 - 1);
|
||||
const yearRange = Array.from({ length: 12 }, (_, i) => startYear + i);
|
||||
const canGoPrevYearRange = startYear > MIN_YEAR;
|
||||
|
||||
// 현재 년도/월 확인 함수
|
||||
const isCurrentYear = (y) => new Date().getFullYear() === y;
|
||||
|
|
@ -482,14 +484,13 @@ function AdminSchedule() {
|
|||
setSchedules([]); // 이전 달 데이터 즉시 초기화
|
||||
};
|
||||
|
||||
// 년도 범위 이동
|
||||
const prevYearRange = () => setCurrentDate(new Date(year - 10, month, 1));
|
||||
const nextYearRange = () => setCurrentDate(new Date(year + 10, month, 1));
|
||||
// 년도 범위 이동 (12년 단위, 2025년 이전 불가)
|
||||
const prevYearRange = () => canGoPrevYearRange && setCurrentDate(new Date(Math.max(MIN_YEAR, year - 12), month, 1));
|
||||
const nextYearRange = () => setCurrentDate(new Date(year + 12, month, 1));
|
||||
|
||||
// 년도 선택 시 월 선택 모드로 전환
|
||||
// 년도 선택
|
||||
const selectYear = (newYear) => {
|
||||
setCurrentDate(new Date(newYear, month, 1));
|
||||
setViewMode('months');
|
||||
};
|
||||
|
||||
// 월 선택 시 적용 후 닫기
|
||||
|
|
@ -730,7 +731,8 @@ function AdminSchedule() {
|
|||
<div className="flex items-center justify-between mb-4">
|
||||
<button
|
||||
onClick={prevYearRange}
|
||||
className="p-1.5 hover:bg-gray-100 rounded-lg transition-colors"
|
||||
disabled={!canGoPrevYearRange}
|
||||
className={`p-1.5 rounded-lg transition-colors ${canGoPrevYearRange ? 'hover:bg-gray-100' : 'opacity-30'}`}
|
||||
>
|
||||
<ChevronLeft size={20} className="text-gray-600" />
|
||||
</button>
|
||||
|
|
|
|||
|
|
@ -613,7 +613,7 @@ function AdminScheduleDict() {
|
|||
) : (
|
||||
<div className="overflow-x-auto max-h-[500px] overflow-y-auto">
|
||||
<table className="w-full">
|
||||
<thead className="bg-gray-50 sticky top-0">
|
||||
<thead className="bg-gray-50 sticky top-0 z-30">
|
||||
<tr>
|
||||
<th className="px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider w-16">#</th>
|
||||
<th className="px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">단어</th>
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ const formVariants = {
|
|||
visible: {
|
||||
opacity: 1,
|
||||
y: 0,
|
||||
transition: { duration: 0.3, ease: "easeOut" },
|
||||
transition: { duration: 0.3, ease: "easeOut", delay: 0.3 },
|
||||
},
|
||||
exit: {
|
||||
opacity: 0,
|
||||
|
|
|
|||
|
|
@ -431,7 +431,6 @@ function Schedule() {
|
|||
|
||||
const selectYear = (newYear) => {
|
||||
setCurrentDate(new Date(newYear, month, 1));
|
||||
setViewMode('months');
|
||||
};
|
||||
|
||||
const selectMonth = (newMonth) => {
|
||||
|
|
@ -568,12 +567,14 @@ function Schedule() {
|
|||
return year === now.getFullYear() && m === now.getMonth();
|
||||
};
|
||||
|
||||
// 연도 선택 범위
|
||||
const [yearRangeStart, setYearRangeStart] = useState(currentYear - 1);
|
||||
// 연도 선택 범위 (2025년부터 시작)
|
||||
const MIN_YEAR = 2025;
|
||||
const [yearRangeStart, setYearRangeStart] = useState(MIN_YEAR);
|
||||
const yearRange = Array.from({ length: 12 }, (_, i) => yearRangeStart + i);
|
||||
const monthNames = ['1월', '2월', '3월', '4월', '5월', '6월', '7월', '8월', '9월', '10월', '11월', '12월'];
|
||||
const prevYearRange = () => setYearRangeStart(prev => prev - 3);
|
||||
const nextYearRange = () => setYearRangeStart(prev => prev + 3);
|
||||
const canGoPrevYearRange = yearRangeStart > MIN_YEAR;
|
||||
const prevYearRange = () => canGoPrevYearRange && setYearRangeStart(prev => Math.max(MIN_YEAR, prev - 12));
|
||||
const nextYearRange = () => setYearRangeStart(prev => prev + 12);
|
||||
|
||||
// 선택된 카테고리 이름
|
||||
const getSelectedCategoryNames = () => {
|
||||
|
|
@ -680,7 +681,7 @@ function Schedule() {
|
|||
className="absolute top-20 left-8 right-8 mx-auto w-80 bg-white rounded-xl shadow-lg border border-gray-200 p-4 z-10"
|
||||
>
|
||||
<div className="flex items-center justify-between mb-4">
|
||||
<button onClick={prevYearRange} className="p-1.5 hover:bg-gray-100 rounded-lg transition-colors">
|
||||
<button onClick={prevYearRange} disabled={!canGoPrevYearRange} className={`p-1.5 rounded-lg transition-colors ${canGoPrevYearRange ? 'hover:bg-gray-100' : 'opacity-30'}`}>
|
||||
<ChevronLeft size={20} className="text-gray-600" />
|
||||
</button>
|
||||
<span className="font-medium text-gray-900">
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue