HEX
Server: Apache/2.4.65 (Debian)
System: Linux kubikelcreative 5.10.0-35-amd64 #1 SMP Debian 5.10.237-1 (2025-05-19) x86_64
User: www-data (33)
PHP: 8.4.13
Disabled: NONE
Upload Files
File: /var/www/indoadvisory_new/webapp/src/routes/team.js
import { Hono } from 'hono';
const team = new Hono();
// Team Members List
team.get('/', async (c) => {
    try {
        const teamList = await c.env.DB.prepare('SELECT * FROM team_members ORDER BY sort_order ASC, created_at ASC').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 Tim - 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 Tim Ahli</h1>
                  <a href="/admin/team/create" class="bg-blue-600 text-white px-6 py-3 rounded-lg font-semibold hover:bg-blue-700 transition-colors">
                      <i class="fas fa-plus mr-2"></i>
                      Tambah Anggota Tim
                  </a>
              </div>
              
              <div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
                  ${teamList.results.map(member => `
                      <div class="bg-white rounded-xl shadow-lg overflow-hidden ${!member.is_active ? 'opacity-60' : ''}">
                          <div class="p-6">
                              <div class="flex items-center justify-between mb-4">
                                  <div class="w-16 h-16 bg-gradient-to-br from-blue-400 to-blue-600 rounded-full flex items-center justify-center">
                                      ${member.image_url ?
            `<img src="${member.image_url}" alt="${member.name}" class="w-16 h-16 rounded-full object-cover">` :
            `<i class="fas fa-user text-white text-xl"></i>`}
                                  </div>
                                  <div class="text-right">
                                      <span class="text-xs font-medium px-2 py-1 rounded-full ${member.is_active ? 'bg-green-100 text-green-800' : 'bg-gray-100 text-gray-600'}">
                                          ${member.is_active ? 'Aktif' : 'Nonaktif'}
                                      </span>
                                  </div>
                              </div>
                              
                              <h3 class="text-xl font-bold text-gray-900 mb-2">${member.name}</h3>
                              <p class="text-blue-600 font-medium mb-3">${member.position_id}</p>
                              
                              ${member.bio_id ? `
                                  <p class="text-gray-600 text-sm mb-4 line-clamp-3">${member.bio_id}</p>
                              ` : ''}
                              
                              <div class="flex items-center justify-between">
                                  <div class="flex space-x-2">
                                      ${member.email ? `
                                          <a href="mailto:${member.email}" class="text-gray-500 hover:text-blue-600">
                                              <i class="fas fa-envelope"></i>
                                          </a>
                                      ` : ''}
                                      ${member.linkedin_url ? `
                                          <a href="${member.linkedin_url}" target="_blank" class="text-gray-500 hover:text-blue-600">
                                              <i class="fab fa-linkedin"></i>
                                          </a>
                                      ` : ''}
                                  </div>
                                  
                                  <div class="flex space-x-2">
                                      <a href="/admin/team/edit/${member.id}" class="text-blue-600 hover:text-blue-900">
                                          <i class="fas fa-edit"></i>
                                      </a>
                                      <button onclick="toggleStatus(${member.id}, ${member.is_active})" class="text-${member.is_active ? 'orange' : 'green'}-600 hover:text-${member.is_active ? 'orange' : 'green'}-900">
                                          <i class="fas fa-${member.is_active ? 'pause' : 'play'}"></i>
                                      </button>
                                      <button onclick="deleteMember(${member.id})" class="text-red-600 hover:text-red-900">
                                          <i class="fas fa-trash"></i>
                                      </button>
                                  </div>
                              </div>
                              
                              <div class="mt-4 text-center">
                                  <span class="text-xs text-gray-500">Urutan: ${member.sort_order}</span>
                              </div>
                          </div>
                      </div>
                  `).join('')}
                  
                  ${teamList.results.length === 0 ? `
                      <div class="col-span-full text-center py-16">
                          <i class="fas fa-users text-gray-400 text-6xl mb-4"></i>
                          <h3 class="text-xl font-semibold text-gray-600 mb-2">Belum Ada Anggota Tim</h3>
                          <p class="text-gray-500 mb-6">Tambahkan anggota tim pertama untuk mulai membangun profil perusahaan</p>
                          <a href="/admin/team/create" class="bg-blue-600 text-white px-6 py-3 rounded-lg font-semibold hover:bg-blue-700 transition-colors">
                              <i class="fas fa-plus mr-2"></i>
                              Tambah Anggota Tim
                          </a>
                      </div>
                  ` : ''}
              </div>
          </div>
          
          <script>
              function toggleStatus(id, currentStatus) {
                  const newStatus = !currentStatus;
                  fetch('/admin/team/' + id + '/toggle', { 
                      method: 'POST',
                      headers: { 'Content-Type': 'application/json' },
                      body: JSON.stringify({ is_active: newStatus })
                  }).then(() => window.location.reload());
              }
              
              function deleteMember(id) {
                  if (confirm('Apakah Anda yakin ingin menghapus anggota tim ini?')) {
                      fetch('/admin/team/' + id + '/delete', { method: 'POST' })
                          .then(() => window.location.reload());
                  }
              }
          </script>
      </body>
      </html>
    `);
    }
    catch (error) {
        return c.html(`<div>Error: ${error.message}</div>`);
    }
});
// Create Team Member Form
team.get('/create', (c) => {
    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>Tambah Anggota Tim - 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-4xl mx-auto px-4 sm:px-6 lg:px-8 py-8">
            <div class="mb-8">
                <h1 class="text-3xl font-bold text-gray-800">Tambah Anggota Tim</h1>
                <p class="text-gray-600 mt-2">Tambahkan profil anggota tim baru</p>
            </div>
            
            <form action="/admin/team/create" method="POST" class="bg-white rounded-xl shadow-lg p-8 space-y-6">
                <div class="grid grid-cols-1 md:grid-cols-2 gap-6">
                    <div>
                        <label class="block text-sm font-medium text-gray-700 mb-2">Nama Lengkap</label>
                        <input 
                            type="text" 
                            name="name" 
                            required 
                            class="w-full px-4 py-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent"
                            placeholder="Dr. Budi Santoso"
                        />
                    </div>
                    
                    <div>
                        <label class="block text-sm font-medium text-gray-700 mb-2">Email</label>
                        <input 
                            type="email" 
                            name="email" 
                            class="w-full px-4 py-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent"
                            placeholder="budi.santoso@indoadvisory.co.id"
                        />
                    </div>
                </div>
                
                <div class="grid grid-cols-1 md:grid-cols-2 gap-6">
                    <div>
                        <label class="block text-sm font-medium text-gray-700 mb-2">Posisi (Bahasa Indonesia)</label>
                        <input 
                            type="text" 
                            name="position_id" 
                            required 
                            class="w-full px-4 py-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent"
                            placeholder="Managing Partner"
                        />
                    </div>
                    
                    <div>
                        <label class="block text-sm font-medium text-gray-700 mb-2">Posisi (English)</label>
                        <input 
                            type="text" 
                            name="position_en" 
                            required 
                            class="w-full px-4 py-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent"
                            placeholder="Managing Partner"
                        />
                    </div>
                </div>
                
                <div>
                    <label class="block text-sm font-medium text-gray-700 mb-2">Bio/Pengalaman (Bahasa Indonesia)</label>
                    <textarea 
                        name="bio_id" 
                        rows="4" 
                        class="w-full px-4 py-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent"
                        placeholder="Pengalaman dan latar belakang pendidikan..."
                    ></textarea>
                </div>
                
                <div>
                    <label class="block text-sm font-medium text-gray-700 mb-2">Bio/Experience (English)</label>
                    <textarea 
                        name="bio_en" 
                        rows="4" 
                        class="w-full px-4 py-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent"
                        placeholder="Experience and educational background..."
                    ></textarea>
                </div>
                
                <div class="grid grid-cols-1 md:grid-cols-2 gap-6">
                    <div>
                        <label class="block text-sm font-medium text-gray-700 mb-2">LinkedIn URL</label>
                        <input 
                            type="url" 
                            name="linkedin_url" 
                            class="w-full px-4 py-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent"
                            placeholder="https://linkedin.com/in/username"
                        />
                    </div>
                    
                    <div>
                        <label class="block text-sm font-medium text-gray-700 mb-2">URL Foto Profil</label>
                        <input 
                            type="url" 
                            name="image_url" 
                            class="w-full px-4 py-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent"
                            placeholder="https://example.com/foto-profil.jpg"
                        />
                    </div>
                </div>
                
                <div class="grid grid-cols-1 md:grid-cols-2 gap-6">
                    <div>
                        <label class="block text-sm font-medium text-gray-700 mb-2">Urutan Tampil</label>
                        <input 
                            type="number" 
                            name="sort_order" 
                            min="0" 
                            value="0"
                            class="w-full px-4 py-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent"
                        />
                        <p class="text-sm text-gray-500 mt-1">Semakin kecil angka, semakin atas urutan tampil</p>
                    </div>
                    
                    <div>
                        <label class="block text-sm font-medium text-gray-700 mb-2">Status</label>
                        <select 
                            name="is_active" 
                            class="w-full px-4 py-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent"
                        >
                            <option value="1">Aktif</option>
                            <option value="0">Nonaktif</option>
                        </select>
                    </div>
                </div>
                
                <div class="flex justify-between items-center pt-6">
                    <a href="/admin/team" class="px-6 py-3 text-gray-700 bg-gray-200 rounded-lg hover:bg-gray-300 transition-colors">
                        <i class="fas fa-arrow-left mr-2"></i>
                        Kembali
                    </a>
                    <button 
                        type="submit" 
                        class="px-8 py-3 bg-blue-600 text-white rounded-lg font-semibold hover:bg-blue-700 transition-colors"
                    >
                        <i class="fas fa-save mr-2"></i>
                        Simpan Anggota Tim
                    </button>
                </div>
            </form>
        </div>
    </body>
    </html>
  `);
});
// Create Team Member Handler
team.post('/create', async (c) => {
    try {
        const formData = await c.req.parseBody();
        const now = new Date().toISOString();
        await c.env.DB.prepare(`INSERT INTO team_members (name, position_id, position_en, bio_id, bio_en, email, linkedin_url, image_url, sort_order, is_active, created_at, updated_at) 
       VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`).bind(formData.name, formData.position_id, formData.position_en, formData.bio_id || null, formData.bio_en || null, formData.email || null, formData.linkedin_url || null, formData.image_url || null, parseInt(formData.sort_order) || 0, parseInt(formData.is_active) === 1, now, now).run();
        return c.redirect('/admin/team');
    }
    catch (error) {
        return c.html(`<script>alert('Error: ${error.message}'); window.history.back();</script>`);
    }
});
// Toggle team member status
team.post('/:id/toggle', async (c) => {
    try {
        const id = c.req.param('id');
        const { is_active } = await c.req.json();
        await c.env.DB.prepare('UPDATE team_members SET is_active = ?, updated_at = ? WHERE id = ?').bind(is_active, new Date().toISOString(), id).run();
        return c.json({ success: true });
    }
    catch (error) {
        return c.json({ error: error.message }, 500);
    }
});
// Delete team member
team.post('/:id/delete', async (c) => {
    try {
        const id = c.req.param('id');
        await c.env.DB.prepare('DELETE FROM team_members 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-gray-700 hover:text-blue-600 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-blue-600 font-semibold 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 team;