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:
parent
b4c393c20a
commit
9d365dcadb
3 changed files with 76 additions and 26 deletions
|
|
@ -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]);
|
||||
|
||||
// 요일 이름
|
||||
|
|
|
|||
|
|
@ -575,19 +575,32 @@ 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 {
|
||||
// 일반 모드: 로컬 필터링
|
||||
return schedules.filter(schedule => {
|
||||
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 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 className="flex items-center gap-2 opacity-0 group-hover:opacity-100 transition-opacity">
|
||||
|
|
|
|||
|
|
@ -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]);
|
||||
|
||||
// 가상 스크롤 설정 (검색 모드에서만 활성화, 동적 높이 지원)
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue