| Server IP : 213.255.246.8 / Your IP : 216.73.217.0 Web Server : Apache System : Linux dublin.stapolin.com 5.14.0-362.18.1.el9_3.x86_64 #1 SMP PREEMPT_DYNAMIC Mon Jan 29 07:05:48 EST 2024 x86_64 User : stapolin ( 1019) PHP Version : 8.4.24 Disable Function : exec,passthru,shell_exec,system MySQL : OFF | cURL : ON | WGET : ON | Perl : ON | Python : OFF | Sudo : ON | Pkexec : ON Directory : /home/stapolin/public_html/dash.stapolin.com/ |
Upload File : |
<?php
/**
* Clients Management Page
*/
$pageTitle = 'Clients';
require_once __DIR__ . '/includes/header.php';
// Get all clients with website counts
try {
$db = getDb();
$clients = $db->fetchAll(
"SELECT c.*, COUNT(w.website_id) as website_count
FROM st_clients c
LEFT JOIN st_websites w ON c.client_id = w.client_id
GROUP BY c.client_id
ORDER BY c.client_name"
);
} catch (Exception $e) {
$clients = [];
}
// Handle success message
$successMessage = isset($_GET['success']) ? $_GET['success'] : null;
?>
<!-- Page Header -->
<div class="flex items-center justify-between gap-4 mb-6">
<div>
<p class="text-muted-foreground">Manage your clients and their associated websites</p>
</div>
<button onclick="document.getElementById('addClientModal').classList.remove('hidden')"
class="btn-primary px-4 py-2 rounded-md text-sm font-medium flex items-center gap-2"
data-testid="button-add-client">
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 6v6m0 0v6m0-6h6m-6 0H6"/>
</svg>
Add Client
</button>
</div>
<?php if ($successMessage): ?>
<div class="mb-6 p-4 rounded-md bg-green-500/10 border border-green-500/20 text-green-600 dark:text-green-400" data-testid="alert-success">
<?= sanitize($successMessage) ?>
</div>
<?php endif; ?>
<!-- Clients Grid -->
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
<?php if (empty($clients)): ?>
<div class="col-span-full">
<div class="card rounded-lg p-12 text-center">
<svg class="w-16 h-16 mx-auto text-muted-foreground/50 mb-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17 20h5v-2a3 3 0 00-5.356-1.857M17 20H7m10 0v-2c0-.656-.126-1.283-.356-1.857M7 20H2v-2a3 3 0 015.356-1.857M7 20v-2c0-.656.126-1.283.356-1.857m0 0a5.002 5.002 0 019.288 0M15 7a3 3 0 11-6 0 3 3 0 016 0z"/>
</svg>
<h3 class="text-lg font-medium mb-2">No clients yet</h3>
<p class="text-muted-foreground mb-4">Add your first client to get started</p>
<button onclick="document.getElementById('addClientModal').classList.remove('hidden')"
class="btn-primary px-4 py-2 rounded-md text-sm font-medium"
data-testid="button-add-first-client">
Add Client
</button>
</div>
</div>
<?php else: ?>
<?php foreach ($clients as $client): ?>
<a href="client-detail.php?id=<?= $client['client_id'] ?>"
class="card rounded-lg p-6 block hover:border-primary/50 transition-colors"
data-testid="card-client-<?= $client['client_id'] ?>">
<div class="flex items-start justify-between gap-4 mb-4">
<div class="w-12 h-12 rounded-lg bg-primary/10 flex items-center justify-center flex-shrink-0">
<span class="text-primary font-semibold text-lg"><?= strtoupper(substr($client['client_name'], 0, 2)) ?></span>
</div>
<span class="badge badge-primary"><?= $client['website_count'] ?> site<?= $client['website_count'] !== 1 ? 's' : '' ?></span>
</div>
<h3 class="font-semibold text-lg mb-1" data-testid="text-client-name-<?= $client['client_id'] ?>"><?= sanitize($client['client_name']) ?></h3>
<?php if (!empty($client['client_email'])): ?>
<p class="text-sm text-muted-foreground"><?= sanitize($client['client_email']) ?></p>
<?php endif; ?>
</a>
<?php endforeach; ?>
<?php endif; ?>
</div>
<!-- Add Client Modal -->
<div id="addClientModal" class="hidden fixed inset-0 z-50 overflow-y-auto" aria-labelledby="modal-title" role="dialog" aria-modal="true">
<div class="flex items-center justify-center min-h-screen px-4 pt-4 pb-20 text-center sm:block sm:p-0">
<div class="fixed inset-0 bg-black/50 transition-opacity" onclick="document.getElementById('addClientModal').classList.add('hidden')"></div>
<div class="inline-block align-bottom card rounded-lg text-left overflow-hidden shadow-xl transform transition-all sm:my-8 sm:align-middle sm:max-w-lg sm:w-full">
<form action="api/clients.php" method="POST">
<input type="hidden" name="action" value="create">
<div class="px-6 py-4 border-b">
<h3 class="text-lg font-semibold" id="modal-title">Add New Client</h3>
</div>
<div class="px-6 py-4 space-y-4">
<div>
<label for="client_name" class="block text-sm font-medium mb-1">Client Name <span class="text-destructive">*</span></label>
<input type="text"
id="client_name"
name="client_name"
required
class="w-full px-3 py-2 rounded-md text-sm"
placeholder="Enter client name"
data-testid="input-client-name">
</div>
<div>
<label for="client_email" class="block text-sm font-medium mb-1">Email Address</label>
<input type="email"
id="client_email"
name="client_email"
class="w-full px-3 py-2 rounded-md text-sm"
placeholder="client@example.com"
data-testid="input-client-email">
</div>
<div>
<label for="client_phone" class="block text-sm font-medium mb-1">Phone Number</label>
<input type="tel"
id="client_phone"
name="client_phone"
class="w-full px-3 py-2 rounded-md text-sm"
placeholder="+1 (555) 123-4567"
data-testid="input-client-phone">
</div>
<div>
<label for="client_notes" class="block text-sm font-medium mb-1">Notes</label>
<textarea id="client_notes"
name="client_notes"
rows="3"
class="w-full px-3 py-2 rounded-md text-sm"
placeholder="Additional notes about this client"
data-testid="input-client-notes"></textarea>
</div>
</div>
<div class="px-6 py-4 border-t flex items-center justify-end gap-3">
<button type="button"
onclick="document.getElementById('addClientModal').classList.add('hidden')"
class="btn-secondary px-4 py-2 rounded-md text-sm font-medium"
data-testid="button-cancel-add-client">
Cancel
</button>
<button type="submit"
class="btn-primary px-4 py-2 rounded-md text-sm font-medium"
data-testid="button-submit-add-client">
Add Client
</button>
</div>
</form>
</div>
</div>
</div>
<?php require_once __DIR__ . '/includes/footer.php'; ?>