/** * Destination Controller - Full CRUD for Tourism Spots (PostgreSQL) */ const { getPool } = require('../db'); const { eventBus, EVENTS } = require('../services/eventBus'); /** * List all destinations */ async function list(req, res) { const pool = getPool(); if (!pool) return res.status(500).json({ error: 'Database not connected' }); try { const { category, district, limit = 50, offset = 0 } = req.query; let query = 'SELECT * FROM destinations WHERE 1=1'; const params = []; let paramCounter = 1; if (category) { query += ` AND category = $${paramCounter++}`; params.push(category); } if (district) { query += ` AND district = $${paramCounter++}`; params.push(district); } query += ` ORDER BY created_at DESC LIMIT $${paramCounter++} OFFSET $${paramCounter++}`; params.push(parseInt(limit), parseInt(offset)); const result = await pool.query(query, params); res.json({ success: true, count: result.rows.length, data: result.rows }); } catch (error) { console.error('[Dest List Error]', error.message); res.status(500).json({ error: 'Failed to fetch destinations' }); } } /** * Create destination */ async function create(req, res) { const data = req.body; const pool = getPool(); if (!pool) return res.status(500).json({ error: 'Database not connected' }); try { const slug = data.name.toLowerCase().replace(/ /g, '-').replace(/[^\w-]+/g, ''); const query = ` INSERT INTO destinations (name, slug, description, category, district, latitude, longitude, highlights, media) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9) RETURNING id, name, slug `; const params = [ data.name, slug, data.description, data.category, data.district || 'Jhargram', data.latitude, data.longitude, JSON.stringify(data.highlights || []), JSON.stringify(data.media || []) ]; const result = await pool.query(query, params); const destination = result.rows[0]; // Emit event for Yatra-X re-indexing eventBus.emit(EVENTS.DESTINATION_CREATED, { id: destination.id, slug: destination.slug }); res.status(201).json({ success: true, data: destination }); } catch (error) { console.error('[Dest Create Error]', error.message); res.status(500).json({ error: 'Failed to create destination' }); } } /** * Update destination */ async function update(req, res) { const { id } = req.params; const data = req.body; const pool = getPool(); if (!pool) return res.status(500).json({ error: 'Database not connected' }); try { const updates = []; const params = [id]; let paramCounter = 2; const allowedFields = ['name', 'description', 'category', 'district', 'latitude', 'longitude', 'highlights', 'media', 'is_active']; allowedFields.forEach(field => { if (data[field] !== undefined) { updates.push(`${field} = $${paramCounter++}`); params.push(typeof data[field] === 'object' ? JSON.stringify(data[field]) : data[field]); } }); if (updates.length === 0) return res.status(400).json({ error: 'No fields to update' }); updates.push('updated_at = NOW()'); const query = `UPDATE destinations SET ${updates.join(', ')} WHERE id = $1`; await pool.query(query, params); // Emit event for Yatra-X re-indexing eventBus.emit(EVENTS.DESTINATION_UPDATED, { id }); res.json({ success: true, message: 'Destination updated' }); } catch (error) { console.error('[Dest Update Error]', error.message); res.status(500).json({ error: 'Failed to update destination' }); } } /** * Delete destination */ async function remove(req, res) { const { id } = req.params; const pool = getPool(); if (!pool) return res.status(500).json({ error: 'Database not connected' }); try { await pool.query('DELETE FROM destinations WHERE id = $1', [id]); // Emit event for Yatra-X re-indexing eventBus.emit(EVENTS.DESTINATION_DELETED, { id }); res.json({ success: true, message: 'Destination deleted' }); } catch (error) { console.error('[Dest Delete Error]', error.message); res.status(500).json({ error: 'Failed to delete destination' }); } } module.exports = { list, create, update, remove };