File: /var/www/indoadvisory_new/webapp/src/routes/inquiries.js
import { Hono } from 'hono';
import { formatDate } from '../utils/database';
const inquiries = new Hono();
// Inquiries List
inquiries.get('/', async (c) => {
try {
const inquiriesList = await c.env.DB.prepare('SELECT * FROM contact_inquiries ORDER BY created_at DESC').all();
const user = c.get('user');
return c.html(`
<!DOCTYPE html>
<html lang="id">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Kelola Inquiry - Admin IndoAdvisory</title>
<script src="https://cdn.tailwindcss.com"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css" rel="stylesheet">
</head>
<body class="bg-gray-100">
${adminNavbar(user)}
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8">
<div class="flex justify-between items-center mb-8">
<h1 class="text-3xl font-bold text-gray-800">Kelola Inquiry</h1>
<div class="flex space-x-4">
<select id="statusFilter" class="px-4 py-2 border border-gray-300 rounded-lg">
<option value="">Semua Status</option>
<option value="new">Baru</option>
<option value="contacted">Dihubungi</option>
<option value="closed">Ditutup</option>
</select>
</div>
</div>
<div class="bg-white rounded-xl shadow-lg overflow-hidden">
<div class="overflow-x-auto">
<table class="w-full">
<thead class="bg-gray-50">
<tr>
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Nama & Email</th>
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Perusahaan</th>
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Layanan</th>
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Status</th>
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Tanggal</th>
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Aksi</th>
</tr>
</thead>
<tbody class="bg-white divide-y divide-gray-200">
${inquiriesList.results.map(inquiry => `
<tr class="hover:bg-gray-50">
<td class="px-6 py-4">
<div>
<div class="text-sm font-medium text-gray-900">${inquiry.name}</div>
<div class="text-sm text-gray-500">${inquiry.email}</div>
</div>
</td>
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-900">
${inquiry.company || '-'}
</td>
<td class="px-6 py-4 whitespace-nowrap">
<span class="px-2 py-1 text-xs font-semibold rounded-full bg-blue-100 text-blue-800">
${inquiry.service || 'Umum'}
</span>
</td>
<td class="px-6 py-4 whitespace-nowrap">
<select onchange="updateStatus(${inquiry.id}, this.value)" class="text-xs font-semibold rounded-full border-0 ${inquiry.status === 'new' ? 'bg-orange-100 text-orange-800' : inquiry.status === 'contacted' ? 'bg-blue-100 text-blue-800' : 'bg-green-100 text-green-800'}">
<option value="new" ${inquiry.status === 'new' ? 'selected' : ''}>Baru</option>
<option value="contacted" ${inquiry.status === 'contacted' ? 'selected' : ''}>Dihubungi</option>
<option value="closed" ${inquiry.status === 'closed' ? 'selected' : ''}>Ditutup</option>
</select>
</td>
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">
${formatDate(inquiry.created_at)}
</td>
<td class="px-6 py-4 whitespace-nowrap text-sm font-medium space-x-2">
<button onclick="viewMessage(${inquiry.id}, '${inquiry.message.replace(/'/g, "\\'")}', '${inquiry.name}')" class="text-blue-600 hover:text-blue-900">
<i class="fas fa-eye mr-1"></i>Lihat
</button>
<a href="mailto:${inquiry.email}?subject=Re: Inquiry dari ${inquiry.name}&body=Halo ${inquiry.name},%0A%0ATerima kasih atas inquiry Anda." class="text-green-600 hover:text-green-900">
<i class="fas fa-envelope mr-1"></i>Email
</a>
<button onclick="deleteInquiry(${inquiry.id})" class="text-red-600 hover:text-red-900">
<i class="fas fa-trash mr-1"></i>Hapus
</button>
</td>
</tr>
`).join('')}
</tbody>
</table>
</div>
</div>
</div>
<!-- Message Modal -->
<div id="messageModal" class="hidden fixed inset-0 bg-gray-600 bg-opacity-50 overflow-y-auto h-full w-full z-50">
<div class="relative top-20 mx-auto p-5 border w-11/12 md:w-3/4 lg:w-1/2 shadow-lg rounded-md bg-white">
<div class="mt-3">
<div class="flex justify-between items-center mb-4">
<h3 class="text-lg font-medium text-gray-900" id="modalTitle">Pesan Inquiry</h3>
<button onclick="closeModal()" class="text-gray-400 hover:text-gray-600">
<i class="fas fa-times"></i>
</button>
</div>
<div class="mt-2 px-7 py-3">
<p class="text-sm text-gray-500" id="modalMessage"></p>
</div>
<div class="items-center px-4 py-3">
<button onclick="closeModal()" class="px-4 py-2 bg-blue-500 text-white text-base font-medium rounded-md w-full shadow-sm hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-blue-300">
Tutup
</button>
</div>
</div>
</div>
</div>
<script>
function updateStatus(id, status) {
fetch('/admin/inquiries/' + id + '/status', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ status: status })
}).then(() => window.location.reload());
}
function deleteInquiry(id) {
if (confirm('Apakah Anda yakin ingin menghapus inquiry ini?')) {
fetch('/admin/inquiries/' + id + '/delete', { method: 'POST' })
.then(() => window.location.reload());
}
}
function viewMessage(id, message, name) {
document.getElementById('modalTitle').textContent = 'Pesan dari ' + name;
document.getElementById('modalMessage').textContent = message;
document.getElementById('messageModal').classList.remove('hidden');
}
function closeModal() {
document.getElementById('messageModal').classList.add('hidden');
}
// Filter functionality
document.getElementById('statusFilter').addEventListener('change', function() {
const filterValue = this.value;
const rows = document.querySelectorAll('tbody tr');
rows.forEach(row => {
const statusSelect = row.querySelector('select');
const currentStatus = statusSelect.value;
if (filterValue === '' || currentStatus === filterValue) {
row.style.display = '';
} else {
row.style.display = 'none';
}
});
});
</script>
</body>
</html>
`);
}
catch (error) {
return c.html(`<div>Error: ${error.message}</div>`);
}
});
// Update inquiry status
inquiries.post('/:id/status', async (c) => {
try {
const id = c.req.param('id');
const { status } = await c.req.json();
await c.env.DB.prepare('UPDATE contact_inquiries SET status = ? WHERE id = ?').bind(status, id).run();
return c.json({ success: true });
}
catch (error) {
return c.json({ error: error.message }, 500);
}
});
// Delete inquiry
inquiries.post('/:id/delete', async (c) => {
try {
const id = c.req.param('id');
await c.env.DB.prepare('DELETE FROM contact_inquiries WHERE id = ?').bind(id).run();
return c.json({ success: true });
}
catch (error) {
return c.json({ error: error.message }, 500);
}
});
// Admin Navbar Component
function adminNavbar(user) {
return `
<nav class="bg-white shadow-lg border-b">
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<div class="flex justify-between items-center h-16">
<div class="flex items-center">
<h1 class="text-xl font-bold text-gray-800">
<i class="fas fa-chart-line text-blue-600 mr-2"></i>
IndoAdvisory Admin
</h1>
</div>
<div class="hidden md:flex items-center space-x-6">
<a href="/admin/dashboard" class="text-gray-700 hover:text-blue-600 px-3 py-2 rounded-md text-sm font-medium">
<i class="fas fa-tachometer-alt mr-1"></i>
Dashboard
</a>
<a href="/admin/articles" class="text-gray-700 hover:text-blue-600 px-3 py-2 rounded-md text-sm font-medium">
<i class="fas fa-newspaper mr-1"></i>
Artikel
</a>
<a href="/admin/inquiries" class="text-blue-600 font-semibold px-3 py-2 rounded-md text-sm font-medium">
<i class="fas fa-envelope mr-1"></i>
Inquiry
</a>
<a href="/admin/team" class="text-gray-700 hover:text-blue-600 px-3 py-2 rounded-md text-sm font-medium">
<i class="fas fa-users mr-1"></i>
Tim
</a>
<a href="/admin/settings" class="text-gray-700 hover:text-blue-600 px-3 py-2 rounded-md text-sm font-medium">
<i class="fas fa-cog mr-1"></i>
Settings
</a>
<a href="/" target="_blank" class="text-gray-700 hover:text-blue-600 px-3 py-2 rounded-md text-sm font-medium">
<i class="fas fa-external-link-alt mr-1"></i>
Lihat Website
</a>
</div>
<div class="flex items-center">
<span class="text-gray-700 mr-4">
<i class="fas fa-user mr-1"></i>
${user.name}
</span>
<a href="/admin/logout" class="text-red-600 hover:text-red-700 px-3 py-2 rounded-md text-sm font-medium">
<i class="fas fa-sign-out-alt mr-1"></i>
Logout
</a>
</div>
</div>
</div>
</nav>
`;
}
export default inquiries;