diff --git a/frontend/src/pages/mobile/public/Schedule.jsx b/frontend/src/pages/mobile/public/Schedule.jsx index 41f7d86..548507b 100644 --- a/frontend/src/pages/mobile/public/Schedule.jsx +++ b/frontend/src/pages/mobile/public/Schedule.jsx @@ -440,7 +440,7 @@ function MobileSchedule() { return category?.color || '#6b7280'; }; - // 날짜별 일정 그룹화 + // 날짜별 일정 그룹화 (생일 우선) const groupedSchedules = useMemo(() => { const groups = {}; schedules.forEach(schedule => { @@ -448,6 +448,16 @@ function MobileSchedule() { if (!groups[date]) groups[date] = []; groups[date].push(schedule); }); + // 각 날짜 그룹 내에서 생일 우선 정렬 + Object.values(groups).forEach(group => { + group.sort((a, b) => { + const aIsBirthday = a.is_birthday || String(a.id).startsWith('birthday-'); + const bIsBirthday = b.is_birthday || String(b.id).startsWith('birthday-'); + if (aIsBirthday && !bIsBirthday) return -1; + if (!aIsBirthday && bIsBirthday) return 1; + return 0; + }); + }); return Object.entries(groups).sort((a, b) => a[0].localeCompare(b[0])); }, [schedules]); @@ -463,7 +473,7 @@ function MobileSchedule() { return days; }, [selectedDate]); - // 선택된 날짜의 일정 + // 선택된 날짜의 일정 (생일 우선) const selectedDateSchedules = useMemo(() => { // KST 기준 날짜 문자열 생성 const year = selectedDate.getFullYear(); @@ -471,7 +481,15 @@ function MobileSchedule() { const day = String(selectedDate.getDate()).padStart(2, '0'); const dateStr = `${year}-${month}-${day}`; // API 응답의 date는 ISO 형식이므로 T 이전 부분만 비교 - return schedules.filter(s => s.date.split('T')[0] === dateStr); + return schedules + .filter(s => s.date.split('T')[0] === dateStr) + .sort((a, b) => { + const aIsBirthday = a.is_birthday || String(a.id).startsWith('birthday-'); + const bIsBirthday = b.is_birthday || String(b.id).startsWith('birthday-'); + if (aIsBirthday && !bIsBirthday) return -1; + if (!aIsBirthday && bIsBirthday) return 1; + return 0; + }); }, [schedules, selectedDate]); // 요일 이름 diff --git a/frontend/src/pages/pc/admin/AdminSchedule.jsx b/frontend/src/pages/pc/admin/AdminSchedule.jsx index e0a25a0..8882ab0 100644 --- a/frontend/src/pages/pc/admin/AdminSchedule.jsx +++ b/frontend/src/pages/pc/admin/AdminSchedule.jsx @@ -575,18 +575,31 @@ function AdminSchedule() { // 일정 목록 (검색 모드일 때 searchResults, 일반 모드일 때 로컬 필터링) - useMemo로 최적화 const filteredSchedules = useMemo(() => { + let result; if (isSearchMode) { if (!searchTerm) return []; // 카테고리 필터링 적용 - if (selectedCategories.length === 0) return searchResults; - return searchResults.filter(s => selectedCategories.includes(s.category_id)); + if (selectedCategories.length === 0) { + result = [...searchResults]; + } else { + result = searchResults.filter(s => selectedCategories.includes(s.category_id)); + } + } else { + // 일반 모드: 로컬 필터링 + result = schedules.filter(schedule => { + const matchesCategory = selectedCategories.length === 0 || selectedCategories.includes(schedule.category_id); + const scheduleDate = formatDate(schedule.date); + const matchesDate = !selectedDate || scheduleDate === selectedDate; + return matchesCategory && matchesDate; + }); } - // 일반 모드: 로컬 필터링 - return schedules.filter(schedule => { - const matchesCategory = selectedCategories.length === 0 || selectedCategories.includes(schedule.category_id); - const scheduleDate = formatDate(schedule.date); - const matchesDate = !selectedDate || scheduleDate === selectedDate; - return matchesCategory && matchesDate; + // 생일 일정을 맨 위로 정렬 + return result.sort((a, b) => { + const aIsBirthday = a.is_birthday || String(a.id).startsWith('birthday-'); + const bIsBirthday = b.is_birthday || String(b.id).startsWith('birthday-'); + if (aIsBirthday && !bIsBirthday) return -1; + if (!aIsBirthday && bIsBirthday) return 1; + return 0; }); }, [isSearchMode, searchTerm, searchResults, schedules, selectedCategories, selectedDate]); @@ -1300,18 +1313,19 @@ function AdminSchedule() { )} - {(schedule.members?.length > 0 || schedule.member_names) && ( -