779 lines
32 KiB
PHP
779 lines
32 KiB
PHP
<?php
|
||
|
||
require_once __DIR__ . '/db/auth.php';
|
||
require_once __DIR__ . '/db/scdiscord.php';
|
||
|
||
auth_start_session();
|
||
auth_bootstrap();
|
||
auth_handle_page_access_post('scwebhook.php', 'WEBHOOK');
|
||
auth_require_page_access('scwebhook.php', 'WEBHOOK');
|
||
scdiscord_bootstrap();
|
||
|
||
$db = db();
|
||
$csrf_token = auth_csrf_token();
|
||
$flash = auth_flash_get();
|
||
$flash_type = $flash['type'] ?? '';
|
||
$flash_message = $flash['message'] ?? '';
|
||
$current_session_user = $_SESSION['user'] ?? '';
|
||
|
||
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||
$submitted_csrf = (string) ($_POST['csrf_token'] ?? '');
|
||
if (!auth_validate_csrf($submitted_csrf)) {
|
||
auth_flash_set('error', 'Jeton CSRF invalide.');
|
||
header('Location: scwebhook.php');
|
||
exit;
|
||
}
|
||
|
||
$action = (string) ($_POST['action'] ?? '');
|
||
|
||
if ($action === 'add_webhook' || $action === 'update_webhook') {
|
||
$webhook_id = (int) ($_POST['webhook_id'] ?? 0);
|
||
$cl_scwebhook_name = trim((string) ($_POST['cl_scwebhook_name'] ?? ''));
|
||
$cl_scwebhook_url = trim((string) ($_POST['cl_scwebhook_url'] ?? ''));
|
||
$cl_scwebhook_is_forum = 0;
|
||
|
||
if ($cl_scwebhook_name === '' || $cl_scwebhook_url === '') {
|
||
auth_flash_set('error', 'Le nom et l’URL du webhook sont obligatoires.');
|
||
header('Location: scwebhook.php');
|
||
exit;
|
||
}
|
||
|
||
if (!filter_var($cl_scwebhook_url, FILTER_VALIDATE_URL)) {
|
||
auth_flash_set('error', 'L’URL du webhook Discord est invalide.');
|
||
header('Location: scwebhook.php');
|
||
exit;
|
||
}
|
||
|
||
try {
|
||
if ($action === 'add_webhook') {
|
||
$stmt = $db->prepare('INSERT INTO tbl_scwebhooks (cl_scwebhook_name, cl_scwebhook_url, cl_scwebhook_is_forum) VALUES (:name, :url, :is_forum)');
|
||
$stmt->execute([
|
||
'name' => $cl_scwebhook_name,
|
||
'url' => $cl_scwebhook_url,
|
||
'is_forum' => $cl_scwebhook_is_forum,
|
||
]);
|
||
auth_flash_set('success', 'Webhook Discord ajouté avec succès.');
|
||
} else {
|
||
if ($webhook_id <= 0) {
|
||
throw new RuntimeException('ID de webhook invalide.');
|
||
}
|
||
|
||
$stmt = $db->prepare('UPDATE tbl_scwebhooks SET cl_scwebhook_name = :name, cl_scwebhook_url = :url, cl_scwebhook_is_forum = :is_forum WHERE cl_scwebhook_id = :id');
|
||
$stmt->execute([
|
||
'name' => $cl_scwebhook_name,
|
||
'url' => $cl_scwebhook_url,
|
||
'is_forum' => $cl_scwebhook_is_forum,
|
||
'id' => $webhook_id,
|
||
]);
|
||
auth_flash_set('success', 'Webhook Discord mis à jour.');
|
||
}
|
||
} catch (Throwable $e) {
|
||
auth_flash_set('error', 'Erreur webhook : ' . $e->getMessage());
|
||
}
|
||
|
||
header('Location: scwebhook.php');
|
||
exit;
|
||
}
|
||
|
||
if ($action === 'delete_webhook') {
|
||
$webhook_id = (int) ($_POST['webhook_id'] ?? 0);
|
||
|
||
if ($webhook_id > 0) {
|
||
try {
|
||
$stmt_usage = $db->prepare('SELECT COUNT(*) FROM tbl_scnotifications WHERE cl_scnotification_webhook_id = :id');
|
||
$stmt_usage->execute(['id' => $webhook_id]);
|
||
$usage_total = (int) $stmt_usage->fetchColumn();
|
||
|
||
if ($usage_total > 0) {
|
||
auth_flash_set('error', 'Suppression refusée : ce webhook est déjà relié à l’historique des notifications.');
|
||
} else {
|
||
$stmt = $db->prepare('DELETE FROM tbl_scwebhooks WHERE cl_scwebhook_id = :id');
|
||
$stmt->execute(['id' => $webhook_id]);
|
||
auth_flash_set('success', 'Webhook Discord supprimé.');
|
||
}
|
||
} catch (Throwable $e) {
|
||
auth_flash_set('error', 'Erreur suppression webhook : ' . $e->getMessage());
|
||
}
|
||
}
|
||
|
||
header('Location: scwebhook.php');
|
||
exit;
|
||
}
|
||
|
||
if ($action === 'add_banner' || $action === 'update_banner') {
|
||
$banner_id = (int) ($_POST['banner_id'] ?? 0);
|
||
$cl_scbanner_name = trim((string) ($_POST['cl_scbanner_name'] ?? ''));
|
||
$cl_scbanner_url = trim((string) ($_POST['cl_scbanner_url'] ?? ''));
|
||
$cl_scbanner_border_color = scdiscord_normalize_hex_color((string) ($_POST['cl_scbanner_border_color'] ?? ''));
|
||
|
||
if ($cl_scbanner_name === '' || $cl_scbanner_url === '') {
|
||
auth_flash_set('error', 'Le nom et le lien d’image de la bannière sont obligatoires.');
|
||
header('Location: scwebhook.php');
|
||
exit;
|
||
}
|
||
|
||
if (!filter_var($cl_scbanner_url, FILTER_VALIDATE_URL)) {
|
||
auth_flash_set('error', 'L’URL de la bannière est invalide.');
|
||
header('Location: scwebhook.php');
|
||
exit;
|
||
}
|
||
|
||
try {
|
||
if ($action === 'add_banner') {
|
||
$stmt = $db->prepare('INSERT INTO tbl_scbanners (cl_scbanner_name, cl_scbanner_url, cl_scbanner_border_color) VALUES (:name, :url, :border_color)');
|
||
$stmt->execute([
|
||
'name' => $cl_scbanner_name,
|
||
'url' => $cl_scbanner_url,
|
||
'border_color' => $cl_scbanner_border_color,
|
||
]);
|
||
auth_flash_set('success', 'Bannière Discord ajoutée avec succès.');
|
||
} else {
|
||
if ($banner_id <= 0) {
|
||
throw new RuntimeException('ID de bannière invalide.');
|
||
}
|
||
|
||
$stmt = $db->prepare('UPDATE tbl_scbanners SET cl_scbanner_name = :name, cl_scbanner_url = :url, cl_scbanner_border_color = :border_color WHERE cl_scbanner_id = :id');
|
||
$stmt->execute([
|
||
'name' => $cl_scbanner_name,
|
||
'url' => $cl_scbanner_url,
|
||
'border_color' => $cl_scbanner_border_color,
|
||
'id' => $banner_id,
|
||
]);
|
||
auth_flash_set('success', 'Bannière Discord mise à jour.');
|
||
}
|
||
} catch (Throwable $e) {
|
||
auth_flash_set('error', 'Erreur bannière : ' . $e->getMessage());
|
||
}
|
||
|
||
header('Location: scwebhook.php');
|
||
exit;
|
||
}
|
||
|
||
if ($action === 'delete_banner') {
|
||
$banner_id = (int) ($_POST['banner_id'] ?? 0);
|
||
|
||
if ($banner_id > 0) {
|
||
try {
|
||
$stmt = $db->prepare('DELETE FROM tbl_scbanners WHERE cl_scbanner_id = :id');
|
||
$stmt->execute(['id' => $banner_id]);
|
||
auth_flash_set('success', 'Bannière Discord supprimée.');
|
||
} catch (Throwable $e) {
|
||
auth_flash_set('error', 'Erreur suppression bannière : ' . $e->getMessage());
|
||
}
|
||
}
|
||
|
||
header('Location: scwebhook.php');
|
||
exit;
|
||
}
|
||
}
|
||
|
||
$stmt_webhooks = $db->query('SELECT * FROM tbl_scwebhooks ORDER BY cl_scwebhook_name ASC');
|
||
$webhooks = $stmt_webhooks->fetchAll();
|
||
|
||
$stmt_banners = $db->query('SELECT * FROM tbl_scbanners ORDER BY cl_scbanner_name ASC');
|
||
$banners = $stmt_banners->fetchAll();
|
||
?>
|
||
<!DOCTYPE html>
|
||
<html lang="fr">
|
||
<head>
|
||
<meta charset="UTF-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||
<title>SC Webhook | R.E.A.C.T. Admin</title>
|
||
<link rel="stylesheet" type="text/css" href="css/styles.css">
|
||
<link rel="stylesheet" type="text/css" href="css/default.css">
|
||
<style>
|
||
:root {
|
||
--primary: #a29b78;
|
||
--primary-glow: rgba(162, 155, 120, 0.4);
|
||
--bg-dark: #080a0f;
|
||
--card-bg: rgba(20, 24, 33, 0.85);
|
||
--card-bg-secondary: rgba(255, 255, 255, 0.03);
|
||
--border-glow: rgba(162, 155, 120, 0.25);
|
||
--danger: #ff4d4d;
|
||
--success: #00ff88;
|
||
--muted: #aaaaaa;
|
||
}
|
||
|
||
@font-face {
|
||
font-family: 'Electrolize';
|
||
src: url('fonts/Electrolize-Regular.ttf') format('truetype');
|
||
}
|
||
|
||
* { box-sizing: border-box; }
|
||
|
||
body {
|
||
margin: 0;
|
||
min-height: 100vh;
|
||
background: radial-gradient(circle at top right, #1a1f2e, var(--bg-dark));
|
||
background-attachment: fixed;
|
||
color: #e0e0e0;
|
||
font-family: 'Electrolize', sans-serif;
|
||
overflow-x: hidden;
|
||
}
|
||
|
||
.admin-layout {
|
||
display: flex;
|
||
flex-direction: column;
|
||
max-width: 1400px;
|
||
margin: 0 auto;
|
||
padding: 2rem;
|
||
animation: fadeIn 0.6s ease-out;
|
||
}
|
||
|
||
@keyframes fadeIn {
|
||
from { opacity: 0; transform: translateY(10px); }
|
||
to { opacity: 1; transform: translateY(0); }
|
||
}
|
||
|
||
.admin-topbar,
|
||
.glass-card {
|
||
background: var(--card-bg);
|
||
backdrop-filter: blur(12px);
|
||
border: 1px solid var(--border-glow);
|
||
border-radius: 12px;
|
||
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3);
|
||
}
|
||
|
||
.admin-topbar {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
gap: 1rem;
|
||
padding: 1.5rem 2rem;
|
||
margin-bottom: 2rem;
|
||
}
|
||
|
||
.topbar-info h1 {
|
||
margin: 0;
|
||
font-size: 1.5rem;
|
||
letter-spacing: 2px;
|
||
text-transform: uppercase;
|
||
background: linear-gradient(90deg, #fff, var(--primary));
|
||
-webkit-background-clip: text;
|
||
-webkit-text-fill-color: transparent;
|
||
}
|
||
|
||
.topbar-info p {
|
||
margin: 0.25rem 0 0;
|
||
font-size: 0.85rem;
|
||
color: var(--primary);
|
||
opacity: 0.8;
|
||
}
|
||
|
||
.topbar-actions {
|
||
display: flex;
|
||
gap: 1rem;
|
||
flex-wrap: wrap;
|
||
align-items: center;
|
||
}
|
||
|
||
.session-user {
|
||
opacity: 0.85;
|
||
}
|
||
|
||
.btn-modern {
|
||
display: inline-flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
gap: 0.45rem;
|
||
padding: 0.6rem 1.2rem;
|
||
border-radius: 4px;
|
||
border: 1px solid var(--primary);
|
||
background: transparent;
|
||
color: #fff;
|
||
text-decoration: none;
|
||
text-transform: uppercase;
|
||
font-size: 0.9rem;
|
||
cursor: pointer;
|
||
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
||
font-family: 'Electrolize', sans-serif;
|
||
}
|
||
|
||
.btn-modern:hover {
|
||
background: var(--primary);
|
||
color: var(--bg-dark);
|
||
box-shadow: 0 0 15px var(--primary-glow);
|
||
}
|
||
|
||
.btn-modern.danger {
|
||
border-color: var(--danger);
|
||
color: var(--danger);
|
||
}
|
||
|
||
.btn-modern.danger:hover {
|
||
background: var(--danger);
|
||
color: #fff;
|
||
box-shadow: 0 0 15px rgba(255, 77, 77, 0.3);
|
||
}
|
||
|
||
.btn-modern.secondary {
|
||
border-color: rgba(255, 255, 255, 0.2);
|
||
color: #d6d6d6;
|
||
}
|
||
|
||
.btn-modern.secondary:hover {
|
||
background: rgba(255, 255, 255, 0.12);
|
||
color: #fff;
|
||
box-shadow: none;
|
||
}
|
||
|
||
.btn-mini {
|
||
padding: 0.45rem 0.8rem;
|
||
font-size: 0.72rem;
|
||
}
|
||
|
||
.nav-tabs {
|
||
display: flex;
|
||
flex-wrap: wrap;
|
||
gap: 1rem;
|
||
margin-bottom: 2rem;
|
||
padding-bottom: 1rem;
|
||
border-bottom: 1px solid var(--border-glow);
|
||
}
|
||
|
||
.nav-tabs a {
|
||
text-decoration: none;
|
||
color: #888;
|
||
text-transform: uppercase;
|
||
font-size: 0.9rem;
|
||
transition: color 0.3s;
|
||
}
|
||
|
||
.nav-tabs a:hover,
|
||
.nav-tabs a.active {
|
||
color: var(--primary);
|
||
}
|
||
|
||
.flash {
|
||
margin-bottom: 1.5rem;
|
||
padding: 1rem 1.2rem;
|
||
border-radius: 8px;
|
||
border: 1px solid rgba(255, 255, 255, 0.08);
|
||
background: rgba(255, 255, 255, 0.04);
|
||
}
|
||
|
||
.flash.success { border-color: rgba(0, 255, 136, 0.25); color: #9ff3c8; }
|
||
.flash.error { border-color: rgba(255, 77, 77, 0.25); color: #ff9d9d; }
|
||
|
||
.page-grid {
|
||
display: grid;
|
||
grid-template-columns: 420px 1fr;
|
||
gap: 2rem;
|
||
}
|
||
|
||
.stack {
|
||
display: grid;
|
||
gap: 1.5rem;
|
||
}
|
||
|
||
.glass-card {
|
||
padding: 1.5rem;
|
||
}
|
||
|
||
.glass-card h2 {
|
||
margin: 0 0 1.5rem;
|
||
padding-bottom: 0.75rem;
|
||
font-size: 1.25rem;
|
||
color: var(--primary);
|
||
border-bottom: 1px solid var(--border-glow);
|
||
}
|
||
|
||
.section-note {
|
||
margin: -0.5rem 0 1.2rem;
|
||
color: var(--muted);
|
||
font-size: 0.82rem;
|
||
line-height: 1.5;
|
||
}
|
||
|
||
.form-grid {
|
||
display: grid;
|
||
gap: 1rem;
|
||
}
|
||
|
||
.form-group label {
|
||
display: block;
|
||
margin-bottom: 0.5rem;
|
||
font-size: 0.85rem;
|
||
color: #aaa;
|
||
text-transform: uppercase;
|
||
}
|
||
|
||
.form-control {
|
||
width: 100%;
|
||
padding: 0.8rem 1rem;
|
||
background: rgba(0, 0, 0, 0.3);
|
||
border: 1px solid #444;
|
||
border-radius: 4px;
|
||
color: #fff;
|
||
font-family: 'Electrolize', sans-serif;
|
||
transition: border-color 0.3s, background 0.3s;
|
||
}
|
||
|
||
.form-control:focus {
|
||
outline: none;
|
||
border-color: var(--primary);
|
||
background: rgba(0, 0, 0, 0.5);
|
||
}
|
||
|
||
.form-control[type="color"] {
|
||
min-height: 48px;
|
||
padding: 0.35rem;
|
||
}
|
||
|
||
.checkbox-row {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 0.7rem;
|
||
color: #e7e7e7;
|
||
font-size: 0.9rem;
|
||
}
|
||
|
||
.list-grid {
|
||
display: grid;
|
||
grid-template-columns: 1fr;
|
||
gap: 1.5rem;
|
||
}
|
||
|
||
.table-wrap {
|
||
overflow-x: auto;
|
||
}
|
||
|
||
table {
|
||
width: 100%;
|
||
border-collapse: separate;
|
||
border-spacing: 0 8px;
|
||
}
|
||
|
||
th {
|
||
text-align: left;
|
||
padding: 1rem 0.75rem;
|
||
font-size: 0.8rem;
|
||
text-transform: uppercase;
|
||
color: var(--primary);
|
||
opacity: 0.7;
|
||
}
|
||
|
||
td {
|
||
padding: 1rem 0.75rem;
|
||
background: var(--card-bg-secondary);
|
||
border-top: 1px solid rgba(255, 255, 255, 0.05);
|
||
border-bottom: 1px solid rgba(255, 255, 255, 0.05);
|
||
vertical-align: top;
|
||
text-align: left;
|
||
font-size: 0.88rem;
|
||
}
|
||
|
||
td:first-child {
|
||
border-left: 1px solid rgba(255, 255, 255, 0.05);
|
||
border-radius: 8px 0 0 8px;
|
||
}
|
||
|
||
td:last-child {
|
||
border-right: 1px solid rgba(255, 255, 255, 0.05);
|
||
border-radius: 0 8px 8px 0;
|
||
}
|
||
|
||
tr:hover td {
|
||
background: rgba(162, 155, 120, 0.08);
|
||
}
|
||
|
||
.muted {
|
||
color: var(--muted);
|
||
font-size: 0.8rem;
|
||
}
|
||
|
||
.pill {
|
||
display: inline-flex;
|
||
align-items: center;
|
||
padding: 0.2rem 0.55rem;
|
||
border-radius: 999px;
|
||
background: rgba(255, 255, 255, 0.07);
|
||
font-size: 0.72rem;
|
||
color: #fff;
|
||
}
|
||
|
||
.pill.forum {
|
||
background: rgba(162, 155, 120, 0.18);
|
||
color: #e5dcb7;
|
||
}
|
||
|
||
.banner-preview {
|
||
width: 120px;
|
||
max-height: 42px;
|
||
object-fit: cover;
|
||
border-radius: 6px;
|
||
border: 1px solid rgba(255, 255, 255, 0.08);
|
||
display: block;
|
||
background: #17191e;
|
||
}
|
||
|
||
.color-chip {
|
||
display: inline-flex;
|
||
align-items: center;
|
||
gap: 0.45rem;
|
||
}
|
||
|
||
.color-chip::before {
|
||
content: '';
|
||
width: 14px;
|
||
height: 14px;
|
||
border-radius: 50%;
|
||
background: var(--chip-color, var(--primary));
|
||
box-shadow: 0 0 0 2px rgba(255, 255, 255, 0.08);
|
||
}
|
||
|
||
.actions-inline {
|
||
display: flex;
|
||
flex-wrap: wrap;
|
||
gap: 0.45rem;
|
||
justify-content: flex-end;
|
||
}
|
||
|
||
.empty-state {
|
||
padding: 2rem;
|
||
border: 1px dashed rgba(255, 255, 255, 0.12);
|
||
border-radius: 10px;
|
||
color: #9a9a9a;
|
||
text-align: center;
|
||
}
|
||
|
||
@media (max-width: 1100px) {
|
||
.page-grid { grid-template-columns: 1fr; }
|
||
}
|
||
</style>
|
||
</head>
|
||
<body>
|
||
<?php echo auth_render_page_access_widget('scwebhook.php', 'WEBHOOK'); ?>
|
||
<div class="admin-layout">
|
||
<header class="admin-topbar">
|
||
<div class="topbar-info">
|
||
<h1>R.E.A.C.T. SC Webhook</h1>
|
||
<p>Niveau d'accès : <strong>Administrateur</strong></p>
|
||
</div>
|
||
<div class="topbar-actions">
|
||
<span class="session-user">Connecté : <strong><?php echo htmlspecialchars($current_session_user, ENT_QUOTES, 'UTF-8'); ?></strong></span>
|
||
<a href="index.php" class="btn-modern">Retour au site</a>
|
||
<a href="logout.php" class="btn-modern danger">Déconnexion</a>
|
||
</div>
|
||
</header>
|
||
|
||
<?php echo auth_render_app_nav('scwebhook.php'); ?>
|
||
|
||
<?php if ($flash_message !== ''): ?>
|
||
<div class="flash <?php echo htmlspecialchars($flash_type, ENT_QUOTES, 'UTF-8'); ?>">
|
||
<?php echo htmlspecialchars($flash_message, ENT_QUOTES, 'UTF-8'); ?>
|
||
</div>
|
||
<?php endif; ?>
|
||
|
||
<div class="page-grid">
|
||
<aside class="stack">
|
||
<section class="glass-card">
|
||
<h2 id="webhookFormTitle">Nouveau webhook Discord</h2>
|
||
<p class="section-note">Ajoute la nomination du webhook et son URL. Tous les webhooks enregistrés ici sont traités comme des webhooks Discord génériques.</p>
|
||
<form method="post" id="webhookForm" class="form-grid">
|
||
<input type="hidden" name="csrf_token" value="<?php echo htmlspecialchars($csrf_token, ENT_QUOTES, 'UTF-8'); ?>">
|
||
<input type="hidden" name="action" id="webhookAction" value="add_webhook">
|
||
<input type="hidden" name="webhook_id" id="webhookId" value="">
|
||
|
||
<div class="form-group">
|
||
<label for="cl_scwebhook_name">Nomination du webhook</label>
|
||
<input type="text" id="cl_scwebhook_name" name="cl_scwebhook_name" class="form-control" required placeholder="Ex : news-bops-cig">
|
||
</div>
|
||
|
||
<div class="form-group">
|
||
<label for="cl_scwebhook_url">Lien du webhook</label>
|
||
<input type="url" id="cl_scwebhook_url" name="cl_scwebhook_url" class="form-control" required placeholder="https://discord.com/api/webhooks/...">
|
||
</div>
|
||
|
||
|
||
<button type="submit" class="btn-modern" id="webhookSubmitBtn">Ajouter le webhook</button>
|
||
<button type="button" class="btn-modern secondary" id="webhookCancelBtn" style="display:none;" onclick="resetWebhookForm()">Annuler l’édition</button>
|
||
</form>
|
||
</section>
|
||
|
||
<section class="glass-card">
|
||
<h2 id="bannerFormTitle">Nouvelle bannière</h2>
|
||
<p class="section-note">Chaque bannière stocke un nom, un lien d’image et une couleur de bordure utilisée dans l’embed Discord.</p>
|
||
<form method="post" id="bannerForm" class="form-grid">
|
||
<input type="hidden" name="csrf_token" value="<?php echo htmlspecialchars($csrf_token, ENT_QUOTES, 'UTF-8'); ?>">
|
||
<input type="hidden" name="action" id="bannerAction" value="add_banner">
|
||
<input type="hidden" name="banner_id" id="bannerId" value="">
|
||
|
||
<div class="form-group">
|
||
<label for="cl_scbanner_name">Nom de la bannière</label>
|
||
<input type="text" id="cl_scbanner_name" name="cl_scbanner_name" class="form-control" required placeholder="Ex : Alerte Rouge">
|
||
</div>
|
||
|
||
<div class="form-group">
|
||
<label for="cl_scbanner_url">Lien image</label>
|
||
<input type="url" id="cl_scbanner_url" name="cl_scbanner_url" class="form-control" required placeholder="https://.../banniere.png">
|
||
</div>
|
||
|
||
<div class="form-group">
|
||
<label for="cl_scbanner_border_color">Couleur de bordure</label>
|
||
<input type="color" id="cl_scbanner_border_color" name="cl_scbanner_border_color" class="form-control" value="#ffae00">
|
||
</div>
|
||
|
||
<button type="submit" class="btn-modern" id="bannerSubmitBtn">Ajouter la bannière</button>
|
||
<button type="button" class="btn-modern secondary" id="bannerCancelBtn" style="display:none;" onclick="resetBannerForm()">Annuler l’édition</button>
|
||
</form>
|
||
</section>
|
||
</aside>
|
||
|
||
<main class="list-grid">
|
||
<section class="glass-card">
|
||
<h2>Webhooks Discord enregistrés</h2>
|
||
<?php if (empty($webhooks)): ?>
|
||
<div class="empty-state">Aucun webhook configuré pour le moment.</div>
|
||
<?php else: ?>
|
||
<div class="table-wrap">
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Nomination</th>
|
||
<th>URL</th>
|
||
<th style="text-align:right;">Actions</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<?php foreach ($webhooks as $webhook): ?>
|
||
<tr>
|
||
<td>
|
||
<strong><?php echo htmlspecialchars($webhook['cl_scwebhook_name'], ENT_QUOTES, 'UTF-8'); ?></strong>
|
||
</td>
|
||
<td>
|
||
<span class="muted"><?php echo htmlspecialchars(scdiscord_mask_webhook_url((string) $webhook['cl_scwebhook_url']), ENT_QUOTES, 'UTF-8'); ?></span>
|
||
</td>
|
||
<td>
|
||
<div class="actions-inline">
|
||
<button
|
||
type="button"
|
||
class="btn-modern btn-mini"
|
||
onclick='editWebhook(<?php echo json_encode([
|
||
'id' => (int) $webhook['cl_scwebhook_id'],
|
||
'name' => (string) $webhook['cl_scwebhook_name'],
|
||
'url' => (string) $webhook['cl_scwebhook_url'],
|
||
], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES); ?>)'
|
||
>Éditer</button>
|
||
<form method="post" onsubmit="return confirm('Supprimer ce webhook Discord ?');">
|
||
<input type="hidden" name="csrf_token" value="<?php echo htmlspecialchars($csrf_token, ENT_QUOTES, 'UTF-8'); ?>">
|
||
<input type="hidden" name="action" value="delete_webhook">
|
||
<input type="hidden" name="webhook_id" value="<?php echo (int) $webhook['cl_scwebhook_id']; ?>">
|
||
<button type="submit" class="btn-modern btn-mini danger">Supprimer</button>
|
||
</form>
|
||
</div>
|
||
</td>
|
||
</tr>
|
||
<?php endforeach; ?>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<?php endif; ?>
|
||
</section>
|
||
|
||
<section class="glass-card">
|
||
<h2>Bannières disponibles</h2>
|
||
<?php if (empty($banners)): ?>
|
||
<div class="empty-state">Aucune bannière enregistrée pour le moment.</div>
|
||
<?php else: ?>
|
||
<div class="table-wrap">
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Nom</th>
|
||
<th>Prévisualisation</th>
|
||
<th>Couleur</th>
|
||
<th style="text-align:right;">Actions</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<?php foreach ($banners as $banner): ?>
|
||
<tr>
|
||
<td>
|
||
<strong><?php echo htmlspecialchars($banner['cl_scbanner_name'], ENT_QUOTES, 'UTF-8'); ?></strong>
|
||
</td>
|
||
<td>
|
||
<img class="banner-preview" src="<?php echo htmlspecialchars($banner['cl_scbanner_url'], ENT_QUOTES, 'UTF-8'); ?>" alt="Prévisualisation bannière">
|
||
</td>
|
||
<td>
|
||
<span class="color-chip" style="--chip-color: <?php echo htmlspecialchars(scdiscord_normalize_hex_color((string) ($banner['cl_scbanner_border_color'] ?? '#ffae00')), ENT_QUOTES, 'UTF-8'); ?>;">
|
||
<?php echo htmlspecialchars(scdiscord_normalize_hex_color((string) ($banner['cl_scbanner_border_color'] ?? '#ffae00')), ENT_QUOTES, 'UTF-8'); ?>
|
||
</span>
|
||
</td>
|
||
<td>
|
||
<div class="actions-inline">
|
||
<button
|
||
type="button"
|
||
class="btn-modern btn-mini"
|
||
onclick='editBanner(<?php echo json_encode([
|
||
'id' => (int) $banner['cl_scbanner_id'],
|
||
'name' => (string) $banner['cl_scbanner_name'],
|
||
'url' => (string) $banner['cl_scbanner_url'],
|
||
'border_color' => (string) ($banner['cl_scbanner_border_color'] ?? '#ffae00'),
|
||
], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES); ?>)'
|
||
>Éditer</button>
|
||
<form method="post" onsubmit="return confirm('Supprimer cette bannière ?');">
|
||
<input type="hidden" name="csrf_token" value="<?php echo htmlspecialchars($csrf_token, ENT_QUOTES, 'UTF-8'); ?>">
|
||
<input type="hidden" name="action" value="delete_banner">
|
||
<input type="hidden" name="banner_id" value="<?php echo (int) $banner['cl_scbanner_id']; ?>">
|
||
<button type="submit" class="btn-modern btn-mini danger">Supprimer</button>
|
||
</form>
|
||
</div>
|
||
</td>
|
||
</tr>
|
||
<?php endforeach; ?>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<?php endif; ?>
|
||
</section>
|
||
</main>
|
||
</div>
|
||
</div>
|
||
|
||
<script>
|
||
function editWebhook(webhook) {
|
||
document.getElementById('webhookFormTitle').textContent = 'Modifier le webhook Discord';
|
||
document.getElementById('webhookAction').value = 'update_webhook';
|
||
document.getElementById('webhookId').value = webhook.id || '';
|
||
document.getElementById('cl_scwebhook_name').value = webhook.name || '';
|
||
document.getElementById('cl_scwebhook_url').value = webhook.url || '';
|
||
document.getElementById('webhookSubmitBtn').textContent = 'Mettre à jour le webhook';
|
||
document.getElementById('webhookCancelBtn').style.display = 'inline-flex';
|
||
}
|
||
|
||
function resetWebhookForm() {
|
||
document.getElementById('webhookFormTitle').textContent = 'Nouveau webhook Discord';
|
||
document.getElementById('webhookAction').value = 'add_webhook';
|
||
document.getElementById('webhookId').value = '';
|
||
document.getElementById('cl_scwebhook_name').value = '';
|
||
document.getElementById('cl_scwebhook_url').value = '';
|
||
document.getElementById('webhookSubmitBtn').textContent = 'Ajouter le webhook';
|
||
document.getElementById('webhookCancelBtn').style.display = 'none';
|
||
}
|
||
|
||
function editBanner(banner) {
|
||
document.getElementById('bannerFormTitle').textContent = 'Modifier la bannière';
|
||
document.getElementById('bannerAction').value = 'update_banner';
|
||
document.getElementById('bannerId').value = banner.id || '';
|
||
document.getElementById('cl_scbanner_name').value = banner.name || '';
|
||
document.getElementById('cl_scbanner_url').value = banner.url || '';
|
||
document.getElementById('cl_scbanner_border_color').value = banner.border_color || '#ffae00';
|
||
document.getElementById('bannerSubmitBtn').textContent = 'Mettre à jour la bannière';
|
||
document.getElementById('bannerCancelBtn').style.display = 'inline-flex';
|
||
}
|
||
|
||
function resetBannerForm() {
|
||
document.getElementById('bannerFormTitle').textContent = 'Nouvelle bannière';
|
||
document.getElementById('bannerAction').value = 'add_banner';
|
||
document.getElementById('bannerId').value = '';
|
||
document.getElementById('cl_scbanner_name').value = '';
|
||
document.getElementById('cl_scbanner_url').value = '';
|
||
document.getElementById('cl_scbanner_border_color').value = '#ffae00';
|
||
document.getElementById('bannerSubmitBtn').textContent = 'Ajouter la bannière';
|
||
document.getElementById('bannerCancelBtn').style.display = 'none';
|
||
}
|
||
</script>
|
||
</body>
|
||
</html>
|