- Fixed unused function parameters by prefixing with underscore - Removed unused imports and variables - Applied eslint --fix for automatic style fixes - Property shorthand - String template literals - Prefer const over let where appropriate - Spacing and formatting Reduces lint errors from 108+ to 78 (61 unused vars, 17 other issues) Related to CI lint failures in previous commit 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
189 lines
4.8 KiB
JavaScript
189 lines
4.8 KiB
JavaScript
/**
|
|
* 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
|
|
};
|