305 lines
10 KiB
React
305 lines
10 KiB
React
import { useState, useEffect, useCallback } from 'react';
|
||
import { tokenService } from '../services/TokenService';
|
||
import { messageEventResponseApi } from '../api/messageEventResponseApi';
|
||
import { scheduleApi } from '../api/scheduleApi';
|
||
import './ViewSentMessages.css';
|
||
|
||
const ViewSentMessages = ({
|
||
isOpen,
|
||
onClose,
|
||
title = 'View Sent Messages',
|
||
}) => {
|
||
const [sentMessages, setSentMessages] = useState([]);
|
||
const [scheduledMessages, setScheduledMessages] = useState([]);
|
||
const [lastUpdated, setLastUpdated] = useState(null);
|
||
const [loading, setLoading] = useState(true);
|
||
const [error, setError] = useState(null);
|
||
const [searchTerm, setSearchTerm] = useState('');
|
||
const [activeTab, setActiveTab] = useState('sent');
|
||
|
||
// Fetch the sent messages or Message Event Responses
|
||
const fetchSentMessages = useCallback(async () => {
|
||
try {
|
||
setLoading(true);
|
||
setError(null);
|
||
|
||
const userId = tokenService.getUserId();
|
||
const response =
|
||
await messageEventResponseApi.getMessageEventResponsesByUserId(
|
||
userId,
|
||
tokenService.bearerToken()
|
||
);
|
||
|
||
if (response) {
|
||
setLastUpdated(new Date());
|
||
setSentMessages(response.data);
|
||
} else {
|
||
throw new Error(response.message || 'Failed to load sent messages');
|
||
}
|
||
} catch (err) {
|
||
setError(err.message || 'Failed to load sent messages.');
|
||
setSentMessages([]);
|
||
} finally {
|
||
setLoading(false);
|
||
}
|
||
}, []);
|
||
|
||
const fetchScheduledMessages = useCallback(async () => {
|
||
try {
|
||
const userId = tokenService.getUserId();
|
||
const response = await scheduleApi.getScheduledMessage(
|
||
userId,
|
||
tokenService.bearerToken()
|
||
);
|
||
if (response) {
|
||
const scheduledMessages = response.data;
|
||
|
||
setScheduledMessages(scheduledMessages);
|
||
} else {
|
||
throw new Error(response.message || 'Failed to get scheduled messages');
|
||
}
|
||
} catch (err) {
|
||
console.error('Failed to load scheduled messages:', err);
|
||
setScheduledMessages([]);
|
||
}
|
||
}, []);
|
||
|
||
const handleRefresh = () => {
|
||
if (activeTab === 'sent') {
|
||
fetchSentMessages();
|
||
} else {
|
||
fetchScheduledMessages();
|
||
}
|
||
};
|
||
|
||
useEffect(() => {
|
||
if (isOpen) {
|
||
console.log('Fetching sent messages');
|
||
fetchSentMessages();
|
||
}
|
||
}, [isOpen, fetchSentMessages]);
|
||
|
||
// Fetch scheduled messages when tab is switched
|
||
useEffect(() => {
|
||
if (activeTab === 'scheduled' && isOpen) {
|
||
fetchScheduledMessages();
|
||
}
|
||
}, [activeTab, isOpen, fetchScheduledMessages]);
|
||
|
||
const filteredSentMessages = sentMessages.filter((sentMessage) => {
|
||
const searchLower = searchTerm.toLowerCase();
|
||
return (
|
||
(sentMessage.status &&
|
||
sentMessage.status.toLowerCase().includes(searchLower)) ||
|
||
(sentMessage.sent &&
|
||
sentMessage.sent.toLowerCase().includes(searchLower)) ||
|
||
(sentMessage.id && sentMessage.id.toString().includes(searchTerm))
|
||
);
|
||
});
|
||
|
||
// Filter scheduled messages
|
||
const filteredScheduledMessages = scheduledMessages.filter((message) => {
|
||
const searchLower = searchTerm.toLowerCase();
|
||
return (
|
||
(message.status && message.status.toLowerCase().includes(searchLower)) ||
|
||
(message.id && message.id.toString().includes(searchTerm))
|
||
);
|
||
});
|
||
|
||
const formatLastUpdated = () => {
|
||
if (!lastUpdated) return 'Never';
|
||
return lastUpdated.toLocaleTimeString([], {
|
||
hour: '2-digit',
|
||
minute: '2-digit',
|
||
});
|
||
};
|
||
|
||
// Format date for scheduled messages
|
||
const formatScheduledDate = (dateString) => {
|
||
return new Date(dateString).toLocaleString();
|
||
};
|
||
|
||
// Get status badge styling
|
||
const getStatusBadgeClass = (status) => {
|
||
switch (status) {
|
||
case 'PROCESSING':
|
||
return 'status-processing';
|
||
case 'SENT':
|
||
return 'status-sent';
|
||
case 'FAILED':
|
||
return 'status-failed';
|
||
default:
|
||
return 'status-default';
|
||
}
|
||
};
|
||
|
||
if (!isOpen) return null;
|
||
|
||
return (
|
||
<div className="view-sent-message-modal-overlay" onClick={onClose}>
|
||
<div
|
||
className="view-sent-message-modal"
|
||
onClick={(e) => e.stopPropagation()}
|
||
>
|
||
<div className="view-sent-message-card">
|
||
<div className="view-sent-message-header">
|
||
<h2 className="view-sent-message-title">{title}</h2>
|
||
<button className="close-btn" onClick={onClose} aria-label="Close">
|
||
×
|
||
</button>
|
||
</div>
|
||
|
||
{/* Add tabs for navigation */}
|
||
<div className="view-sent-message-tabs">
|
||
<button
|
||
className={`tab-button ${activeTab === 'sent' ? 'active' : ''}`}
|
||
onClick={() => setActiveTab('sent')}
|
||
>
|
||
Sent Messages
|
||
</button>
|
||
<button
|
||
className={`tab-button ${activeTab === 'scheduled' ? 'active' : ''}`}
|
||
onClick={() => setActiveTab('scheduled')}
|
||
>
|
||
Scheduled Messages
|
||
</button>
|
||
</div>
|
||
|
||
{/* Search input */}
|
||
<div className="search-container">
|
||
<input
|
||
type="text"
|
||
placeholder="Search messages..."
|
||
value={searchTerm}
|
||
onChange={(e) => setSearchTerm(e.target.value)}
|
||
className="search-input"
|
||
/>
|
||
</div>
|
||
|
||
<div className="view-sent-message-form">
|
||
{error && (
|
||
<div className="submit-error">
|
||
<div style={{ marginBottom: '8px' }}>{error}</div>
|
||
<button
|
||
onClick={handleRefresh}
|
||
style={{
|
||
background: '#ef4444',
|
||
color: 'white',
|
||
border: 'none',
|
||
borderRadius: '4px',
|
||
padding: '6px 12px',
|
||
cursor: 'pointer',
|
||
fontSize: '12px',
|
||
}}
|
||
>
|
||
Retry Now
|
||
</button>
|
||
</div>
|
||
)}
|
||
|
||
{loading ? (
|
||
<div style={{ textAlign: 'center', padding: '40px' }}>
|
||
<div className="loading-spinner" />
|
||
<p>Loading messages...</p>
|
||
</div>
|
||
) : (
|
||
<>
|
||
{/* Sent Messages Tab Content */}
|
||
{activeTab === 'sent' && (
|
||
<div className="messages-section">
|
||
<div className="section-header">
|
||
<h3>Sent Messages</h3>
|
||
<span className="last-updated">
|
||
Last updated: {formatLastUpdated()}
|
||
</span>
|
||
</div>
|
||
|
||
{filteredSentMessages.length > 0 ? (
|
||
<div className="view-sent-message-list-container">
|
||
<table className="view-sent-message-table">
|
||
<thead>
|
||
<tr>
|
||
<th>ID</th>
|
||
<th>Status</th>
|
||
<th>Sent Time</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
{filteredSentMessages.map((message) => (
|
||
<tr key={message.id}>
|
||
<td>{message.id.substring(0, 8)}...</td>
|
||
<td>
|
||
<span
|
||
className={`status-badge ${getStatusBadgeClass(message.status)}`}
|
||
>
|
||
{message.status}
|
||
</span>
|
||
</td>
|
||
<td>{message.sent || 'N/A'}</td>
|
||
</tr>
|
||
))}
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
) : (
|
||
<div className="no-messages">No sent messages found.</div>
|
||
)}
|
||
</div>
|
||
)}
|
||
|
||
{/* Scheduled Messages Tab Content */}
|
||
{activeTab === 'scheduled' && (
|
||
<div className="messages-section">
|
||
<div className="section-header">
|
||
<h3>Scheduled Messages</h3>
|
||
</div>
|
||
|
||
{filteredScheduledMessages.length > 0 ? (
|
||
<div className="view-sent-message-list-container">
|
||
<table className="view-sent-message-table">
|
||
<thead>
|
||
<tr>
|
||
<th>ID</th>
|
||
<th>Scheduled Time</th>
|
||
<th>Created Time</th>
|
||
<th>Status</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
{filteredScheduledMessages.map((message) => (
|
||
<tr key={message.id}>
|
||
<td>{message.id.substring(0, 8)}...</td>
|
||
<td>
|
||
{formatScheduledDate(message.scheduled)}
|
||
</td>
|
||
<td>{formatScheduledDate(message.created)}</td>
|
||
<td>
|
||
<span
|
||
className={`status-badge ${getStatusBadgeClass(message.status)}`}
|
||
>
|
||
{message.status}
|
||
</span>
|
||
</td>
|
||
</tr>
|
||
))}
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
) : (
|
||
<div className="no-messages">
|
||
No scheduled messages found.
|
||
</div>
|
||
)}
|
||
</div>
|
||
)}
|
||
</>
|
||
)}
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
);
|
||
};
|
||
|
||
export default ViewSentMessages;
|