const express = require('express'); const { query } = require('../db'); const router = express.Router(); // 여행 계획 전체 조회 (최신 1개) router.get('/', async (req, res) => { try { // 최신 여행 계획 조회 const planResult = await query( 'SELECT * FROM travel_plans ORDER BY created_at DESC LIMIT 1' ); if (planResult.rows.length === 0) { return res.json(null); } const plan = planResult.rows[0]; // 해당 계획의 모든 일정 조회 const schedules = await query( `SELECT ds.id, ds.schedule_date, json_agg( json_build_object( 'id', a.id, 'time', a.time, 'title', a.title, 'description', a.description, 'location', a.location, 'type', a.type, 'coordinates', CASE WHEN a.lat IS NOT NULL AND a.lng IS NOT NULL THEN json_build_object('lat', a.lat, 'lng', a.lng) ELSE NULL END, 'images', a.images, 'links', a.links, 'relatedPlaces', ( SELECT json_agg( json_build_object( 'id', rp.id, 'name', rp.name, 'description', rp.description, 'address', rp.address, 'coordinates', CASE WHEN rp.lat IS NOT NULL AND rp.lng IS NOT NULL THEN json_build_object('lat', rp.lat, 'lng', rp.lng) ELSE NULL END, 'memo', rp.memo, 'willVisit', rp.will_visit, 'category', rp.category, 'images', rp.images, 'links', rp.links ) ) FROM related_places rp WHERE rp.activity_id = a.id ) ) ORDER BY a.time ) FILTER (WHERE a.id IS NOT NULL) as activities FROM day_schedules ds LEFT JOIN activities a ON a.day_schedule_id = ds.id WHERE ds.travel_plan_id = $1 GROUP BY ds.id, ds.schedule_date ORDER BY ds.schedule_date`, [plan.id] ); const travelPlan = { id: plan.id, startDate: plan.start_date, endDate: plan.end_date, schedule: schedules.rows.map(row => ({ date: row.schedule_date, activities: row.activities || [] })), budget: { total: 0, accommodation: 0, food: 0, transportation: 0, shopping: 0, activities: 0 }, checklist: [] }; res.json(travelPlan); } catch (error) { console.error('Error fetching travel plan:', error); res.status(500).json({ error: error.message }); } }); // 여행 계획 저장/업데이트 router.post('/', async (req, res) => { const client = await query('BEGIN'); try { const { startDate, endDate, schedule } = req.body; // 기존 계획 삭제 (단순화: 항상 최신 1개만 유지) await query('DELETE FROM travel_plans'); // 새 여행 계획 생성 const planResult = await query( 'INSERT INTO travel_plans (start_date, end_date) VALUES ($1, $2) RETURNING id', [startDate, endDate] ); const planId = planResult.rows[0].id; // 일정별 데이터 삽입 for (const day of schedule) { // day_schedule 삽입 const scheduleResult = await query( 'INSERT INTO day_schedules (travel_plan_id, schedule_date) VALUES ($1, $2) RETURNING id', [planId, day.date] ); const scheduleId = scheduleResult.rows[0].id; // activities 삽입 if (day.activities && day.activities.length > 0) { for (const activity of day.activities) { const activityResult = await query( `INSERT INTO activities ( day_schedule_id, time, title, description, location, type, lat, lng, images, links ) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10) RETURNING id`, [ scheduleId, activity.time, activity.title, activity.description || null, activity.location || null, activity.type, activity.coordinates?.lat || null, activity.coordinates?.lng || null, activity.images || null, activity.links || null ] ); const activityId = activityResult.rows[0].id; // related_places 삽입 if (activity.relatedPlaces && activity.relatedPlaces.length > 0) { for (const place of activity.relatedPlaces) { await query( `INSERT INTO related_places ( activity_id, name, description, address, lat, lng, memo, will_visit, category, images, links ) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11)`, [ activityId, place.name, place.description || null, place.address || null, place.coordinates?.lat || null, place.coordinates?.lng || null, place.memo || null, place.willVisit || false, place.category || 'other', place.images || null, place.links || null ] ); } } } } } await query('COMMIT'); res.json({ success: true, id: planId }); } catch (error) { await query('ROLLBACK'); console.error('Error saving travel plan:', error); res.status(500).json({ error: error.message }); } }); module.exports = router;