DNSBlock
This commit is contained in:
74
resources/views/admin/clients/form.php
Normal file
74
resources/views/admin/clients/form.php
Normal file
@@ -0,0 +1,74 @@
|
||||
<div class="max-w-2xl mx-auto bg-white rounded-xl shadow-sm border border-gray-100 p-6">
|
||||
<h3 class="text-lg font-semibold text-gray-800 mb-6"><?= isset($client) ? 'Editar Cliente' : 'Novo Cliente' ?></h3>
|
||||
|
||||
<form action="<?= isset($client) ? '/admin/clients/update/' . $client['id'] : '/admin/clients/store' ?>"
|
||||
method="POST">
|
||||
<div class="space-y-4">
|
||||
<div>
|
||||
<label class="block text-sm font-medium text-gray-700 mb-1">Razão Social / Nome</label>
|
||||
<input type="text" name="name" value="<?= $client['name'] ?? '' ?>"
|
||||
class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-primary-500 focus:border-transparent"
|
||||
required>
|
||||
</div>
|
||||
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||
<div>
|
||||
<label class="block text-sm font-medium text-gray-700 mb-1">ASN (ex: AS12345)</label>
|
||||
<input type="text" name="asn" value="<?= $client['asn'] ?? '' ?>"
|
||||
class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-primary-500 focus:border-transparent"
|
||||
required>
|
||||
</div>
|
||||
<div>
|
||||
<label class="block text-sm font-medium text-gray-700 mb-1">Telegram ID (Opcional)</label>
|
||||
<input type="text" name="telegram_id" value="<?= $client['telegram_id'] ?? '' ?>"
|
||||
class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-primary-500 focus:border-transparent">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||
<div>
|
||||
<label class="block text-sm font-medium text-gray-700 mb-1">Email Principal (Login)</label>
|
||||
<input type="email" name="email" value="<?= $client['email'] ?? '' ?>"
|
||||
class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-primary-500 focus:border-transparent"
|
||||
required>
|
||||
</div>
|
||||
<div>
|
||||
<label class="block text-sm font-medium text-gray-700 mb-1">Email Financeiro</label>
|
||||
<input type="email" name="financial_email" value="<?= $client['financial_email'] ?? '' ?>"
|
||||
class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-primary-500 focus:border-transparent"
|
||||
required>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label class="block text-sm font-medium text-gray-700 mb-1">Senha de Acesso
|
||||
<?= isset($client) ? '<span class="text-gray-400 font-normal">(Deixe em branco para manter)</span>' : '' ?></label>
|
||||
<input type="password" name="password"
|
||||
class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-primary-500 focus:border-transparent"
|
||||
<?= isset($client) ? '' : 'required' ?>>
|
||||
</div>
|
||||
|
||||
<?php if (isset($client)): ?>
|
||||
<div>
|
||||
<label class="block text-sm font-medium text-gray-700 mb-1">Status</label>
|
||||
<select name="status"
|
||||
class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-primary-500 focus:border-transparent">
|
||||
<option value="active" <?= $client['status'] == 'active' ? 'selected' : '' ?>>Ativo</option>
|
||||
<option value="inactive" <?= $client['status'] == 'inactive' ? 'selected' : '' ?>>Inativo</option>
|
||||
</select>
|
||||
</div>
|
||||
<?php else: ?>
|
||||
<input type="hidden" name="status" value="active">
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
|
||||
<div class="mt-6 flex justify-end space-x-3">
|
||||
<a href="/admin/clients"
|
||||
class="px-4 py-2 text-gray-700 hover:bg-gray-100 rounded-lg transition-colors">Cancelar</a>
|
||||
<button type="submit"
|
||||
class="px-4 py-2 bg-primary-600 text-white rounded-lg hover:bg-primary-700 transition-colors">
|
||||
<?= isset($client) ? 'Salvar Alterações' : 'Criar Cliente' ?>
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
57
resources/views/admin/clients/index.php
Normal file
57
resources/views/admin/clients/index.php
Normal file
@@ -0,0 +1,57 @@
|
||||
<div class="bg-white rounded-xl shadow-sm border border-gray-100 overflow-hidden">
|
||||
<div class="px-6 py-4 border-b border-gray-100 flex justify-between items-center bg-gray-50">
|
||||
<h3 class="text-lg font-semibold text-gray-800">Clientes Cadastrados</h3>
|
||||
<a href="/admin/clients/create"
|
||||
class="bg-primary-600 hover:bg-primary-700 text-white px-4 py-2 rounded-lg text-sm font-medium transition-colors flex items-center">
|
||||
<svg class="w-4 h-4 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 4v16m8-8H4"></path>
|
||||
</svg>
|
||||
Novo Cliente
|
||||
</a>
|
||||
</div>
|
||||
<div class="overflow-x-auto">
|
||||
<table class="w-full text-left border-collapse">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="px-6 py-3 text-xs font-medium text-gray-500 uppercase tracking-wider bg-gray-50">Nome
|
||||
</th>
|
||||
<th class="px-6 py-3 text-xs font-medium text-gray-500 uppercase tracking-wider bg-gray-50">ASN</th>
|
||||
<th class="px-6 py-3 text-xs font-medium text-gray-500 uppercase tracking-wider bg-gray-50">Email
|
||||
</th>
|
||||
<th class="px-6 py-3 text-xs font-medium text-gray-500 uppercase tracking-wider bg-gray-50">Status
|
||||
</th>
|
||||
<th class="px-6 py-3 text-xs font-medium text-gray-500 uppercase tracking-wider bg-gray-50">Ações
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody class="divide-y divide-gray-100">
|
||||
<?php if (!empty($clients)): ?>
|
||||
<?php foreach ($clients as $client): ?>
|
||||
<tr class="hover:bg-gray-50 transition-colors">
|
||||
<td class="px-6 py-4 text-sm font-medium text-gray-900"><?= htmlspecialchars($client['name']) ?>
|
||||
</td>
|
||||
<td class="px-6 py-4 text-sm text-gray-500"><?= htmlspecialchars($client['asn']) ?></td>
|
||||
<td class="px-6 py-4 text-sm text-gray-500"><?= htmlspecialchars($client['email']) ?></td>
|
||||
<td class="px-6 py-4 text-sm">
|
||||
<span
|
||||
class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full <?= $client['status'] == 'active' ? 'bg-green-100 text-green-800' : 'bg-red-100 text-red-800' ?>">
|
||||
<?= $client['status'] == 'active' ? 'Ativo' : 'Inativo' ?>
|
||||
</span>
|
||||
</td>
|
||||
<td class="px-6 py-4 text-sm font-medium">
|
||||
<a href="/admin/clients/edit/<?= $client['id'] ?>"
|
||||
class="text-[#1e3a8a] hover:text-blue-900 mr-3">Editar</a>
|
||||
<a href="/admin/clients/delete/<?= $client['id'] ?>" onclick="return confirm('Tem certeza?')"
|
||||
class="text-red-600 hover:text-red-900">Excluir</a>
|
||||
</td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
<?php else: ?>
|
||||
<tr>
|
||||
<td colspan="5" class="px-6 py-4 text-center text-gray-500">Nenhum cliente encontrado.</td>
|
||||
</tr>
|
||||
<?php endif; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
121
resources/views/admin/dashboard.php
Normal file
121
resources/views/admin/dashboard.php
Normal file
@@ -0,0 +1,121 @@
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6 mb-8">
|
||||
<!-- Card 1 -->
|
||||
<div class="bg-white rounded-xl shadow-sm p-6 border border-gray-100 hover:shadow-md transition-shadow">
|
||||
<div class="flex items-center">
|
||||
<div class="p-3 rounded-full bg-blue-50 text-blue-600">
|
||||
<svg class="w-8 h-8" 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 0zm6 3a2 2 0 11-4 0 2 2 0 014 0zM7 10a2 2 0 11-4 0 2 2 0 014 0z">
|
||||
</path>
|
||||
</svg>
|
||||
</div>
|
||||
<div class="ml-4">
|
||||
<p class="text-sm font-medium text-gray-500">Clientes Ativos</p>
|
||||
<p class="text-2xl font-bold text-gray-900"><?= $stats['clients'] ?? 0 ?></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Card 2 -->
|
||||
<div class="bg-white rounded-xl shadow-sm p-6 border border-gray-100 hover:shadow-md transition-shadow">
|
||||
<div class="flex items-center">
|
||||
<div class="p-3 rounded-full bg-green-50 text-green-600">
|
||||
<svg class="w-8 h-8" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
||||
d="M5 12h14M5 12a2 2 0 01-2-2V6a2 2 0 012-2h14a2 2 0 012 2v4a2 2 0 01-2 2M5 12a2 2 0 00-2 2v4a2 2 0 002 2h14a2 2 0 002-2v-4a2 2 0 00-2-2m-2-4h.01M17 16h.01">
|
||||
</path>
|
||||
</svg>
|
||||
</div>
|
||||
<div class="ml-4">
|
||||
<p class="text-sm font-medium text-gray-500">Servidores Online</p>
|
||||
<p class="text-2xl font-bold text-gray-900"><?= $stats['servers'] ?? 0 ?></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Card 3 -->
|
||||
<div class="bg-white rounded-xl shadow-sm p-6 border border-gray-100 hover:shadow-md transition-shadow">
|
||||
<div class="flex items-center">
|
||||
<div class="p-3 rounded-full bg-red-50 text-red-600">
|
||||
<svg class="w-8 h-8" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
||||
d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z">
|
||||
</path>
|
||||
</svg>
|
||||
</div>
|
||||
<div class="ml-4">
|
||||
<p class="text-sm font-medium text-gray-500">Domínios Bloqueados</p>
|
||||
<p class="text-2xl font-bold text-gray-900"><?= $stats['blocked_domains'] ?? 0 ?></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Card 4 -->
|
||||
<div class="bg-white rounded-xl shadow-sm p-6 border border-gray-100 hover:shadow-md transition-shadow">
|
||||
<div class="flex items-center">
|
||||
<div class="p-3 rounded-full bg-purple-50 text-purple-600">
|
||||
<svg class="w-8 h-8" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
||||
d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z">
|
||||
</path>
|
||||
</svg>
|
||||
</div>
|
||||
<div class="ml-4">
|
||||
<p class="text-sm font-medium text-gray-500">Ordens Totais</p>
|
||||
<p class="text-2xl font-bold text-gray-900"><?= $stats['orders'] ?? 0 ?></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="bg-white rounded-xl shadow-sm border border-gray-100 overflow-hidden">
|
||||
<div class="px-6 py-4 border-b border-gray-100 flex justify-between items-center bg-gray-50">
|
||||
<h3 class="text-lg font-semibold text-gray-800">Últimas Ordens Judiciais</h3>
|
||||
<a href="/admin/orders" class="text-sm text-primary-600 hover:text-primary-700 font-medium">Ver todas</a>
|
||||
</div>
|
||||
<div class="overflow-x-auto">
|
||||
<table class="w-full text-left border-collapse">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">ID</th>
|
||||
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Título
|
||||
</th>
|
||||
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Tipo
|
||||
</th>
|
||||
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Início do
|
||||
Bloqueio</th>
|
||||
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Ações
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody class="divide-y divide-gray-100">
|
||||
<?php if (!empty($recent_orders)): ?>
|
||||
<?php foreach ($recent_orders as $order): ?>
|
||||
<tr class="hover:bg-gray-50 transition-colors">
|
||||
<td class="px-6 py-4 text-sm text-gray-500"><?= $order['id'] ?></td>
|
||||
<td class="px-6 py-4 text-sm font-medium text-gray-900"><?= htmlspecialchars($order['title']) ?>
|
||||
</td>
|
||||
<td class="px-6 py-4 text-sm">
|
||||
<span
|
||||
class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full <?= $order['type'] == 'block' ? 'bg-red-100 text-red-800' : 'bg-green-100 text-green-800' ?>">
|
||||
<?= $order['type'] == 'block' ? 'Bloqueio' : 'Desbloqueio' ?>
|
||||
</span>
|
||||
</td>
|
||||
<td class="px-6 py-4 text-sm text-gray-500">
|
||||
<?= date('d/m/Y', strtotime($order['received_at'])) ?>
|
||||
</td>
|
||||
<td class="px-6 py-4 text-sm font-medium">
|
||||
<a href="/admin/orders/view/<?= $order['id'] ?>"
|
||||
class="text-primary-600 hover:text-primary-900 hover:underline">Detalhes</a>
|
||||
</td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
<?php else: ?>
|
||||
<tr>
|
||||
<td colspan="5" class="px-6 py-4 text-center text-gray-500">Nenhuma ordem registrada.</td>
|
||||
</tr>
|
||||
<?php endif; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
84
resources/views/admin/logs/index.php
Normal file
84
resources/views/admin/logs/index.php
Normal file
@@ -0,0 +1,84 @@
|
||||
<div class="bg-white rounded-xl shadow-sm border border-gray-100 overflow-hidden">
|
||||
<div class="p-6 border-b border-gray-100 flex justify-between items-center">
|
||||
<h2 class="text-lg font-semibold text-gray-800">Logs de Conexão e Erros</h2>
|
||||
<span class="text-sm text-gray-500">Mostrando últimos registros</span>
|
||||
</div>
|
||||
|
||||
<div class="overflow-x-auto">
|
||||
<table class="w-full text-left border-collapse">
|
||||
<thead>
|
||||
<tr class="bg-gray-50 text-gray-600 text-sm uppercase tracking-wider">
|
||||
<th class="p-4 font-medium border-b border-gray-100">Data/Hora</th>
|
||||
<th class="p-4 font-medium border-b border-gray-100">Servidor</th>
|
||||
<th class="p-4 font-medium border-b border-gray-100">Ação</th>
|
||||
<th class="p-4 font-medium border-b border-gray-100">Mensagem</th>
|
||||
<th class="p-4 font-medium border-b border-gray-100">IP Origem</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody class="text-sm divide-y divide-gray-100">
|
||||
<?php foreach ($logs as $log): ?>
|
||||
<tr class="hover:bg-gray-50 transition-colors">
|
||||
<td class="p-4 text-gray-600 whitespace-nowrap">
|
||||
<?= date('d/m/Y H:i:s', strtotime($log['created_at'])) ?>
|
||||
</td>
|
||||
<td class="p-4">
|
||||
<?php if ($log['server_name']): ?>
|
||||
<a href="/admin/servers/edit/<?= $log['server_id'] ?>"
|
||||
class="font-medium text-primary-600 hover:underline">
|
||||
<?= htmlspecialchars($log['server_name']) ?>
|
||||
</a>
|
||||
<div class="text-xs text-gray-400"><?= htmlspecialchars($log['ip_v4']) ?></div>
|
||||
<?php else: ?>
|
||||
<span class="text-gray-400 italic">Desconhecido / Falha Auth</span>
|
||||
<?php endif; ?>
|
||||
</td>
|
||||
<td class="p-4">
|
||||
<?php
|
||||
$badgeColor = match ($log['action']) {
|
||||
'sync' => 'bg-green-100 text-green-700',
|
||||
'bind_machine' => 'bg-blue-100 text-blue-700',
|
||||
'auth_failed', 'auth_blocked', 'error' => 'bg-red-100 text-red-700',
|
||||
default => 'bg-gray-100 text-gray-700'
|
||||
};
|
||||
?>
|
||||
<span class="px-2 py-1 rounded-full text-xs font-medium <?= $badgeColor ?>">
|
||||
<?= htmlspecialchars($log['action']) ?>
|
||||
</span>
|
||||
</td>
|
||||
<td class="p-4 text-gray-700">
|
||||
<?= htmlspecialchars($log['message']) ?>
|
||||
</td>
|
||||
<td class="p-4 text-gray-500 font-mono text-xs">
|
||||
<?= htmlspecialchars($log['ip_address']) ?>
|
||||
</td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
|
||||
<?php if (empty($logs)): ?>
|
||||
<tr>
|
||||
<td colspan="5" class="p-8 text-center text-gray-500">
|
||||
Nenhum log registrado ainda.
|
||||
</td>
|
||||
</tr>
|
||||
<?php endif; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<!-- Pagination -->
|
||||
<?php if ($totalPages > 1): ?>
|
||||
<div class="p-4 border-t border-gray-100 flex justify-center space-x-2">
|
||||
<?php if ($page > 1): ?>
|
||||
<a href="?page=<?= $page - 1 ?>"
|
||||
class="px-3 py-1 border border-gray-300 rounded hover:bg-gray-50 text-sm">Anterior</a>
|
||||
<?php endif; ?>
|
||||
|
||||
<span class="px-3 py-1 text-sm text-gray-600">Página <?= $page ?> de <?= $totalPages ?></span>
|
||||
|
||||
<?php if ($page < $totalPages): ?>
|
||||
<a href="?page=<?= $page + 1 ?>"
|
||||
class="px-3 py-1 border border-gray-300 rounded hover:bg-gray-50 text-sm">Próxima</a>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
119
resources/views/admin/orders/create.php
Normal file
119
resources/views/admin/orders/create.php
Normal file
@@ -0,0 +1,119 @@
|
||||
<div class="max-w-3xl mx-auto bg-white rounded-xl shadow-sm border border-gray-100 p-6">
|
||||
<h3 class="text-lg font-semibold text-gray-800 mb-6">Nova Ordem Judicial</h3>
|
||||
|
||||
<?php if (isset($_SESSION['flash_error'])): ?>
|
||||
<div class="bg-red-50 border-l-4 border-red-500 p-4 mb-6">
|
||||
<p class="text-sm text-red-700"><?= $_SESSION['flash_error'] ?></p>
|
||||
</div>
|
||||
<?php unset($_SESSION['flash_error']); ?>
|
||||
<?php endif; ?>
|
||||
|
||||
<!-- Quill Styles -->
|
||||
<link href="https://cdn.quilljs.com/1.3.6/quill.snow.css" rel="stylesheet">
|
||||
|
||||
<form action="/admin/orders/store" method="POST" enctype="multipart/form-data" class="space-y-6" id="orderForm">
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
|
||||
<div class="col-span-2">
|
||||
<label class="block text-sm font-medium text-gray-700 mb-1">Título / Identificação da Ordem</label>
|
||||
<input type="text" name="title" required placeholder="Ex: Processo nº 123456 - Bloqueio Jogos"
|
||||
oninvalid="this.setCustomValidity('Por favor, preencha o título da ordem.')"
|
||||
oninput="this.setCustomValidity('')"
|
||||
class="w-full px-4 py-2 rounded-lg border border-gray-300 focus:ring-2 focus:ring-primary-500 focus:border-primary-500 outline-none">
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label class="block text-sm font-medium text-gray-700 mb-1">Tipo da Ordem</label>
|
||||
<select name="type" required oninvalid="this.setCustomValidity('Por favor, selecione o tipo da ordem.')"
|
||||
oninput="this.setCustomValidity('')"
|
||||
class="w-full px-4 py-2 rounded-lg border border-gray-300 focus:ring-2 focus:ring-primary-500 focus:border-primary-500 outline-none">
|
||||
<option value="block">Bloqueio</option>
|
||||
<option value="unblock">Desbloqueio</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label class="block text-sm font-medium text-gray-700 mb-1">Data de Recebimento</label>
|
||||
<input type="date" name="received_at"
|
||||
class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-primary-500 focus:border-transparent"
|
||||
required oninvalid="this.setCustomValidity('Por favor, informe a data de recebimento.')"
|
||||
oninput="this.setCustomValidity('')">
|
||||
</div>
|
||||
|
||||
<div class="col-span-2">
|
||||
<label class="block text-sm font-medium text-gray-700 mb-1">Conteúdo do Email / Descrição</label>
|
||||
<div id="editor" class="bg-white" style="height: 200px;"></div>
|
||||
<input type="hidden" name="content" id="content">
|
||||
</div>
|
||||
|
||||
<div class="col-span-2">
|
||||
<label class="block text-sm font-medium text-gray-700 mb-1">Arquivo de Domínios (.csv, .txt)</label>
|
||||
<div x-data="{ fileName: '' }" class="mt-1">
|
||||
<label
|
||||
class="flex justify-center px-6 pt-5 pb-6 border-2 border-gray-300 border-dashed rounded-lg cursor-pointer hover:border-primary-500 transition-colors bg-white">
|
||||
<div class="space-y-1 text-center">
|
||||
<svg class="mx-auto h-12 w-12 text-gray-400" stroke="currentColor" fill="none"
|
||||
viewBox="0 0 48 48" aria-hidden="true">
|
||||
<path
|
||||
d="M28 8H12a4 4 0 00-4 4v20m32-12v8m0 0v8a4 4 0 01-4 4H12a4 4 0 01-4-4v-4m32-4l-3.172-3.172a4 4 0 00-5.656 0L28 28M8 32l9.172-9.172a4 4 0 015.656 0L28 28m0 0l4 4m4-24h8m-4-4v8m-12 4h.02"
|
||||
stroke-width="2" stroke-linecap="round" stroke-linejoin="round" />
|
||||
</svg>
|
||||
<div class="flex text-sm text-gray-600 justify-center">
|
||||
<span class="font-medium text-primary-600 hover:text-primary-500">Upload um
|
||||
arquivo</span>
|
||||
<p class="pl-1">ou arraste e solte</p>
|
||||
</div>
|
||||
<p class="text-xs text-gray-500">CSV ou TXT até 10MB</p>
|
||||
<p class="text-sm font-semibold text-gray-800 mt-2"
|
||||
x-text="fileName ? 'Selecionado: ' + fileName : ''"></p>
|
||||
</div>
|
||||
<input type="file" name="csv_file" class="sr-only" accept=".csv,.txt"
|
||||
@change="fileName = $event.target.files[0].name" required
|
||||
oninvalid="this.setCustomValidity('Por favor, selecione um arquivo CSV ou TXT.')"
|
||||
oninput="this.setCustomValidity('')">
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex justify-end space-x-3 pt-4 border-t border-gray-100">
|
||||
<a href="/admin/orders"
|
||||
class="px-4 py-2 text-gray-700 bg-gray-100 rounded-lg hover:bg-gray-200 transition-colors">Cancelar</a>
|
||||
<button type="submit"
|
||||
class="px-4 py-2 text-white bg-primary-600 rounded-lg hover:bg-primary-700 transition-colors">Salvar e
|
||||
Processar</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<!-- Quill Script -->
|
||||
<script src="https://cdn.quilljs.com/1.3.6/quill.js"></script>
|
||||
<script>
|
||||
var quill = new Quill('#editor', {
|
||||
theme: 'snow',
|
||||
placeholder: 'Cole o conteúdo do email ou descreva a ordem aqui...',
|
||||
modules: {
|
||||
toolbar: [
|
||||
['bold', 'italic', 'underline', 'strike'],
|
||||
['blockquote', 'code-block'],
|
||||
[{ 'header': 1 }, { 'header': 2 }],
|
||||
[{ 'list': 'ordered' }, { 'list': 'bullet' }],
|
||||
[{ 'script': 'sub' }, { 'script': 'super' }],
|
||||
[{ 'indent': '-1' }, { 'indent': '+1' }],
|
||||
[{ 'direction': 'rtl' }],
|
||||
[{ 'size': ['small', false, 'large', 'huge'] }],
|
||||
[{ 'header': [1, 2, 3, 4, 5, 6, false] }],
|
||||
[{ 'color': [] }, { 'background': [] }],
|
||||
[{ 'font': [] }],
|
||||
[{ 'align': [] }],
|
||||
['clean'],
|
||||
['link']
|
||||
]
|
||||
}
|
||||
});
|
||||
|
||||
var form = document.getElementById('orderForm');
|
||||
form.onsubmit = function () {
|
||||
var content = document.querySelector('input[name=content]');
|
||||
content.value = quill.root.innerHTML;
|
||||
};
|
||||
</script>
|
||||
85
resources/views/admin/orders/index.php
Normal file
85
resources/views/admin/orders/index.php
Normal file
@@ -0,0 +1,85 @@
|
||||
<div class="bg-white rounded-xl shadow-sm border border-gray-100 overflow-hidden">
|
||||
<div class="px-6 py-4 border-b border-gray-100 flex justify-between items-center bg-gray-50">
|
||||
<h3 class="text-lg font-semibold text-gray-800">Ordens Judiciais</h3>
|
||||
<a href="/admin/orders/create"
|
||||
class="bg-primary-600 hover:bg-primary-700 text-white px-4 py-2 rounded-lg text-sm font-medium transition-colors flex items-center">
|
||||
<svg class="w-4 h-4 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 4v16m8-8H4"></path>
|
||||
</svg>
|
||||
Nova Ordem
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<?php if (isset($_SESSION['flash_success'])): ?>
|
||||
<div class="bg-green-50 border-l-4 border-green-500 p-4 m-6">
|
||||
<p class="text-sm text-green-700"><?= $_SESSION['flash_success'] ?></p>
|
||||
</div>
|
||||
<?php unset($_SESSION['flash_success']); ?>
|
||||
<?php endif; ?>
|
||||
|
||||
<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">ID</th>
|
||||
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Título
|
||||
</th>
|
||||
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Tipo</th>
|
||||
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Início do
|
||||
Bloqueio</th>
|
||||
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Ações
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody class="divide-y divide-gray-100">
|
||||
<?php if (!empty($orders)): ?>
|
||||
<?php foreach ($orders as $order): ?>
|
||||
<tr class="hover:bg-gray-50 transition-colors">
|
||||
<td class="px-6 py-4 text-sm text-gray-500"><?= $order['id'] ?></td>
|
||||
<td class="px-6 py-4 text-sm font-medium text-gray-900"><?= htmlspecialchars($order['title']) ?>
|
||||
</td>
|
||||
<td class="px-6 py-4 text-sm">
|
||||
<span
|
||||
class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full <?= $order['type'] == 'block' ? 'bg-red-100 text-red-800' : 'bg-green-100 text-green-800' ?>">
|
||||
<?= $order['type'] == 'block' ? 'Bloqueio' : 'Desbloqueio' ?>
|
||||
</span>
|
||||
</td>
|
||||
<td class="px-6 py-4 text-sm text-gray-500"><?= date('d/m/Y', strtotime($order['received_at'])) ?>
|
||||
</td>
|
||||
<td class="px-6 py-4 text-sm font-medium">
|
||||
<a href="/admin/orders/view/<?= $order['id'] ?>"
|
||||
class="text-primary-600 hover:text-primary-900 hover:underline">Detalhes</a>
|
||||
</td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
<?php else: ?>
|
||||
<tr>
|
||||
<td colspan="5" class="px-6 py-4 text-center text-gray-500">Nenhuma ordem encontrada.</td>
|
||||
</tr>
|
||||
<?php endif; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<?php if (isset($pagination) && $pagination['total'] > 1): ?>
|
||||
<div class="px-6 py-4 border-t border-gray-100 flex justify-between items-center">
|
||||
<div>
|
||||
<span class="text-sm text-gray-700">
|
||||
Página <span class="font-medium"><?= $pagination['current'] ?></span> de <span
|
||||
class="font-medium"><?= $pagination['total'] ?></span>
|
||||
</span>
|
||||
</div>
|
||||
<div class="flex space-x-2">
|
||||
<?php if ($pagination['prev']): ?>
|
||||
<a href="?page=<?= $pagination['prev'] ?>"
|
||||
class="px-3 py-1 border border-gray-300 rounded-md text-sm font-medium text-gray-700 hover:bg-gray-50">Anterior</a>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if ($pagination['next']): ?>
|
||||
<a href="?page=<?= $pagination['next'] ?>"
|
||||
class="px-3 py-1 border border-gray-300 rounded-md text-sm font-medium text-gray-700 hover:bg-gray-50">Próxima</a>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
61
resources/views/admin/orders/view.php
Normal file
61
resources/views/admin/orders/view.php
Normal file
@@ -0,0 +1,61 @@
|
||||
<div class="space-y-6">
|
||||
<div class="bg-white rounded-xl shadow-sm border border-gray-100 p-6">
|
||||
<div class="flex justify-between items-start">
|
||||
<div>
|
||||
<h3 class="text-xl font-bold text-gray-900"><?= htmlspecialchars($order['title']) ?></h3>
|
||||
<p class="text-sm text-gray-500 mt-1">Recebido em
|
||||
<?= date('d/m/Y H:i', strtotime($order['received_at'])) ?>
|
||||
</p>
|
||||
</div>
|
||||
<span
|
||||
class="px-3 py-1 rounded-full text-sm font-semibold <?= $order['type'] == 'block' ? 'bg-red-100 text-red-800' : 'bg-green-100 text-green-800' ?>">
|
||||
<?= $order['type'] == 'block' ? 'Bloqueio' : 'Desbloqueio' ?>
|
||||
</span>
|
||||
</div>
|
||||
<div class="mt-6 border-t border-gray-100 pt-4">
|
||||
<h4 class="text-sm font-medium text-gray-700">Conteúdo / Descrição</h4>
|
||||
<style>
|
||||
.prose a {
|
||||
color: #2563eb;
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.prose a:hover {
|
||||
color: #1e40af;
|
||||
}
|
||||
</style>
|
||||
<div class="mt-2 text-gray-600 text-sm prose max-w-none"><?= $order['content'] ?></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="bg-white rounded-xl shadow-sm border border-gray-100 overflow-hidden">
|
||||
<div class="px-6 py-4 border-b border-gray-100 bg-gray-50">
|
||||
<h3 class="text-lg font-semibold text-gray-800">Domínios Afetados (<?= count($items) ?>)</h3>
|
||||
</div>
|
||||
<div class="overflow-x-auto max-h-96">
|
||||
<table class="w-full text-left border-collapse">
|
||||
<thead class="bg-gray-50 sticky top-0">
|
||||
<tr>
|
||||
<th class="px-6 py-3 text-xs font-medium text-gray-500 uppercase tracking-wider">Domínio</th>
|
||||
<th class="px-6 py-3 text-xs font-medium text-gray-500 uppercase tracking-wider">Ação Nesta
|
||||
Ordem</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody class="divide-y divide-gray-100">
|
||||
<?php foreach ($items as $item): ?>
|
||||
<tr class="hover:bg-gray-50">
|
||||
<td class="px-6 py-3 text-sm font-mono text-gray-900"><?= htmlspecialchars($item['name']) ?>
|
||||
</td>
|
||||
<td class="px-6 py-3 text-sm">
|
||||
<span
|
||||
class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full <?= $item['action'] == 'block' ? 'bg-red-100 text-red-800' : 'bg-green-100 text-green-800' ?>">
|
||||
<?= $item['action'] == 'block' ? 'Bloquear' : 'Desbloquear' ?>
|
||||
</span>
|
||||
</td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
65
resources/views/admin/profile.php
Normal file
65
resources/views/admin/profile.php
Normal file
@@ -0,0 +1,65 @@
|
||||
<div class="max-w-4xl mx-auto space-y-6">
|
||||
|
||||
<!-- Profile Info -->
|
||||
<div class="bg-white rounded-xl shadow-sm border border-gray-100 p-6">
|
||||
<h3 class="text-lg font-semibold text-gray-800 mb-6">Informações Pessoais</h3>
|
||||
|
||||
<form action="/admin/profile/update" method="POST" class="space-y-4">
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
|
||||
<div>
|
||||
<label class="block text-sm font-medium text-gray-700 mb-1">Nome</label>
|
||||
<input type="text" name="name" value="<?= htmlspecialchars($user['name']) ?>" required
|
||||
class="w-full px-4 py-2 rounded-lg border border-gray-300 focus:ring-2 focus:ring-primary-500 focus:border-primary-500 outline-none">
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label class="block text-sm font-medium text-gray-700 mb-1">Email</label>
|
||||
<input type="email" name="email" value="<?= htmlspecialchars($user['email']) ?>" required
|
||||
class="w-full px-4 py-2 rounded-lg border border-gray-300 focus:ring-2 focus:ring-primary-500 focus:border-primary-500 outline-none">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex justify-end pt-4">
|
||||
<button type="submit"
|
||||
class="bg-primary-600 hover:bg-primary-700 text-white px-4 py-2 rounded-lg text-sm font-medium transition-colors">
|
||||
Salvar Alterações
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<!-- Change Password -->
|
||||
<div class="bg-white rounded-xl shadow-sm border border-gray-100 p-6">
|
||||
<h3 class="text-lg font-semibold text-gray-800 mb-6">Alterar Senha</h3>
|
||||
|
||||
<form action="/admin/profile/password" method="POST" class="space-y-4">
|
||||
<div>
|
||||
<label class="block text-sm font-medium text-gray-700 mb-1">Senha Atual</label>
|
||||
<input type="password" name="current_password" required
|
||||
class="w-full px-4 py-2 rounded-lg border border-gray-300 focus:ring-2 focus:ring-primary-500 focus:border-primary-500 outline-none">
|
||||
</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-1">Nova Senha</label>
|
||||
<input type="password" name="new_password" required
|
||||
class="w-full px-4 py-2 rounded-lg border border-gray-300 focus:ring-2 focus:ring-primary-500 focus:border-primary-500 outline-none">
|
||||
<p class="text-xs text-gray-500 mt-1">Mínimo 8 caracteres, 1 maiúscula, 1 especial.</p>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label class="block text-sm font-medium text-gray-700 mb-1">Confirmar Nova Senha</label>
|
||||
<input type="password" name="confirm_password" required
|
||||
class="w-full px-4 py-2 rounded-lg border border-gray-300 focus:ring-2 focus:ring-primary-500 focus:border-primary-500 outline-none">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex justify-end pt-4">
|
||||
<button type="submit"
|
||||
class="bg-gray-800 hover:bg-gray-900 text-white px-4 py-2 rounded-lg text-sm font-medium transition-colors">
|
||||
Alterar Senha
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
58
resources/views/admin/search/results.php
Normal file
58
resources/views/admin/search/results.php
Normal file
@@ -0,0 +1,58 @@
|
||||
<div class="space-y-6">
|
||||
<div class="bg-white rounded-xl shadow-sm border border-gray-100 p-6">
|
||||
<h3 class="text-lg font-semibold text-gray-800 mb-4">Resultados para "<?= htmlspecialchars($query) ?>"</h3>
|
||||
|
||||
<?php if (empty($results['clients']) && empty($results['servers']) && empty($results['orders']) && empty($results['domains'])): ?>
|
||||
<p class="text-gray-500">Nenhum resultado encontrado.</p>
|
||||
<?php else: ?>
|
||||
|
||||
<?php if (!empty($results['clients'])): ?>
|
||||
<div class="mb-6">
|
||||
<h4 class="text-sm font-bold text-gray-500 uppercase tracking-wider mb-2">Clientes</h4>
|
||||
<ul class="divide-y divide-gray-100">
|
||||
<?php foreach ($results['clients'] as $item): ?>
|
||||
<li class="py-2"><a href="/admin/clients/edit/<?= $item['id'] ?>"
|
||||
class="text-primary-600 hover:underline"><?= htmlspecialchars($item['name']) ?></a></li>
|
||||
<?php endforeach; ?>
|
||||
</ul>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if (!empty($results['servers'])): ?>
|
||||
<div class="mb-6">
|
||||
<h4 class="text-sm font-bold text-gray-500 uppercase tracking-wider mb-2">Servidores</h4>
|
||||
<ul class="divide-y divide-gray-100">
|
||||
<?php foreach ($results['servers'] as $item): ?>
|
||||
<li class="py-2"><a href="/admin/servers"
|
||||
class="text-primary-600 hover:underline"><?= htmlspecialchars($item['name']) ?></a></li>
|
||||
<?php endforeach; ?>
|
||||
</ul>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if (!empty($results['orders'])): ?>
|
||||
<div class="mb-6">
|
||||
<h4 class="text-sm font-bold text-gray-500 uppercase tracking-wider mb-2">Ordens</h4>
|
||||
<ul class="divide-y divide-gray-100">
|
||||
<?php foreach ($results['orders'] as $item): ?>
|
||||
<li class="py-2"><a href="/admin/orders/view/<?= $item['id'] ?>"
|
||||
class="text-primary-600 hover:underline"><?= htmlspecialchars($item['name']) ?></a></li>
|
||||
<?php endforeach; ?>
|
||||
</ul>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if (!empty($results['domains'])): ?>
|
||||
<div class="mb-6">
|
||||
<h4 class="text-sm font-bold text-gray-500 uppercase tracking-wider mb-2">Domínios</h4>
|
||||
<ul class="divide-y divide-gray-100">
|
||||
<?php foreach ($results['domains'] as $item): ?>
|
||||
<li class="py-2"><span class="text-gray-700"><?= htmlspecialchars($item['name']) ?></span></li>
|
||||
<?php endforeach; ?>
|
||||
</ul>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</div>
|
||||
112
resources/views/admin/servers/form.php
Normal file
112
resources/views/admin/servers/form.php
Normal file
@@ -0,0 +1,112 @@
|
||||
<div class="max-w-2xl mx-auto bg-white rounded-xl shadow-sm border border-gray-100 p-6">
|
||||
<h3 class="text-lg font-semibold text-gray-800 mb-6"><?= isset($server) ? 'Editar Servidor' : 'Novo Servidor' ?>
|
||||
</h3>
|
||||
|
||||
<?php if (isset($_SESSION['flash_error'])): ?>
|
||||
<div class="bg-red-50 text-red-700 p-4 rounded-lg mb-6">
|
||||
<?= $_SESSION['flash_error'];
|
||||
unset($_SESSION['flash_error']); ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<form action="<?= isset($server) ? '/admin/servers/update/' . $server['id'] : '/admin/servers/store' ?>"
|
||||
method="POST">
|
||||
<div class="space-y-4">
|
||||
<div>
|
||||
<label class="block text-sm font-medium text-gray-700 mb-1">Cliente</label>
|
||||
<select name="client_id"
|
||||
class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-primary-500 focus:border-transparent"
|
||||
required>
|
||||
<option value="">Selecione um cliente...</option>
|
||||
<?php foreach ($clients as $client): ?>
|
||||
<option value="<?= $client['id'] ?>" <?= (isset($server) && $server['client_id'] == $client['id']) ? 'selected' : '' ?>>
|
||||
<?= htmlspecialchars($client['name']) ?> (<?= htmlspecialchars($client['asn']) ?>)
|
||||
</option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label class="block text-sm font-medium text-gray-700 mb-1">Nome do Servidor</label>
|
||||
<input type="text" name="name" value="<?= $server['name'] ?? '' ?>"
|
||||
class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-primary-500 focus:border-transparent"
|
||||
required>
|
||||
</div>
|
||||
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||
<div>
|
||||
<label class="block text-sm font-medium text-gray-700 mb-1">IP v4</label>
|
||||
<input type="text" name="ip_v4" value="<?= $server['ip_v4'] ?? '' ?>"
|
||||
class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-primary-500 focus:border-transparent"
|
||||
required placeholder="0.0.0.0">
|
||||
</div>
|
||||
<div>
|
||||
<label class="block text-sm font-medium text-gray-700 mb-1">IP v6 (Opcional)</label>
|
||||
<input type="text" name="ip_v6" value="<?= $server['ip_v6'] ?? '' ?>"
|
||||
class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-primary-500 focus:border-transparent"
|
||||
placeholder="::1">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php if (isset($server)): ?>
|
||||
<div>
|
||||
<label class="block text-sm font-medium text-gray-700 mb-1">Status</label>
|
||||
<select name="status"
|
||||
class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-primary-500 focus:border-transparent">
|
||||
<option value="active" <?= $server['status'] == 'active' ? 'selected' : '' ?>>Ativo</option>
|
||||
<option value="inactive" <?= $server['status'] == 'inactive' ? 'selected' : '' ?>>Inativo</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="col-span-1 md:col-span-2 border-t border-gray-100 pt-4 mt-2">
|
||||
<h4 class="text-sm font-semibold text-gray-900 mb-4">Integração do Agente</h4>
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||
<div>
|
||||
<label class="block text-sm font-medium text-gray-700 mb-1">Serial Key</label>
|
||||
<div class="flex">
|
||||
<input type="text" value="<?= $server['serial_key'] ?>" readonly
|
||||
class="w-full px-4 py-2 bg-gray-50 border border-gray-300 rounded-l-lg text-gray-500 font-mono text-sm">
|
||||
<button type="button"
|
||||
onclick="navigator.clipboard.writeText('<?= $server['serial_key'] ?>')"
|
||||
class="px-3 py-2 bg-gray-100 border border-l-0 border-gray-300 rounded-r-lg hover:bg-gray-200 text-gray-600">
|
||||
<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="M8 5H6a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2v-1M8 5a2 2 0 002 2h2a2 2 0 002-2M8 5a2 2 0 012-2h2a2 2 0 012 2m0 0h2a2 2 0 012 2v3m2 4H10m0 0l3-3m-3 3l3 3">
|
||||
</path>
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<label class="block text-sm font-medium text-gray-700 mb-1">Machine ID Vinculado</label>
|
||||
<?php if (!empty($server['machine_id'])): ?>
|
||||
<div class="flex items-center space-x-2">
|
||||
<input type="text" value="<?= $server['machine_id'] ?>" readonly
|
||||
class="w-full px-4 py-2 bg-gray-50 border border-gray-300 rounded-lg text-gray-500 font-mono text-sm">
|
||||
<a href="/admin/servers/reset-machine/<?= $server['id'] ?>"
|
||||
onclick="return confirm('Tem certeza? Isso permitirá que um novo servidor utilize esta Serial Key.')"
|
||||
class="px-4 py-2 bg-red-100 text-red-700 rounded-lg hover:bg-red-200 text-sm whitespace-nowrap">
|
||||
Desvincular
|
||||
</a>
|
||||
</div>
|
||||
<?php else: ?>
|
||||
<div class="px-4 py-2 bg-yellow-50 border border-yellow-100 rounded-lg text-yellow-700 text-sm">
|
||||
Nenhuma máquina vinculada. Aguardando conexão.
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
|
||||
<div class="mt-6 flex justify-end space-x-3">
|
||||
<a href="/admin/servers"
|
||||
class="px-4 py-2 text-gray-700 hover:bg-gray-100 rounded-lg transition-colors">Cancelar</a>
|
||||
<button type="submit"
|
||||
class="px-4 py-2 bg-primary-600 text-white rounded-lg hover:bg-primary-700 transition-colors">
|
||||
<?= isset($server) ? 'Salvar Alterações' : 'Criar Servidor' ?>
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
87
resources/views/admin/servers/index.php
Normal file
87
resources/views/admin/servers/index.php
Normal file
@@ -0,0 +1,87 @@
|
||||
<div class="bg-white rounded-xl shadow-sm border border-gray-100 overflow-hidden">
|
||||
<div class="px-6 py-4 border-b border-gray-100 flex justify-between items-center bg-gray-50">
|
||||
<h3 class="text-lg font-semibold text-gray-800">Servidores Registrados</h3>
|
||||
<a href="/admin/servers/create"
|
||||
class="bg-primary-600 hover:bg-primary-700 text-white px-4 py-2 rounded-lg text-sm font-medium transition-colors flex items-center">
|
||||
<svg class="w-4 h-4 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 4v16m8-8H4"></path>
|
||||
</svg>
|
||||
Novo Servidor
|
||||
</a>
|
||||
</div>
|
||||
<div class="overflow-x-auto">
|
||||
<table class="w-full text-left border-collapse">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="px-6 py-3 text-xs font-medium text-gray-500 uppercase tracking-wider bg-gray-50">Nome
|
||||
</th>
|
||||
<th class="px-6 py-3 text-xs font-medium text-gray-500 uppercase tracking-wider bg-gray-50">Cliente
|
||||
</th>
|
||||
<th class="px-6 py-3 text-xs font-medium text-gray-500 uppercase tracking-wider bg-gray-50">IP (v4)
|
||||
</th>
|
||||
<th class="px-6 py-3 text-xs font-medium text-gray-500 uppercase tracking-wider bg-gray-50">Serial
|
||||
Key</th>
|
||||
<th class="px-6 py-3 text-xs font-medium text-gray-500 uppercase tracking-wider bg-gray-50">Status
|
||||
</th>
|
||||
<th class="px-6 py-3 text-xs font-medium text-gray-500 uppercase tracking-wider bg-gray-50">Agente
|
||||
</th>
|
||||
<th class="px-6 py-3 text-xs font-medium text-gray-500 uppercase tracking-wider bg-gray-50">Ações
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody class="divide-y divide-gray-100">
|
||||
<?php if (!empty($servers)): ?>
|
||||
<?php foreach ($servers as $server): ?>
|
||||
<?php
|
||||
$lastSeen = !empty($server['last_seen']) ? strtotime($server['last_seen']) : 0;
|
||||
$isOnline = $lastSeen && (time() - $lastSeen < 300); // 5 minutes
|
||||
$lastSeenText = $lastSeen ? date('d/m/Y H:i', $lastSeen) : 'Nunca';
|
||||
?>
|
||||
<tr class="hover:bg-gray-50 transition-colors">
|
||||
<td class="px-6 py-4 text-sm font-medium text-gray-900"><?= htmlspecialchars($server['name']) ?>
|
||||
</td>
|
||||
<td class="px-6 py-4 text-sm text-gray-500"><?= htmlspecialchars($server['client_name']) ?></td>
|
||||
<td class="px-6 py-4 text-sm text-gray-500"><?= htmlspecialchars($server['ip_v4']) ?></td>
|
||||
<td class="px-6 py-4 text-sm text-gray-400 font-mono text-xs">
|
||||
<div class="flex items-center space-x-2">
|
||||
<span><?= substr($server['serial_key'], 0, 8) ?>...</span>
|
||||
<button
|
||||
onclick="navigator.clipboard.writeText('<?= $server['serial_key'] ?>'); alert('Key copiada!');"
|
||||
class="text-primary-600 hover:text-primary-800" title="Copiar Serial Completo">
|
||||
<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="M8 16H6a2 2 0 01-2-2V6a2 2 0 012-2h8a2 2 0 012 2v2m-6 12h8a2 2 0 002-2v-8a2 2 0 00-2-2h-8a2 2 0 00-2 2v8a2 2 0 002 2z">
|
||||
</path>
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
</td>
|
||||
<td class="px-6 py-4 text-sm">
|
||||
<span
|
||||
class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full <?= $server['status'] == 'active' ? 'bg-green-100 text-green-800' : 'bg-gray-100 text-gray-800' ?>">
|
||||
<?= $server['status'] == 'active' ? 'Ativo' : 'Inativo' ?>
|
||||
</span>
|
||||
</td>
|
||||
<td class="px-6 py-4 text-sm">
|
||||
<span title="Visto por último: <?= $lastSeenText ?>"
|
||||
class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full <?= $isOnline ? 'bg-green-100 text-green-800' : 'bg-red-100 text-red-800' ?>">
|
||||
<?= $isOnline ? 'Online' : 'Offline' ?>
|
||||
</span>
|
||||
</td>
|
||||
<td class="px-6 py-4 text-sm font-medium">
|
||||
<a href="/admin/servers/edit/<?= $server['id'] ?>"
|
||||
class="text-[#1e3a8a] hover:text-blue-900 mr-3">Editar</a>
|
||||
<a href="/admin/servers/delete/<?= $server['id'] ?>" class="text-red-600 hover:text-red-900"
|
||||
onclick="return confirm('Tem certeza?')">Excluir</a>
|
||||
</td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
<?php else: ?>
|
||||
<tr>
|
||||
<td colspan="6" class="px-6 py-4 text-center text-gray-500">Nenhum servidor encontrado.</td>
|
||||
</tr>
|
||||
<?php endif; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
Reference in New Issue
Block a user