diff --git a/backend/src/services/schedule.js b/backend/src/services/schedule.js index 415b798..a7699b6 100644 --- a/backend/src/services/schedule.js +++ b/backend/src/services/schedule.js @@ -383,8 +383,33 @@ export async function getMonthlySchedules(db, year, month) { } } - // 날짜순 정렬 - schedules.sort((a, b) => a.date.localeCompare(b.date)); + // 날짜순 정렬 (같은 날짜 내에서 특수 일정을 먼저 배치) + schedules.sort((a, b) => { + // 날짜 비교 + const dateCompare = a.date.localeCompare(b.date); + if (dateCompare !== 0) return dateCompare; + + // 같은 날짜면 특수 일정(생일, 기념일)을 먼저 + const aSpecial = a.is_birthday || a.is_debut || a.is_anniversary; + const bSpecial = b.is_birthday || b.is_debut || b.is_anniversary; + if (aSpecial && !bSpecial) return -1; + if (!aSpecial && bSpecial) return 1; + + // 둘 다 특수 일정이면 기념일 > 생일 순서 + if (aSpecial && bSpecial) { + const aDebut = a.is_debut || a.is_anniversary; + const bDebut = b.is_debut || b.is_anniversary; + if (aDebut && !bDebut) return -1; + if (!aDebut && bDebut) return 1; + } + + // 시간순 정렬 + if (a.time && b.time) return a.time.localeCompare(b.time); + if (a.time) return -1; + if (b.time) return 1; + + return 0; + }); return { schedules }; } diff --git a/frontend/src/pages/mobile/schedule/Schedule.jsx b/frontend/src/pages/mobile/schedule/Schedule.jsx index b8b7695..69c0432 100644 --- a/frontend/src/pages/mobile/schedule/Schedule.jsx +++ b/frontend/src/pages/mobile/schedule/Schedule.jsx @@ -336,19 +336,8 @@ function MobileSchedule() { const month = String(selectedDate.getMonth() + 1).padStart(2, '0'); const day = String(selectedDate.getDate()).padStart(2, '0'); const dateStr = `${year}-${month}-${day}`; - 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-'); - const aIsDebut = a.is_debut || a.is_anniversary; - const bIsDebut = b.is_debut || b.is_anniversary; - const aIsSpecial = aIsBirthday || aIsDebut; - const bIsSpecial = bIsBirthday || bIsDebut; - if (aIsSpecial && !bIsSpecial) return -1; - if (!aIsSpecial && bIsSpecial) return 1; - return 0; - }); + // 백엔드에서 이미 정렬된 상태로 전달됨 (특수 일정 우선) + return schedules.filter((s) => s.date.split('T')[0] === dateStr); }, [schedules, selectedDate]); // 요일 이름 diff --git a/frontend/src/pages/pc/public/schedule/Schedule.jsx b/frontend/src/pages/pc/public/schedule/Schedule.jsx index 72859bc..ab0276e 100644 --- a/frontend/src/pages/pc/public/schedule/Schedule.jsx +++ b/frontend/src/pages/pc/public/schedule/Schedule.jsx @@ -238,45 +238,18 @@ function PCSchedule() { const currentYearMonth = `${year}-${String(month + 1).padStart(2, '0')}`; const filteredSchedules = useMemo(() => { - const sortWithSpecialFirst = (list) => { - return [...list].sort((a, b) => { - const aIsBirthday = a.is_birthday || String(a.id).startsWith('birthday-'); - const bIsBirthday = b.is_birthday || String(b.id).startsWith('birthday-'); - const aIsDebut = a.is_debut || a.is_anniversary; - const bIsDebut = b.is_debut || b.is_anniversary; - const aIsSpecial = aIsBirthday || aIsDebut; - const bIsSpecial = bIsBirthday || bIsDebut; - if (aIsSpecial && !bIsSpecial) return -1; - if (!aIsSpecial && bIsSpecial) return 1; - return 0; - }); - }; - + // 백엔드에서 이미 정렬된 상태로 전달됨 (특수 일정 우선) if (isSearchMode) { if (!searchTerm) return []; - if (selectedCategories.length === 0) return sortWithSpecialFirst(searchResults); - return sortWithSpecialFirst(searchResults.filter((s) => selectedCategories.includes(s.category_id))); + if (selectedCategories.length === 0) return searchResults; + return searchResults.filter((s) => selectedCategories.includes(s.category_id)); } - const filtered = schedules - .filter((s) => { - const matchesDate = selectedDate ? s.date === selectedDate : s.date?.startsWith(currentYearMonth); - const matchesCategory = selectedCategories.length === 0 || selectedCategories.includes(s.category_id); - return matchesDate && matchesCategory; - }) - .sort((a, b) => { - const aIsBirthday = a.is_birthday || String(a.id).startsWith('birthday-'); - const bIsBirthday = b.is_birthday || String(b.id).startsWith('birthday-'); - const aIsDebut = a.is_debut || a.is_anniversary; - const bIsDebut = b.is_debut || b.is_anniversary; - const aIsSpecial = aIsBirthday || aIsDebut; - const bIsSpecial = bIsBirthday || bIsDebut; - if (aIsSpecial && !bIsSpecial) return -1; - if (!aIsSpecial && bIsSpecial) return 1; - if (a.date !== b.date) return a.date.localeCompare(b.date); - return (a.time || '00:00:00').localeCompare(b.time || '00:00:00'); - }); - return filtered; + return schedules.filter((s) => { + const matchesDate = selectedDate ? s.date === selectedDate : s.date?.startsWith(currentYearMonth); + const matchesCategory = selectedCategories.length === 0 || selectedCategories.includes(s.category_id); + return matchesDate && matchesCategory; + }); }, [schedules, selectedDate, currentYearMonth, selectedCategories, isSearchMode, searchTerm, searchResults]); // 가상 스크롤