/** * Unified Inbox Controller * Combines contact, media, and case submissions into single view */ const Contact = require('../models/Contact.model'); const MediaInquiry = require('../models/MediaInquiry.model'); const CaseSubmission = require('../models/CaseSubmission.model'); /** * Get unified inbox with all communication types */ async function getInbox(req, res) { try { const { type, // filter: contact, media, case, or all status, // filter: new, pending, assigned, etc limit = 20, skip = 0 } = req.query; const options = { limit: parseInt(limit), skip: parseInt(skip) }; const items = []; // Fetch contacts if (!type || type === 'all' || type === 'contact') { const contacts = status ? await Contact.findByStatus(status, options) : await Contact.list({}, options); items.push(...contacts.map(c => ({ ...c, _type: 'contact', _displayStatus: c.status, _priority: c.priority || 'normal', _created: c.created_at }))); } // Fetch media inquiries if (!type || type === 'all' || type === 'media') { const media = status ? await MediaInquiry.findByStatus(status, options) : await MediaInquiry.findByStatus('new', options); items.push(...media.map(m => ({ ...m, _type: 'media', _displayStatus: m.status, _priority: m.ai_triage?.urgency || 'medium', _created: m.created_at }))); } // Fetch case submissions if (!type || type === 'all' || type === 'case') { const cases = status ? await CaseSubmission.findByStatus(status, options) : await CaseSubmission.findByStatus('pending', options); items.push(...cases.map(c => ({ ...c, _type: 'case', _displayStatus: c.moderation?.status || 'pending', _priority: c.ai_review?.relevance_score >= 0.7 ? 'high' : 'normal', _created: c.submitted_at }))); } // Sort by created date (most recent first) items.sort((a, b) => new Date(b._created) - new Date(a._created)); // Apply limit to combined results const paginatedItems = items.slice(0, options.limit); res.json({ success: true, total: items.length, items: paginatedItems, hasMore: items.length > options.limit }); } catch (error) { console.error('Unified inbox error:', error); res.status(500).json({ success: false, error: 'Failed to load inbox' }); } } /** * Get unified inbox statistics */ async function getStats(req, res) { try { // Get statistics from all three sources const [contactStats, mediaStats, caseStats] = await Promise.all([ Contact.getStats(), getMediaStats(), getCaseStats() ]); res.json({ success: true, stats: { contacts: contactStats, media: mediaStats, cases: caseStats, total: { new: (contactStats.by_status.new || 0) + (mediaStats.by_status.new || 0) + (caseStats.by_status.pending || 0), assigned: (contactStats.by_status.assigned || 0) + (mediaStats.by_status.triaged || 0), responded: (contactStats.by_status.responded || 0) + (mediaStats.by_status.responded || 0), all: contactStats.total + mediaStats.total + caseStats.total } } }); } catch (error) { console.error('Inbox stats error:', error); res.status(500).json({ success: false, error: 'Failed to load statistics' }); } } /** * Helper: Get media inquiry statistics */ async function getMediaStats() { const [_total, newCount, triagedCount, respondedCount, closedCount] = await Promise.all([ MediaInquiry.countByStatus('new'), MediaInquiry.countByStatus('new'), MediaInquiry.countByStatus('triaged'), MediaInquiry.countByStatus('responded'), MediaInquiry.countByStatus('closed') ]); // Get total by adding all status counts const totalSum = newCount + triagedCount + respondedCount + closedCount; return { total: totalSum, by_status: { new: newCount, triaged: triagedCount, responded: respondedCount, closed: closedCount } }; } /** * Helper: Get case submission statistics */ async function getCaseStats() { const [pending, approved, rejected, needsInfo] = await Promise.all([ CaseSubmission.countByStatus('pending'), CaseSubmission.countByStatus('approved'), CaseSubmission.countByStatus('rejected'), CaseSubmission.countByStatus('needs_info') ]); const total = pending + approved + rejected + needsInfo; return { total, by_status: { pending, approved, rejected, needs_info: needsInfo } }; } module.exports = { getInbox, getStats };