All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
184 lines
5.8 KiB
JavaScript
184 lines
5.8 KiB
JavaScript
import { useState, useEffect } from 'react';
|
|
import { useNavigate } from 'react-router-dom';
|
|
import api from '../api';
|
|
import './MyMessages.css';
|
|
|
|
function MyMessages() {
|
|
const [messages, setMessages] = useState([]);
|
|
const [loading, setLoading] = useState(true);
|
|
const [error, setError] = useState('');
|
|
const [selectedMessage, setSelectedMessage] = useState(null);
|
|
const navigate = useNavigate();
|
|
|
|
useEffect(() => {
|
|
fetchMessages();
|
|
}, []);
|
|
|
|
const fetchMessages = async () => {
|
|
try {
|
|
const token = localStorage.getItem('token');
|
|
if (!token) {
|
|
navigate('/login');
|
|
return;
|
|
}
|
|
|
|
const response = await api.get('/my-messages');
|
|
setMessages(response.data);
|
|
setLoading(false);
|
|
} catch (err) {
|
|
console.error('Error fetching messages:', err);
|
|
setError('Failed to load messages');
|
|
setLoading(false);
|
|
|
|
if (err.response?.status === 401) {
|
|
navigate('/login');
|
|
}
|
|
}
|
|
};
|
|
|
|
const getStatusColor = (status) => {
|
|
const colors = {
|
|
new: '#3b82f6',
|
|
read: '#f59e0b',
|
|
replied: '#10b981',
|
|
};
|
|
return colors[status] || '#6b7280';
|
|
};
|
|
|
|
const formatDate = (dateString) => {
|
|
return new Date(dateString).toLocaleDateString('en-US', {
|
|
year: 'numeric',
|
|
month: 'short',
|
|
day: 'numeric',
|
|
hour: '2-digit',
|
|
minute: '2-digit',
|
|
});
|
|
};
|
|
|
|
if (loading) {
|
|
return <div className="loading">Loading your messages...</div>;
|
|
}
|
|
|
|
return (
|
|
<div className="messages-page">
|
|
<div className="messages-container">
|
|
<div className="messages-header">
|
|
<h1>My Messages</h1>
|
|
<p>View your contact messages and admin responses</p>
|
|
</div>
|
|
|
|
{error && (
|
|
<div className="error-message">
|
|
{error}
|
|
</div>
|
|
)}
|
|
|
|
{messages.length === 0 ? (
|
|
<div className="no-messages">
|
|
<div className="no-messages-icon">💬</div>
|
|
<h3>No messages yet</h3>
|
|
<p>You haven't sent any contact messages yet.</p>
|
|
<button onClick={() => navigate('/contact')} className="btn">
|
|
Send a Message
|
|
</button>
|
|
</div>
|
|
) : (
|
|
<div className="messages-list">
|
|
{messages.map((message) => (
|
|
<div key={message.id} className="message-card">
|
|
<div className="message-card-header">
|
|
<div className="message-title-section">
|
|
<h3>{message.subject}</h3>
|
|
<p className="message-date">Sent on {formatDate(message.created_at)}</p>
|
|
</div>
|
|
<span
|
|
className="status-badge"
|
|
style={{
|
|
backgroundColor: getStatusColor(message.status) + '20',
|
|
color: getStatusColor(message.status),
|
|
border: `1px solid ${getStatusColor(message.status)}`
|
|
}}
|
|
>
|
|
{message.status.toUpperCase()}
|
|
</span>
|
|
</div>
|
|
|
|
<div className="message-content">
|
|
<h4>Your Message:</h4>
|
|
<div className="message-box">
|
|
<p>{message.message}</p>
|
|
</div>
|
|
</div>
|
|
|
|
{message.admin_notes && (
|
|
<div className="admin-response">
|
|
<h4>
|
|
<span className="response-icon">✓</span>
|
|
Admin Response:
|
|
</h4>
|
|
<div className="response-box">
|
|
<p>{message.admin_notes}</p>
|
|
</div>
|
|
</div>
|
|
)}
|
|
|
|
{!message.admin_notes && message.status === 'new' && (
|
|
<div className="waiting-response">
|
|
<p>⏳ Waiting for admin response...</p>
|
|
</div>
|
|
)}
|
|
|
|
<div className="message-details-section">
|
|
<button
|
|
onClick={() =>
|
|
setSelectedMessage(
|
|
selectedMessage?.id === message.id ? null : message
|
|
)
|
|
}
|
|
className="details-toggle"
|
|
>
|
|
{selectedMessage?.id === message.id ? '▲ Hide Details' : '▼ Show Details'}
|
|
</button>
|
|
|
|
{selectedMessage?.id === message.id && (
|
|
<div className="message-details">
|
|
<div className="details-grid">
|
|
<div className="detail-item">
|
|
<strong>Name:</strong>
|
|
<span>{message.full_name}</span>
|
|
</div>
|
|
<div className="detail-item">
|
|
<strong>Email:</strong>
|
|
<span>{message.email}</span>
|
|
</div>
|
|
{message.phone && (
|
|
<div className="detail-item">
|
|
<strong>Phone:</strong>
|
|
<span>{message.phone}</span>
|
|
</div>
|
|
)}
|
|
<div className="detail-item">
|
|
<strong>Read Status:</strong>
|
|
<span>{message.is_read ? 'Read' : 'Unread'}</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
)}
|
|
</div>
|
|
</div>
|
|
))}
|
|
</div>
|
|
)}
|
|
|
|
<div className="messages-actions">
|
|
<button onClick={() => navigate('/')} className="btn btn-secondary">
|
|
← Back to Home
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
export default MyMessages;
|