fix(frontend): 멤버 표시 오류 수정 및 생일 우선 정렬 추가

수정:
- AdminSchedule.jsx 1306번 라인 멤버 처리 오류 수정
- getMemberList 헬퍼 함수 사용으로 통일

생일 우선 정렬:
- PC 공개 일정 페이지: filteredSchedules에 생일 우선 정렬 추가
- PC 관리 페이지: filteredSchedules에 생일 우선 정렬 추가
- 모바일 공개 페이지: groupedSchedules, selectedDateSchedules에 생일 우선 정렬 추가

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
caadiq 2026-01-21 16:26:17 +09:00
parent b4c393c20a
commit 9d365dcadb
3 changed files with 76 additions and 26 deletions

View file

@ -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]);
//

View file

@ -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() {
</span>
)}
</div>
{(schedule.members?.length > 0 || schedule.member_names) && (
<div className="flex flex-wrap gap-1.5 mt-2">
{(() => {
const memberList = schedule.members?.map(m => m.name) || schedule.member_names?.split(',') || [];
return memberList.map((name, i) => (
{(() => {
const memberList = getMemberList(schedule);
if (memberList.length === 0) return null;
return (
<div className="flex flex-wrap gap-1.5 mt-2">
{memberList.map((name, i) => (
<span key={i} className="px-2 py-0.5 bg-primary/10 text-primary text-xs font-medium rounded-full">
{name.trim()}
{name}
</span>
));
})()}
</div>
)}
))}
</div>
);
})()}
</div>
<div className="flex items-center gap-2 opacity-0 group-hover:opacity-100 transition-opacity">

View file

@ -483,18 +483,29 @@ function Schedule() {
const currentYearMonth = `${year}-${String(month + 1).padStart(2, '0')}`;
const filteredSchedules = useMemo(() => {
//
const sortWithBirthdayFirst = (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-');
if (aIsBirthday && !bIsBirthday) return -1;
if (!aIsBirthday && bIsBirthday) return 1;
return 0;
});
};
//
if (isSearchMode) {
// , API (Meilisearch )
if (!searchTerm) return [];
//
if (selectedCategories.length === 0) return searchResults;
return searchResults.filter(s => selectedCategories.includes(s.category_id));
if (selectedCategories.length === 0) return sortWithBirthdayFirst(searchResults);
return sortWithBirthdayFirst(searchResults.filter(s => selectedCategories.includes(s.category_id)));
}
// :
return schedules
const filtered = schedules
.filter(s => {
const scheduleDate = s.date ? s.date.split('T')[0] : '';
const matchesDate = selectedDate
@ -504,6 +515,12 @@ function Schedule() {
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-');
if (aIsBirthday && !bIsBirthday) return -1;
if (!aIsBirthday && bIsBirthday) return 1;
// /
const dateA = a.date ? a.date.split('T')[0] : '';
const dateB = b.date ? b.date.split('T')[0] : '';
if (dateA !== dateB) return dateA.localeCompare(dateB);
@ -511,6 +528,7 @@ function Schedule() {
const timeB = b.time || '00:00:00';
return timeA.localeCompare(timeB);
});
return filtered;
}, [schedules, selectedDate, currentYearMonth, selectedCategories, isSearchMode, searchTerm, searchResults]);
// ( , )