fromis_9/backend/src/routes/schedules/index.js

153 lines
3.8 KiB
JavaScript
Raw Normal View History

/**
* 일정 라우트
* GET: 공개, POST/PUT/DELETE: 인증 필요
*/
import suggestionsRoutes from './suggestions.js';
export default async function schedulesRoutes(fastify) {
const { db } = fastify;
// 추천 검색어 라우트 등록
fastify.register(suggestionsRoutes, { prefix: '/suggestions' });
/**
* GET /api/schedules
* 월별 일정 목록 조회
* @query year - 년도 (필수)
* @query month - (필수)
*/
fastify.get('/', {
schema: {
tags: ['schedules'],
summary: '월별 일정 목록 조회',
querystring: {
type: 'object',
required: ['year', 'month'],
properties: {
year: { type: 'integer', description: '년도' },
month: { type: 'integer', minimum: 1, maximum: 12, description: '월' },
},
},
},
}, async (request, reply) => {
const { year, month } = request.query;
if (!year || !month) {
return reply.code(400).send({ error: 'year와 month는 필수입니다.' });
}
const startDate = `${year}-${String(month).padStart(2, '0')}-01`;
const endDate = new Date(year, month, 0).toISOString().split('T')[0];
const [schedules] = await db.query(`
SELECT
s.id,
s.title,
s.date,
s.time,
s.category_id,
c.name as category_name,
c.color as category_color,
sy.channel_name as source_name
FROM schedules s
LEFT JOIN schedule_categories c ON s.category_id = c.id
LEFT JOIN schedule_youtube sy ON s.id = sy.schedule_id
WHERE s.date BETWEEN ? AND ?
ORDER BY s.date ASC, s.time ASC
`, [startDate, endDate]);
// 날짜별로 그룹화
const grouped = {};
for (const s of schedules) {
const dateKey = s.date.toISOString().split('T')[0];
if (!grouped[dateKey]) {
grouped[dateKey] = {
categories: [],
schedules: [],
};
}
// 일정 추가
const schedule = {
id: s.id,
title: s.title,
time: s.time,
category: {
id: s.category_id,
name: s.category_name,
color: s.category_color,
},
};
if (s.source_name) {
schedule.source_name = s.source_name;
}
grouped[dateKey].schedules.push(schedule);
// 카테고리 카운트
const existingCategory = grouped[dateKey].categories.find(c => c.id === s.category_id);
if (existingCategory) {
existingCategory.count++;
} else {
grouped[dateKey].categories.push({
id: s.category_id,
name: s.category_name,
color: s.category_color,
count: 1,
});
}
}
return grouped;
});
/**
* GET /api/schedules/:id
* 일정 상세 조회
*/
fastify.get('/:id', {
schema: {
tags: ['schedules'],
summary: '일정 상세 조회',
},
}, async (request, reply) => {
const { id } = request.params;
const [schedules] = await db.query(`
SELECT
s.*,
c.name as category_name,
c.color as category_color,
sy.channel_name as source_name
FROM schedules s
LEFT JOIN schedule_categories c ON s.category_id = c.id
LEFT JOIN schedule_youtube sy ON s.id = sy.schedule_id
WHERE s.id = ?
`, [id]);
if (schedules.length === 0) {
return reply.code(404).send({ error: '일정을 찾을 수 없습니다.' });
}
const s = schedules[0];
const result = {
id: s.id,
title: s.title,
date: s.date,
time: s.time,
category: {
id: s.category_id,
name: s.category_name,
color: s.category_color,
},
created_at: s.created_at,
updated_at: s.updated_at,
};
if (s.source_name) {
result.source_name = s.source_name;
}
return result;
});
}