fix: 모바일 일정 페이지 카테고리 API 형식 수정 및 X source.name 비움

- 모바일 Schedule.jsx: category 객체 형식 지원 (category.id, category.name 등)
- 백엔드 API: X 일정의 source.name을 빈 문자열로 변경
- Meilisearch: 검색 결과도 source 객체 형식으로 통일

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
caadiq 2026-01-19 10:16:24 +09:00
parent d7d0506b83
commit c5f5639b11
3 changed files with 26 additions and 15 deletions

View file

@ -121,7 +121,7 @@ export default async function schedulesRoutes(fastify) {
};
} else if (s.category_id === 3 && s.x_post_id) {
result.source = {
name: 'X',
name: '',
url: `https://x.com/realfromis_9/status/${s.x_post_id}`,
};
}
@ -247,7 +247,7 @@ async function handleMonthlySchedules(db, year, month) {
};
} else if (s.category_id === 3 && s.x_post_id) {
schedule.source = {
name: 'X',
name: '',
url: `https://x.com/realfromis_9/status/${s.x_post_id}`,
};
}

View file

@ -137,6 +137,16 @@ function formatScheduleResponse(hit) {
? hit.member_names.split(',').map(name => name.trim()).filter(Boolean)
: [];
// source 객체 구성 (X는 name 비움)
let source = null;
if (hit.category_id === 2 && hit.source_name) {
// YouTube
source = { name: hit.source_name, url: null };
} else if (hit.category_id === 3) {
// X (name 비움)
source = { name: '', url: null };
}
return {
id: hit.id,
title: hit.title,
@ -146,7 +156,7 @@ function formatScheduleResponse(hit) {
name: hit.category_name,
color: hit.category_color,
},
source_name: hit.source_name || null,
source,
members,
_rankingScore: hit._rankingScore,
};

View file

@ -275,11 +275,12 @@ function MobileSchedule() {
const categories = useMemo(() => {
const categoryMap = new Map();
schedules.forEach(s => {
if (s.category_id && !categoryMap.has(s.category_id)) {
categoryMap.set(s.category_id, {
id: s.category_id,
name: s.category_name,
color: s.category_color,
const catId = s.category?.id || s.category_id;
if (catId && !categoryMap.has(catId)) {
categoryMap.set(catId, {
id: catId,
name: s.category?.name || s.category_name,
color: s.category?.color || s.category_color,
});
}
});
@ -717,7 +718,7 @@ function MobileSchedule() {
{/* 일정 점 (최대 3개) */}
<div className="flex gap-0.5 mt-1 h-1.5">
{!isSelected(date) && daySchedules.map((schedule, i) => {
const cat = categories.find(c => c.id === schedule.category_id);
const cat = categories.find(c => c.id === (schedule.category?.id || schedule.category_id));
const color = cat?.color || '#6b7280';
return (
<div
@ -857,7 +858,7 @@ function MobileSchedule() {
<div className={virtualItem.index < searchResults.length - 1 ? "pb-3" : ""}>
<ScheduleCard
schedule={schedule}
categoryColor={getCategoryColor(schedule.category_id)}
categoryColor={getCategoryColor(schedule.category?.id || schedule.category_id)}
categories={categories}
onClick={() => navigate(`/schedule/${schedule.id}`)}
/>
@ -909,7 +910,7 @@ function MobileSchedule() {
<TimelineScheduleCard
key={schedule.id}
schedule={schedule}
categoryColor={getCategoryColor(schedule.category_id)}
categoryColor={getCategoryColor(schedule.category?.id || schedule.category_id)}
categories={categories}
delay={index * 0.05}
onClick={() => navigate(`/schedule/${schedule.id}`)}
@ -926,7 +927,7 @@ function MobileSchedule() {
// () -
function ScheduleCard({ schedule, categoryColor, categories, delay = 0, onClick }) {
const categoryName = categories.find(c => c.id === schedule.category_id)?.name || '미분류';
const categoryName = categories.find(c => c.id === (schedule.category?.id || schedule.category_id))?.name || '미분류';
const memberNames = schedule.member_names || schedule.members?.map(m => m.name).join(',') || '';
const memberList = memberNames.split(',').filter(name => name.trim());
@ -1036,7 +1037,7 @@ function ScheduleCard({ schedule, categoryColor, categories, delay = 0, onClick
// -
function TimelineScheduleCard({ schedule, categoryColor, categories, delay = 0, onClick }) {
const categoryName = categories.find(c => c.id === schedule.category_id)?.name || '미분류';
const categoryName = categories.find(c => c.id === (schedule.category?.id || schedule.category_id))?.name || '미분류';
const memberNames = schedule.member_names || schedule.members?.map(m => m.name).join(',') || '';
const memberList = memberNames.split(',').filter(name => name.trim());
@ -1148,7 +1149,7 @@ function CalendarPicker({
if (!dateMap[date]) {
dateMap[date] = [];
}
const category = categories.find(c => c.id === schedule.category_id);
const category = categories.find(c => c.id === (schedule.category?.id || schedule.category_id));
dateMap[date].push(category?.color || '#6b7280');
});
return dateMap;
@ -1330,7 +1331,7 @@ function CalendarPicker({
{!isSelected(item.date) && daySchedules.length > 0 && (
<div className="flex gap-0.5 mt-0.5 h-1.5">
{daySchedules.map((schedule, i) => {
const cat = categories.find(c => c.id === schedule.category_id);
const cat = categories.find(c => c.id === (schedule.category?.id || schedule.category_id));
const color = cat?.color || '#6b7280';
return (
<div