GhostManSec
Server: LiteSpeed
System: Linux premium256.web-hosting.com 4.18.0-553.54.1.lve.el8.x86_64 #1 SMP Wed Jun 4 13:01:13 UTC 2025 x86_64
User: niyknzcu (1843)
PHP: 8.0.30
Disabled: NONE
Upload Files
File: /home/niyknzcu/nexlancedigital.com/clients.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Clients โ€” Nexlance</title>
<link rel="stylesheet" href="dashboard.css">
<link rel="stylesheet" href="app.css">
<!-- Firebase SDK -->
    <script src="https://www.gstatic.com/firebasejs/10.14.1/firebase-app-compat.js"></script>
    <script src="https://www.gstatic.com/firebasejs/10.14.1/firebase-auth-compat.js"></script>
    <script src="https://www.gstatic.com/firebasejs/10.14.1/firebase-firestore-compat.js"></script>
</head>
<body>
<div class="container">

  <!-- Sidebar -->
  <aside class="sidebar">
    <h2 class="logo">Nexlance</h2>
    <ul class="nav">
      <li><a href="dashboard.html">๐Ÿ“Š Dashboard</a></li>
      <li class="active"><a href="clients.html">๐Ÿ‘ฅ Clients</a></li>
      <li><a href="team.html">๐Ÿง‘โ€๐Ÿ’ผ Team</a></li>
      <li><a href="projects.html">๐Ÿ“ Projects</a></li>
      <li><a href="invoices.html">๐Ÿงพ Invoices</a></li>
      <li><a href="services.html">๐Ÿ›  Services</a></li>
      <li><a href="access-roles.html">๐Ÿ” Access / Roles</a></li>
      <hr style="border:none;border-top:1px solid #c9bfff;margin:12px 0 8px;">
      <li><a href="developer-info.html">๐Ÿ‘จโ€๐Ÿ’ป Support Info</a></li>
    </ul>
  </aside>

  <!-- Main -->
  <main class="main">
    <div class="topbar">
      <input type="text" id="globalSearch" placeholder="Search clients, projects, invoices...">
      <div class="profile"><a href="admin.html" style="color:inherit;text-decoration:none;">โš™๏ธ Admin</a></div>
    </div>

    <!-- Page Header -->
    <div class="page-header">
      <div class="page-header-left">
        <h1>Clients</h1>
        <p>Manage all your client relationships</p>
      </div>
      <div class="page-header-actions">
        <button class="btn btn-primary" onclick="openAddModal()">+ Add Client</button>
      </div>
    </div>

    <!-- Stats -->
    <div class="stats-grid">
      <div class="stat-card">
        <div class="stat-label">Total Clients</div>
        <div class="stat-value" id="statTotal">0</div>
        <div class="stat-sub">All time</div>
      </div>
      <div class="stat-card green">
        <div class="stat-label">Active Projects</div>
        <div class="stat-value" id="statActive">0</div>
        <div class="stat-sub">In progress</div>
      </div>
      <div class="stat-card orange">
        <div class="stat-label">Pending Payments</div>
        <div class="stat-value" id="statPending">โ‚น0</div>
        <div class="stat-sub">Unpaid balance</div>
      </div>
      <div class="stat-card blue">
        <div class="stat-label">Total Revenue</div>
        <div class="stat-value" id="statRevenue">โ‚น0</div>
        <div class="stat-sub">Contract value</div>
      </div>
    </div>

    <!-- Filter Bar -->
    <div class="filter-bar">
      <input type="search" class="search-input" id="searchInput" placeholder="๐Ÿ”  Search by name, company, domain...">
      <select id="filterType">
        <option value="">All Website Types</option>
        <option>Business Website</option>
        <option>Ecommerce Website</option>
        <option>Landing Page</option>
        <option>Website Redesign</option>
      </select>
      <select id="filterPlan">
        <option value="">All Plans</option>
        <option>Basic</option>
        <option>Premium</option>
        <option>Custom</option>
      </select>
      <div class="spacer"></div>
      <span id="clientCount" style="font-size:0.82rem;color:#aaa;"></span>
    </div>

    <!-- Table -->
    <div class="table-card">
      <div class="table-header">
        <h3>Client List</h3>
        <span id="tableCount"></span>
      </div>
      <table>
        <thead>
          <tr>
            <th>Client</th>
            <th>Website Type</th>
            <th>Plan</th>
            <th>Platform</th>
            <th>Last Payment</th>
            <th>Total Value</th>
            <th>Balance Due</th>
            <th>Actions</th>
          </tr>
        </thead>
        <tbody id="clientsTableBody">
          <tr><td colspan="8"><div class="empty-state"><div class="e-icon">โณ</div><h3>Loading clients...</h3></div></td></tr>
        </tbody>
      </table>
    </div>

  </main>
</div>

<!-- Add / Edit Client Modal -->
<div class="modal-overlay" id="clientModal">
  <div class="modal modal-lg">
    <div class="modal-header">
      <h2 id="modalTitle">Add New Client</h2>
      <button class="modal-close" onclick="closeModal()">โœ•</button>
    </div>

    <h4 style="font-size:0.82rem;color:#6c5ce7;text-transform:uppercase;letter-spacing:0.5px;margin-bottom:14px;">Basic Information</h4>
    <div class="form-grid">
      <div class="form-group">
        <label>Full Name *</label>
        <input type="text" id="fName" placeholder="Rahul Sharma">
      </div>
      <div class="form-group">
        <label>Email Address</label>
        <input type="email" id="fEmail" placeholder="client@company.com">
      </div>
      <div class="form-group">
        <label>Phone Number</label>
        <input type="tel" id="fPhone" placeholder="+91 98765 43210">
      </div>
      <div class="form-group">
        <label>Company Name</label>
        <input type="text" id="fCompany" placeholder="Company Pvt Ltd">
      </div>
      <div class="form-group">
        <label>Domain Name</label>
        <input type="text" id="fDomain" placeholder="company.in">
      </div>
      <div class="form-group">
        <label>Hosting Provider</label>
        <input type="text" id="fHostingProvider" placeholder="Hostinger / AWS / GoDaddy">
      </div>
    </div>

    <h4 style="font-size:0.82rem;color:#6c5ce7;text-transform:uppercase;letter-spacing:0.5px;margin:18px 0 14px;">Website Details</h4>
    <div class="form-grid">
      <div class="form-group">
        <label>Project Type</label>
        <select id="fProjectType">
          <option value="">Select type</option>
          <option>Business Website</option>
          <option>Ecommerce Website</option>
          <option>Landing Page</option>
          <option>Website Redesign</option>
        </select>
      </div>
      <div class="form-group">
        <label>Platform</label>
        <select id="fPlatform">
          <option value="">Select platform</option>
          <option>WordPress</option>
          <option>Shopify</option>
          <option>WooCommerce</option>
          <option>Custom</option>
          <option>Webflow</option>
        </select>
      </div>
      <div class="form-group">
        <label>Hosting Expiry</label>
        <input type="date" id="fHostingExpiry">
      </div>
      <div class="form-group">
        <label>SSL Expiry</label>
        <input type="date" id="fSslExpiry">
      </div>
      <div class="form-group">
        <label>Maintenance Plan</label>
        <select id="fMaintenance">
          <option>None</option>
          <option>Monthly</option>
          <option>Quarterly</option>
          <option>Annual</option>
        </select>
      </div>
      <div class="form-group">
        <label>Plan Type</label>
        <select id="fPlanType">
          <option>Basic</option>
          <option>Premium</option>
          <option>Custom</option>
        </select>
      </div>
    </div>

    <h4 style="font-size:0.82rem;color:#6c5ce7;text-transform:uppercase;letter-spacing:0.5px;margin:18px 0 14px;">Billing</h4>
    <div class="form-grid">
      <div class="form-group">
        <label>Total Contract Value (โ‚น)</label>
        <input type="number" id="fContractValue" placeholder="45000">
      </div>
      <div class="form-group">
        <label>Paid Amount (โ‚น)</label>
        <input type="number" id="fPaidAmount" placeholder="35000">
      </div>
    </div>

    <div class="modal-footer">
      <button class="btn btn-secondary" onclick="closeModal()">Cancel</button>
      <button class="btn btn-primary" onclick="saveClient()">Save Client</button>
    </div>
  </div>
</div>

<script src="supabase-config.js"></script>
<script>
let clients = [];
let editingId = null;

async function init() {
  clients = await fetchClients();
  renderStats();
  renderTable(clients);
}

function renderStats() {
  const total = clients.length;
  const pending = clients.reduce((s, c) => s + (c.total_contract_value - c.paid_amount), 0);
  const revenue = clients.reduce((s, c) => s + (c.total_contract_value || 0), 0);
  document.getElementById('statTotal').textContent = total;
  document.getElementById('statActive').textContent = clients.filter(c => (c.total_contract_value - c.paid_amount) > 0).length;
  document.getElementById('statPending').textContent = formatCurrency(pending);
  document.getElementById('statRevenue').textContent = formatCurrency(revenue);
}

function statusBadge(type) {
  const map = {
    'Business Website': 'badge-blue', 'Ecommerce Website': 'badge-purple',
    'Landing Page': 'badge-teal', 'Website Redesign': 'badge-orange'
  };
  return `<span class="badge ${map[type] || 'badge-gray'}">${type || 'โ€”'}</span>`;
}
function planBadge(plan) {
  const map = { 'Premium': 'badge-purple', 'Basic': 'badge-blue', 'Custom': 'badge-orange' };
  return `<span class="badge ${map[plan] || 'badge-gray'}">${plan || 'โ€”'}</span>`;
}

function renderTable(data) {
  const tbody = document.getElementById('clientsTableBody');
  document.getElementById('tableCount').textContent = data.length + ' clients';
  if (!data.length) {
    tbody.innerHTML = `<tr><td colspan="8"><div class="empty-state"><div class="e-icon">๐Ÿ‘ฅ</div><h3>No clients found</h3><p>Add your first client to get started</p></div></td></tr>`;
    return;
  }
  tbody.innerHTML = data.map(c => {
    const balance = (c.total_contract_value || 0) - (c.paid_amount || 0);
    return `<tr>
      <td data-label="Client">
        <div style="font-weight:600;color:#333;">${c.name}</div>
        <div style="font-size:0.78rem;color:#aaa;">${c.company || ''}</div>
      </td>
      <td data-label="Type">${statusBadge(c.project_type)}</td>
      <td data-label="Plan">${planBadge(c.plan_type)}</td>
      <td data-label="Platform"><span style="color:#666;">${c.platform || 'โ€”'}</span></td>
      <td data-label="Last Payment"><span style="color:#666;font-size:0.85rem;">${c.paid_amount ? formatCurrency(c.paid_amount) : 'โ€”'}</span></td>
      <td data-label="Total Value"><strong style="color:#4b3fbf;">${formatCurrency(c.total_contract_value || 0)}</strong></td>
      <td data-label="Balance Due">
        <span class="${balance > 0 ? 'badge badge-red' : 'badge badge-green'}">${balance > 0 ? formatCurrency(balance) : 'Paid โœ“'}</span>
      </td>
      <td data-label="Actions">
        <div class="table-actions">
          <a href="client-detail.html?id=${c.id}" class="action-btn action-view" title="View Profile">๐Ÿ‘</a>
          <button class="action-btn action-edit" onclick="openEditModal('${c.id}')" title="Edit">โœ๏ธ</button>
          <button class="action-btn action-delete" onclick="handleDelete('${c.id}')" title="Delete">๐Ÿ—‘</button>
        </div>
      </td>
    </tr>`;
  }).join('');
}

function filterClients() {
  const search = document.getElementById('searchInput').value.toLowerCase();
  const type = document.getElementById('filterType').value;
  const plan = document.getElementById('filterPlan').value;
  const filtered = clients.filter(c => {
    const matchSearch = !search ||
      (c.name || '').toLowerCase().includes(search) ||
      (c.company || '').toLowerCase().includes(search) ||
      (c.domain_name || '').toLowerCase().includes(search) ||
      (c.email || '').toLowerCase().includes(search);
    const matchType = !type || c.project_type === type;
    const matchPlan = !plan || c.plan_type === plan;
    return matchSearch && matchType && matchPlan;
  });
  renderTable(filtered);
}

document.getElementById('searchInput').addEventListener('input', filterClients);
document.getElementById('filterType').addEventListener('change', filterClients);
document.getElementById('filterPlan').addEventListener('change', filterClients);

function openAddModal() {
  editingId = null;
  document.getElementById('modalTitle').textContent = 'Add New Client';
  ['fName','fEmail','fPhone','fCompany','fDomain','fHostingProvider','fHostingExpiry','fSslExpiry','fContractValue','fPaidAmount'].forEach(id => document.getElementById(id).value = '');
  document.getElementById('fProjectType').value = '';
  document.getElementById('fPlatform').value = '';
  document.getElementById('fMaintenance').value = 'None';
  document.getElementById('fPlanType').value = 'Basic';
  document.getElementById('clientModal').classList.add('active');
}

function openEditModal(id) {
  const c = clients.find(x => x.id === id);
  if (!c) return;
  editingId = id;
  document.getElementById('modalTitle').textContent = 'Edit Client';
  document.getElementById('fName').value = c.name || '';
  document.getElementById('fEmail').value = c.email || '';
  document.getElementById('fPhone').value = c.phone || '';
  document.getElementById('fCompany').value = c.company || '';
  document.getElementById('fDomain').value = c.domain_name || '';
  document.getElementById('fHostingProvider').value = c.hosting_provider || '';
  document.getElementById('fProjectType').value = c.project_type || '';
  document.getElementById('fPlatform').value = c.platform || '';
  document.getElementById('fHostingExpiry').value = c.hosting_expiry || '';
  document.getElementById('fSslExpiry').value = c.ssl_expiry || '';
  document.getElementById('fMaintenance').value = c.maintenance_plan || 'None';
  document.getElementById('fPlanType').value = c.plan_type || 'Basic';
  document.getElementById('fContractValue').value = c.total_contract_value || '';
  document.getElementById('fPaidAmount').value = c.paid_amount || '';
  document.getElementById('clientModal').classList.add('active');
}

function closeModal() { document.getElementById('clientModal').classList.remove('active'); }

async function saveClient() {
  const name = document.getElementById('fName').value.trim();
  if (!name) { showToast('Client name is required', 'error'); return; }
  const he = document.getElementById('fHostingExpiry').value;
  const se = document.getElementById('fSslExpiry').value;
  if (he && !isValidDate(he)) { markDateError('fHostingExpiry', 'Invalid hosting expiry date'); showToast('Enter a valid hosting expiry date', 'error'); return; }
  if (se && !isValidDate(se)) { markDateError('fSslExpiry', 'Invalid SSL expiry date'); showToast('Enter a valid SSL expiry date', 'error'); return; }
  clearDateError('fHostingExpiry'); clearDateError('fSslExpiry');
  const data = {
    name, email: document.getElementById('fEmail').value.trim(),
    phone: document.getElementById('fPhone').value.trim(),
    company: document.getElementById('fCompany').value.trim(),
    domain_name: document.getElementById('fDomain').value.trim(),
    hosting_provider: document.getElementById('fHostingProvider').value.trim(),
    project_type: document.getElementById('fProjectType').value,
    platform: document.getElementById('fPlatform').value,
    hosting_expiry: he || null,
    ssl_expiry: se || null,
    maintenance_plan: document.getElementById('fMaintenance').value,
    plan_type: document.getElementById('fPlanType').value,
    total_contract_value: Number(document.getElementById('fContractValue').value) || 0,
    paid_amount: Number(document.getElementById('fPaidAmount').value) || 0
  };
  try {
    if (editingId) {
      const updated = await updateClient(editingId, data);
      const idx = clients.findIndex(c => c.id === editingId);
      if (idx > -1) clients[idx] = updated;
      showToast('Client updated successfully!', 'success');
    } else {
      const created = await addClient(data);
      clients.unshift(created);
      showToast('Client added successfully!', 'success');
    }
    closeModal(); renderStats(); filterClients();
  } catch (e) { showToast('Error: ' + e.message, 'error'); }
}

async function handleDelete(id) {
  if (!confirm('Delete this client? This action cannot be undone.')) return;
  try {
    await deleteClient(id);
    clients = clients.filter(c => c.id !== id);
    renderStats(); filterClients();
    showToast('Client deleted.', 'info');
  } catch (e) { showToast('Error: ' + e.message, 'error'); }
}

// Close modal on overlay click
document.getElementById('clientModal').addEventListener('click', function(e) {
  if (e.target === this) closeModal();
});

attachDateValidation('fHostingExpiry', { label: 'Hosting Expiry' });
attachDateValidation('fSslExpiry',     { label: 'SSL Expiry' });
init();
</script>
</body>
</html>