785 lines
30 KiB
HTML
Executable File
785 lines
30 KiB
HTML
Executable File
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<meta name="robots" content="noindex, nofollow, noarchive">
|
|
<title>Messages - MSPE Admin</title>
|
|
<link rel="preconnect" href="https://fonts.googleapis.com">
|
|
<link href="https://fonts.googleapis.com/css2?family=DM+Sans:wght@400;500;600;700&display=swap" rel="stylesheet">
|
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css" integrity="sha384-t1nt8BQoYMLFN5p42tRAtuAAFQaCQODekUVeKKZrEnEyp4H2R0RHFz0KWpmj7i8g" crossorigin="anonymous">
|
|
<link rel="stylesheet" href="/admin/css/admin.css">
|
|
<style>
|
|
.messages-grid {
|
|
display: grid;
|
|
grid-template-columns: 1fr 2fr;
|
|
gap: 2rem;
|
|
height: calc(100vh - 200px);
|
|
}
|
|
|
|
.messages-list {
|
|
background: white;
|
|
border-radius: 10px;
|
|
box-shadow: var(--shadow-sm);
|
|
overflow: hidden;
|
|
display: flex;
|
|
flex-direction: column;
|
|
}
|
|
|
|
.messages-list-header {
|
|
padding: 1.5rem;
|
|
border-bottom: 1px solid var(--gray-200);
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
}
|
|
|
|
.messages-list-header h3 {
|
|
margin: 0;
|
|
}
|
|
|
|
.unread-count {
|
|
background: var(--primary);
|
|
color: white;
|
|
padding: 0.25rem 0.75rem;
|
|
border-radius: 20px;
|
|
font-size: 0.875rem;
|
|
font-weight: 600;
|
|
}
|
|
|
|
.messages-filters {
|
|
padding: 1rem 1.5rem;
|
|
border-bottom: 1px solid var(--gray-200);
|
|
display: flex;
|
|
gap: 1rem;
|
|
}
|
|
|
|
.messages-filters select {
|
|
padding: 0.5rem 1rem;
|
|
border: 1px solid var(--gray-300);
|
|
border-radius: var(--radius-sm);
|
|
font-size: 0.875rem;
|
|
}
|
|
|
|
.messages-items {
|
|
flex: 1;
|
|
overflow-y: auto;
|
|
}
|
|
|
|
.message-item {
|
|
padding: 1rem 1.5rem;
|
|
border-bottom: 1px solid var(--gray-200);
|
|
cursor: pointer;
|
|
transition: all 0.3s ease;
|
|
}
|
|
|
|
.message-item:hover {
|
|
background: var(--gray-50);
|
|
}
|
|
|
|
.message-item.active {
|
|
background: var(--primary);
|
|
color: white;
|
|
}
|
|
|
|
.message-item.active .message-meta,
|
|
.message-item.active .message-preview {
|
|
color: rgba(255,255,255,0.8);
|
|
}
|
|
|
|
.message-item.unread {
|
|
background: rgba(14, 165, 233, 0.05);
|
|
border-left: 3px solid var(--primary);
|
|
}
|
|
|
|
.message-header {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: flex-start;
|
|
margin-bottom: 0.5rem;
|
|
}
|
|
|
|
.message-sender {
|
|
font-weight: 600;
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 0.5rem;
|
|
}
|
|
|
|
.message-sender .unread-dot {
|
|
width: 8px;
|
|
height: 8px;
|
|
background: var(--primary);
|
|
border-radius: 50%;
|
|
}
|
|
|
|
.message-meta {
|
|
font-size: 0.75rem;
|
|
color: var(--gray-500);
|
|
}
|
|
|
|
.message-preview {
|
|
font-size: 0.875rem;
|
|
color: var(--gray-600);
|
|
overflow: hidden;
|
|
text-overflow: ellipsis;
|
|
white-space: nowrap;
|
|
}
|
|
|
|
.message-details {
|
|
background: white;
|
|
border-radius: 10px;
|
|
box-shadow: var(--shadow-sm);
|
|
overflow: hidden;
|
|
display: flex;
|
|
flex-direction: column;
|
|
}
|
|
|
|
.message-details-header {
|
|
padding: 1.5rem;
|
|
border-bottom: 1px solid var(--gray-200);
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: flex-start;
|
|
}
|
|
|
|
.message-details-header h3 {
|
|
margin: 0 0 0.5rem 0;
|
|
}
|
|
|
|
.message-details-header .meta {
|
|
font-size: 0.875rem;
|
|
color: var(--gray-500);
|
|
}
|
|
|
|
.message-actions-header {
|
|
display: flex;
|
|
gap: 0.5rem;
|
|
}
|
|
|
|
.message-actions-header button {
|
|
padding: 0.5rem 1rem;
|
|
border: 1px solid var(--gray-300);
|
|
background: white;
|
|
border-radius: 6px;
|
|
cursor: pointer;
|
|
font-size: 0.875rem;
|
|
transition: all 0.3s ease;
|
|
}
|
|
|
|
.message-actions-header button:hover {
|
|
background: var(--gray-100);
|
|
}
|
|
|
|
.message-actions-header button.delete:hover {
|
|
background: #fee2e2;
|
|
color: #dc2626;
|
|
border-color: #dc2626;
|
|
}
|
|
|
|
.message-details-content {
|
|
flex: 1;
|
|
padding: 1.5rem;
|
|
overflow-y: auto;
|
|
}
|
|
|
|
.contact-info {
|
|
display: grid;
|
|
grid-template-columns: repeat(2, 1fr);
|
|
gap: 1.5rem;
|
|
margin-bottom: 2rem;
|
|
padding-bottom: 1.5rem;
|
|
border-bottom: 1px solid var(--gray-200);
|
|
}
|
|
|
|
.contact-info-item {
|
|
display: flex;
|
|
flex-direction: column;
|
|
}
|
|
|
|
.contact-info-item label {
|
|
font-size: 0.75rem;
|
|
font-weight: 600;
|
|
color: var(--gray-500);
|
|
text-transform: uppercase;
|
|
letter-spacing: 0.5px;
|
|
margin-bottom: 0.375rem;
|
|
}
|
|
|
|
.contact-info-item .value {
|
|
font-size: 0.9375rem;
|
|
color: var(--gray-700);
|
|
}
|
|
|
|
.contact-info-item .value a {
|
|
color: var(--primary);
|
|
text-decoration: none;
|
|
}
|
|
|
|
.message-body {
|
|
line-height: 1.7;
|
|
color: var(--gray-700);
|
|
}
|
|
|
|
.message-body h4 {
|
|
margin-bottom: 1rem;
|
|
color: var(--gray-900);
|
|
}
|
|
|
|
.empty-state {
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
justify-content: center;
|
|
height: 100%;
|
|
padding: 4rem 2rem;
|
|
text-align: center;
|
|
color: var(--gray-500);
|
|
}
|
|
|
|
.empty-state i {
|
|
font-size: 4rem;
|
|
margin-bottom: 1rem;
|
|
opacity: 0.3;
|
|
}
|
|
|
|
@media (max-width: 1024px) {
|
|
.messages-grid {
|
|
grid-template-columns: 1fr;
|
|
height: auto;
|
|
}
|
|
|
|
.messages-list {
|
|
max-height: 400px;
|
|
}
|
|
}
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<div class="admin-wrapper">
|
|
<aside class="sidebar" id="sidebar">
|
|
<div class="sidebar-header">
|
|
<a href="/admin/dashboard.html" class="sidebar-logo">
|
|
<i class="fas fa-cube"></i>
|
|
<span>MSPE</span>
|
|
</a>
|
|
<button class="sidebar-toggle" id="sidebar-toggle">
|
|
<i class="fas fa-bars"></i>
|
|
</button>
|
|
</div>
|
|
|
|
<nav class="sidebar-nav">
|
|
<div class="nav-section">
|
|
<span class="nav-section-title">Main</span>
|
|
<ul class="nav-menu">
|
|
<li class="nav-item">
|
|
<a href="/admin/dashboard.html" class="nav-link">
|
|
<i class="fas fa-th-large"></i>
|
|
<span>Dashboard</span>
|
|
</a>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
|
|
<div class="nav-section">
|
|
<span class="nav-section-title">Content</span>
|
|
<ul class="nav-menu">
|
|
<li class="nav-item">
|
|
<a href="/admin/pages.html" class="nav-link">
|
|
<i class="fas fa-file-alt"></i>
|
|
<span>Pages</span>
|
|
</a>
|
|
</li>
|
|
<li class="nav-item">
|
|
<a href="/admin/services.html" class="nav-link">
|
|
<i class="fas fa-concierge-bell"></i>
|
|
<span>Services</span>
|
|
</a>
|
|
</li>
|
|
<li class="nav-item">
|
|
<a href="/admin/portfolio.html" class="nav-link">
|
|
<i class="fas fa-briefcase"></i>
|
|
<span>Portfolio</span>
|
|
</a>
|
|
</li>
|
|
<li class="nav-item">
|
|
<a href="/admin/news.html" class="nav-link">
|
|
<i class="fas fa-newspaper"></i>
|
|
<span>News & Events</span>
|
|
</a>
|
|
</li>
|
|
<li class="nav-item">
|
|
<a href="/admin/testimonials.html" class="nav-link">
|
|
<i class="fas fa-quote-right"></i>
|
|
<span>Testimonials</span>
|
|
</a>
|
|
</li>
|
|
<li class="nav-item">
|
|
<a href="/admin/team.html" class="nav-link">
|
|
<i class="fas fa-users"></i>
|
|
<span>Team</span>
|
|
</a>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
|
|
<div class="nav-section">
|
|
<span class="nav-section-title">Media</span>
|
|
<ul class="nav-menu">
|
|
<li class="nav-item">
|
|
<a href="/admin/media.html" class="nav-link">
|
|
<i class="fas fa-images"></i>
|
|
<span>Media Library</span>
|
|
</a>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
|
|
<div class="nav-section">
|
|
<span class="nav-section-title">Inquiries</span>
|
|
<ul class="nav-menu">
|
|
<li class="nav-item active">
|
|
<a href="/admin/messages.html" class="nav-link">
|
|
<i class="fas fa-envelope"></i>
|
|
<span>Messages</span>
|
|
<span class="badge" id="sidebar-unread-count">0</span>
|
|
</a>
|
|
</li>
|
|
<li class="nav-item">
|
|
<a href="/admin/subscribers.html" class="nav-link">
|
|
<i class="fas fa-bell"></i>
|
|
<span>Subscribers</span>
|
|
</a>
|
|
</li>
|
|
<li class="nav-item">
|
|
<a href="/admin/bookings.html" class="nav-link">
|
|
<i class="fas fa-calendar-check"></i>
|
|
<span>Bookings</span>
|
|
</a>
|
|
</li>
|
|
<li class="nav-item">
|
|
<a href="/admin/availability.html" class="nav-link">
|
|
<i class="fas fa-clock"></i>
|
|
<span>Availability</span>
|
|
</a>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
|
|
<div class="nav-section">
|
|
<span class="nav-section-title">Settings</span>
|
|
<ul class="nav-menu">
|
|
<li class="nav-item">
|
|
<a href="/admin/settings.html" class="nav-link">
|
|
<i class="fas fa-cog"></i>
|
|
<span>Site Settings</span>
|
|
</a>
|
|
</li>
|
|
<li class="nav-item">
|
|
<a href="/admin/users.html" class="nav-link">
|
|
<i class="fas fa-user-shield"></i>
|
|
<span>Admin Users</span>
|
|
</a>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</nav>
|
|
|
|
<div class="sidebar-footer">
|
|
<a href="/index.html" class="view-site-btn" target="_blank">
|
|
<i class="fas fa-external-link-alt"></i>
|
|
<span>View Website</span>
|
|
</a>
|
|
</div>
|
|
</aside>
|
|
|
|
<main class="main-content">
|
|
<header class="admin-header">
|
|
<div class="header-left">
|
|
<button class="mobile-toggle" id="mobile-toggle">
|
|
<i class="fas fa-bars"></i>
|
|
</button>
|
|
<h1 class="page-title">Messages</h1>
|
|
</div>
|
|
|
|
<div class="header-right">
|
|
<div class="header-search">
|
|
<i class="fas fa-search"></i>
|
|
<input type="text" placeholder="Search messages..." id="search-input">
|
|
</div>
|
|
|
|
<div class="header-user">
|
|
<div class="user-avatar">
|
|
<img src="https://ui-avatars.com/api/?name=Admin&background=0ea5e9&color=fff" alt="Admin">
|
|
</div>
|
|
<div class="user-info">
|
|
<span class="user-name">Admin</span>
|
|
<span class="user-role">Administrator</span>
|
|
</div>
|
|
<div class="user-dropdown">
|
|
<button class="dropdown-toggle">
|
|
<i class="fas fa-chevron-down"></i>
|
|
</button>
|
|
<ul class="dropdown-menu">
|
|
<li><a href="/admin/settings.html"><i class="fas fa-cog"></i> Settings</a></li>
|
|
<li class="divider"></li>
|
|
<li><a href="#" id="logout-btn"><i class="fas fa-sign-out-alt"></i> Logout</a></li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</header>
|
|
|
|
<div class="content-wrapper">
|
|
<div class="messages-grid">
|
|
<div class="messages-list">
|
|
<div class="messages-list-header">
|
|
<h3>Inbox</h3>
|
|
<span class="unread-count" id="unread-count">0 unread</span>
|
|
</div>
|
|
|
|
<div class="messages-filters">
|
|
<select id="status-filter">
|
|
<option value="">All Messages</option>
|
|
<option value="unread">Unread</option>
|
|
<option value="read">Read</option>
|
|
</select>
|
|
</div>
|
|
|
|
<div class="messages-items" id="messages-list">
|
|
<div class="empty-state">
|
|
<i class="fas fa-spinner fa-spin"></i>
|
|
<p>Loading messages...</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="message-details" id="message-details">
|
|
<div class="empty-state">
|
|
<i class="fas fa-envelope-open-text"></i>
|
|
<p>Select a message to view details</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</main>
|
|
</div>
|
|
|
|
<script src="/admin/js/admin.js"></script>
|
|
<script>
|
|
let allMessages = [];
|
|
let selectedMessageId = null;
|
|
|
|
document.addEventListener('DOMContentLoaded', function() {
|
|
loadMessages();
|
|
setupEventListeners();
|
|
checkUrlParams();
|
|
});
|
|
|
|
function setupEventListeners() {
|
|
document.getElementById('status-filter').addEventListener('change', filterMessages);
|
|
document.getElementById('search-input').addEventListener('input', MSPE.debounce(filterMessages, 300));
|
|
}
|
|
|
|
function checkUrlParams() {
|
|
const params = new URLSearchParams(window.location.search);
|
|
const messageId = params.get('id');
|
|
if (messageId) {
|
|
setTimeout(() => selectMessage(messageId), 500);
|
|
}
|
|
}
|
|
|
|
async function loadMessages() {
|
|
try {
|
|
const response = await MSPE.API.get('contact.php');
|
|
|
|
if (response && response.success) {
|
|
allMessages = response.data || [];
|
|
updateUnreadCount(response.unread || 0);
|
|
renderMessagesList(allMessages);
|
|
}
|
|
} catch (error) {
|
|
console.error('Failed to load messages:', error);
|
|
document.getElementById('messages-list').innerHTML = `
|
|
<div class="empty-state">
|
|
<i class="fas fa-exclamation-circle"></i>
|
|
<p>Failed to load messages</p>
|
|
</div>
|
|
`;
|
|
}
|
|
}
|
|
|
|
function updateUnreadCount(count) {
|
|
document.getElementById('unread-count').textContent = `${count} unread`;
|
|
document.getElementById('sidebar-unread-count').textContent = count;
|
|
|
|
if (count === 0) {
|
|
document.getElementById('sidebar-unread-count').style.display = 'none';
|
|
} else {
|
|
document.getElementById('sidebar-unread-count').style.display = 'inline';
|
|
}
|
|
}
|
|
|
|
function renderMessagesList(messages) {
|
|
const container = document.getElementById('messages-list');
|
|
|
|
if (!messages || messages.length === 0) {
|
|
container.innerHTML = `
|
|
<div class="empty-state">
|
|
<i class="fas fa-inbox"></i>
|
|
<p>No messages yet</p>
|
|
<span style="font-size: 0.875rem;">Messages from your contact form will appear here</span>
|
|
</div>
|
|
`;
|
|
return;
|
|
}
|
|
|
|
container.innerHTML = messages.map(message => {
|
|
const isUnread = (message.status === 'unread');
|
|
const isActive = (message.id === selectedMessageId);
|
|
const name = `${message.first_name || ''} ${message.last_name || ''}`.trim();
|
|
const timeAgo = getTimeAgo(new Date(message.created_at));
|
|
const rawMessage = String(message.message || '');
|
|
const preview = rawMessage.length > 60
|
|
? rawMessage.substring(0, 60) + '...'
|
|
: rawMessage;
|
|
const safeId = MSPE.escapeHtml(message.id || '');
|
|
const safeName = MSPE.escapeHtml(name || 'Unknown Sender');
|
|
const safeTimeAgo = MSPE.escapeHtml(timeAgo || '');
|
|
const safePreview = MSPE.escapeHtml(preview || '');
|
|
|
|
return `
|
|
<div class="message-item ${isUnread ? 'unread' : ''} ${isActive ? 'active' : ''}"
|
|
data-id="${safeId}">
|
|
<div class="message-header">
|
|
<span class="message-sender">
|
|
${isUnread ? '<span class="unread-dot"></span>' : ''}
|
|
${safeName}
|
|
</span>
|
|
<span class="message-meta">${safeTimeAgo}</span>
|
|
</div>
|
|
<div class="message-preview">${safePreview}</div>
|
|
</div>
|
|
`;
|
|
}).join('');
|
|
|
|
container.querySelectorAll('.message-item').forEach(item => {
|
|
item.addEventListener('click', () => {
|
|
const id = item.dataset.id;
|
|
if (id) selectMessage(id);
|
|
});
|
|
});
|
|
}
|
|
|
|
async function selectMessage(id) {
|
|
selectedMessageId = id;
|
|
|
|
// Update list selection
|
|
document.querySelectorAll('.message-item').forEach(item => {
|
|
item.classList.remove('active');
|
|
if (item.dataset.id === id) {
|
|
item.classList.add('active');
|
|
item.classList.remove('unread');
|
|
}
|
|
});
|
|
|
|
try {
|
|
const response = await MSPE.API.get(`contact.php?id=${id}`);
|
|
|
|
if (response && response.success && response.data) {
|
|
const message = response.data;
|
|
renderMessageDetails(message);
|
|
|
|
// Update message in local array
|
|
const index = allMessages.findIndex(m => m.id === id);
|
|
if (index !== -1) {
|
|
allMessages[index].status = 'read';
|
|
}
|
|
|
|
// Update unread count
|
|
const unreadCount = allMessages.filter(m => m.status === 'unread').length;
|
|
updateUnreadCount(unreadCount);
|
|
}
|
|
} catch (error) {
|
|
console.error('Failed to load message:', error);
|
|
}
|
|
}
|
|
|
|
function renderMessageDetails(message) {
|
|
const container = document.getElementById('message-details');
|
|
const name = `${message.first_name || ''} ${message.last_name || ''}`.trim();
|
|
const date = new Date(message.created_at);
|
|
const formattedDate = date.toLocaleDateString('en-US', {
|
|
weekday: 'long',
|
|
year: 'numeric',
|
|
month: 'long',
|
|
day: 'numeric',
|
|
hour: 'numeric',
|
|
minute: '2-digit'
|
|
});
|
|
|
|
const serviceLabels = {
|
|
'it-support': 'IT Support',
|
|
'cybersecurity': 'Cybersecurity',
|
|
'cloud': 'Cloud Services',
|
|
'consulting': 'Business Consulting',
|
|
'general': 'General Inquiry'
|
|
};
|
|
|
|
const safeName = MSPE.escapeHtml(name || 'Unknown Sender');
|
|
const safeDate = MSPE.escapeHtml(formattedDate || '');
|
|
const safeEmail = MSPE.escapeHtml(message.email || '');
|
|
const safePhone = MSPE.escapeHtml(message.phone || 'Not provided');
|
|
const safeCompany = MSPE.escapeHtml(message.company || 'Not provided');
|
|
const safeService = MSPE.escapeHtml(serviceLabels[message.service] || message.service || 'Not specified');
|
|
const safeBudget = message.budget ? MSPE.escapeHtml(message.budget) : '';
|
|
const safeMessageBody = MSPE.escapeHtml(message.message || 'Not provided').replace(/\n/g, '<br>');
|
|
const safeId = MSPE.escapeHtml(message.id || '');
|
|
|
|
container.innerHTML = `
|
|
<div class="message-details-header">
|
|
<div>
|
|
<h3>${safeName}</h3>
|
|
<div class="meta">${safeDate}</div>
|
|
</div>
|
|
<div class="message-actions-header">
|
|
<button class="reply-btn" data-email="${safeEmail}">
|
|
<i class="fas fa-reply"></i> Reply
|
|
</button>
|
|
<button class="delete delete-btn" data-id="${safeId}">
|
|
<i class="fas fa-trash"></i> Delete
|
|
</button>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="message-details-content">
|
|
<div class="contact-info">
|
|
<div class="contact-info-item">
|
|
<label>Email</label>
|
|
<div class="value"><a href="mailto:${safeEmail}">${safeEmail}</a></div>
|
|
</div>
|
|
<div class="contact-info-item">
|
|
<label>Phone</label>
|
|
<div class="value">${safePhone}</div>
|
|
</div>
|
|
<div class="contact-info-item">
|
|
<label>Company</label>
|
|
<div class="value">${safeCompany}</div>
|
|
</div>
|
|
<div class="contact-info-item">
|
|
<label>Service Interest</label>
|
|
<div class="value">${safeService}</div>
|
|
</div>
|
|
${message.budget ? `
|
|
<div class="contact-info-item">
|
|
<label>Budget</label>
|
|
<div class="value">${safeBudget}</div>
|
|
</div>
|
|
` : ''}
|
|
</div>
|
|
|
|
<div class="message-body">
|
|
<h4>Message</h4>
|
|
<p>${safeMessageBody}</p>
|
|
</div>
|
|
</div>
|
|
`;
|
|
|
|
const replyBtn = container.querySelector('.reply-btn');
|
|
if (replyBtn) {
|
|
replyBtn.addEventListener('click', () => {
|
|
const email = replyBtn.dataset.email || '';
|
|
if (email) replyToMessage(email);
|
|
});
|
|
}
|
|
|
|
const deleteBtn = container.querySelector('.delete-btn');
|
|
if (deleteBtn) {
|
|
deleteBtn.addEventListener('click', () => {
|
|
const id = deleteBtn.dataset.id || '';
|
|
if (id) deleteMessage(id);
|
|
});
|
|
}
|
|
}
|
|
|
|
function replyToMessage(email) {
|
|
window.location.href = `mailto:${email}`;
|
|
}
|
|
|
|
async function deleteMessage(id) {
|
|
if (!await MSPE.confirmDialog('Are you sure you want to delete this message? This action cannot be undone.')) {
|
|
return;
|
|
}
|
|
|
|
try {
|
|
const response = await MSPE.API.delete(`contact.php?id=${id}`);
|
|
|
|
if (response && response.success) {
|
|
MSPE.showNotification('Message deleted successfully', 'success');
|
|
|
|
// Remove from local array
|
|
allMessages = allMessages.filter(m => m.id !== id);
|
|
|
|
// Clear details panel
|
|
selectedMessageId = null;
|
|
document.getElementById('message-details').innerHTML = `
|
|
<div class="empty-state">
|
|
<i class="fas fa-envelope-open-text"></i>
|
|
<p>Select a message to view details</p>
|
|
</div>
|
|
`;
|
|
|
|
// Re-render list
|
|
renderMessagesList(allMessages);
|
|
|
|
// Update unread count
|
|
const unreadCount = allMessages.filter(m => m.status === 'unread').length;
|
|
updateUnreadCount(unreadCount);
|
|
}
|
|
} catch (error) {
|
|
console.error('Failed to delete message:', error);
|
|
MSPE.showNotification('Failed to delete message', 'error');
|
|
}
|
|
}
|
|
|
|
function filterMessages() {
|
|
const status = document.getElementById('status-filter').value;
|
|
const search = document.getElementById('search-input').value.toLowerCase();
|
|
|
|
let filtered = allMessages;
|
|
|
|
if (status) {
|
|
filtered = filtered.filter(m => m.status === status);
|
|
}
|
|
|
|
if (search) {
|
|
filtered = filtered.filter(m =>
|
|
m.first_name.toLowerCase().includes(search) ||
|
|
m.last_name.toLowerCase().includes(search) ||
|
|
m.email.toLowerCase().includes(search) ||
|
|
m.message.toLowerCase().includes(search) ||
|
|
(m.company && m.company.toLowerCase().includes(search))
|
|
);
|
|
}
|
|
|
|
renderMessagesList(filtered);
|
|
}
|
|
|
|
function getTimeAgo(date) {
|
|
const now = new Date();
|
|
const diffMs = now - date;
|
|
const diffMins = Math.floor(diffMs / 60000);
|
|
const diffHours = Math.floor(diffMs / 3600000);
|
|
const diffDays = Math.floor(diffMs / 86400000);
|
|
|
|
if (diffMins < 1) return 'Just now';
|
|
if (diffMins < 60) return `${diffMins}m ago`;
|
|
if (diffHours < 24) return `${diffHours}h ago`;
|
|
if (diffDays < 7) return `${diffDays}d ago`;
|
|
|
|
return date.toLocaleDateString('en-US', { month: 'short', day: 'numeric' });
|
|
}
|
|
</script>
|
|
</body>
|
|
</html>
|