owner and admin section
This commit is contained in:
@@ -0,0 +1,393 @@
|
||||
<?php
|
||||
ini_set('display_errors', 1);
|
||||
ini_set('display_startup_errors', 1);
|
||||
error_reporting(E_ALL);
|
||||
|
||||
if (session_status() === PHP_SESSION_NONE) session_start();
|
||||
include('include/headscript.php');
|
||||
|
||||
$dbHandler = DBHandlerSelect::getInstance();
|
||||
$pdo = $dbHandler->getConnection();
|
||||
|
||||
if (!isset($iduserlogin)) {
|
||||
header("Location: login.php");
|
||||
exit;
|
||||
}
|
||||
// Solo admin
|
||||
if ((int)$kindofrole !== ROLE_ADMIN) {
|
||||
header("Location: index.php");
|
||||
exit;
|
||||
}
|
||||
|
||||
function e(?string $v): string
|
||||
{
|
||||
return htmlspecialchars((string)$v, ENT_QUOTES, 'UTF-8');
|
||||
}
|
||||
function getFlash(): ?array
|
||||
{
|
||||
if (!isset($_SESSION['flash'])) return null;
|
||||
$f = $_SESSION['flash'];
|
||||
unset($_SESSION['flash']);
|
||||
return $f;
|
||||
}
|
||||
|
||||
// --- Filtri ---
|
||||
$q_search = trim($_GET['q'] ?? '');
|
||||
$q_role = isset($_GET['role']) && $_GET['role'] !== '' ? (int)$_GET['role'] : 0;
|
||||
$q_status = trim($_GET['status'] ?? '');
|
||||
|
||||
$where = ["1=1"];
|
||||
$params = [];
|
||||
if ($q_search !== '') {
|
||||
$where[] = "(u.first_name LIKE ? OR u.last_name LIKE ? OR u.email LIKE ?)";
|
||||
$like = '%' . $q_search . '%';
|
||||
array_push($params, $like, $like, $like);
|
||||
}
|
||||
if ($q_role > 0) {
|
||||
$where[] = "u.role_id = ?";
|
||||
$params[] = $q_role;
|
||||
}
|
||||
if ($q_status !== '') {
|
||||
$where[] = "u.status = ?";
|
||||
$params[] = $q_status;
|
||||
}
|
||||
$whereSql = implode(' AND ', $where);
|
||||
|
||||
// --- Utenti ---
|
||||
$sql = "
|
||||
SELECT u.id, u.first_name, u.last_name, u.email, u.phone, u.avatar,
|
||||
u.role_id, u.status, u.last_login, u.created_at,
|
||||
r.display_name AS role_label,
|
||||
(SELECT COUNT(*) FROM shops sh WHERE sh.owner_id = u.id) AS shops_count
|
||||
FROM auth_users u
|
||||
LEFT JOIN auth_roles r ON u.role_id = r.id
|
||||
WHERE $whereSql
|
||||
ORDER BY u.created_at DESC
|
||||
";
|
||||
$stmt = $pdo->prepare($sql);
|
||||
$stmt->execute($params);
|
||||
$users = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||
|
||||
// Ruoli per i filtri/select
|
||||
$roles = $pdo->query("SELECT id, display_name FROM auth_roles ORDER BY id ASC")->fetchAll(PDO::FETCH_ASSOC);
|
||||
|
||||
$flash = getFlash();
|
||||
$ret = http_build_query(array_filter(['q' => $q_search, 'role' => $q_role ?: '', 'status' => $q_status]));
|
||||
|
||||
function roleBadge(int $role_id): string
|
||||
{
|
||||
switch ($role_id) {
|
||||
case 1:
|
||||
return 'bg-danger'; // Admin
|
||||
case 2:
|
||||
return 'bg-primary'; // Owner
|
||||
case 3:
|
||||
return 'bg-secondary'; // User
|
||||
default:
|
||||
return 'bg-dark';
|
||||
}
|
||||
}
|
||||
?>
|
||||
<!doctype html>
|
||||
<html lang="it">
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link rel="icon" href="assets/images/favicon-32x32.png" type="image/png" />
|
||||
<?php include('cssinclude.php'); ?>
|
||||
<?php include('siteinfo.php'); ?>
|
||||
<title>Gestione Utenti</title>
|
||||
<style>
|
||||
:root {
|
||||
--soft-border: #e9edf3;
|
||||
--muted: #6b7280;
|
||||
--bg: #f6f7fb;
|
||||
}
|
||||
|
||||
body {
|
||||
background: var(--bg);
|
||||
}
|
||||
|
||||
.card-shell {
|
||||
border-radius: 14px;
|
||||
border: 1px solid var(--soft-border);
|
||||
background: #fff;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.card-shell .card-header {
|
||||
background: linear-gradient(180deg, #fff, #fbfcff);
|
||||
border-bottom: 1px solid var(--soft-border);
|
||||
}
|
||||
|
||||
.page-title {
|
||||
font-weight: 900;
|
||||
letter-spacing: -0.02em;
|
||||
}
|
||||
|
||||
.avatar-sm {
|
||||
width: 38px;
|
||||
height: 38px;
|
||||
border-radius: 50%;
|
||||
object-fit: cover;
|
||||
background: #eef2f7;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-weight: 800;
|
||||
color: #64748b;
|
||||
}
|
||||
|
||||
.table> :not(caption)>*>* {
|
||||
padding: .85rem .75rem;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.user-email {
|
||||
color: var(--muted);
|
||||
font-size: .85rem;
|
||||
}
|
||||
|
||||
.dot-status {
|
||||
width: 9px;
|
||||
height: 9px;
|
||||
border-radius: 50%;
|
||||
display: inline-block;
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
.st-active {
|
||||
background: #16a34a;
|
||||
}
|
||||
|
||||
.st-banned {
|
||||
background: #dc2626;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div class="wrapper">
|
||||
<?php include('include/navbar.php'); ?>
|
||||
<?php include('include/topbar.php'); ?>
|
||||
|
||||
<div class="page-wrapper">
|
||||
<div class="page-content">
|
||||
|
||||
<div class="card-shell">
|
||||
<div class="card-header p-3 p-md-4">
|
||||
<div class="d-flex flex-wrap justify-content-between align-items-center gap-2">
|
||||
<div class="page-title h5 mb-0"><i class="bx bx-group me-1"></i> Gestione Utenti</div>
|
||||
<span class="text-muted small"><?= count($users) ?> utenti</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card-body">
|
||||
<?php if ($flash): ?>
|
||||
<div class="alert alert-<?= e($flash['type']) ?> alert-dismissible fade show" role="alert">
|
||||
<?= e($flash['text']) ?>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="alert"></button>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<!-- Filtri -->
|
||||
<form method="GET" class="row g-2 mb-3">
|
||||
<div class="col-md-5">
|
||||
<input type="text" name="q" class="form-control" placeholder="Cerca nome, cognome o email…" value="<?= e($q_search) ?>">
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<select name="role" class="form-select">
|
||||
<option value="">Tutti i ruoli</option>
|
||||
<?php foreach ($roles as $r): ?>
|
||||
<option value="<?= (int)$r['id'] ?>" <?= $q_role === (int)$r['id'] ? 'selected' : '' ?>>
|
||||
<?= e($r['display_name'] ?: ('Ruolo ' . $r['id'])) ?>
|
||||
</option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-2">
|
||||
<select name="status" class="form-select">
|
||||
<option value="">Tutti gli stati</option>
|
||||
<option value="Active" <?= $q_status === 'Active' ? 'selected' : '' ?>>Attivi</option>
|
||||
<option value="banned" <?= $q_status === 'banned' ? 'selected' : '' ?>>Bloccati</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-2 d-grid">
|
||||
<button class="btn btn-primary"><i class="bx bx-search"></i> Filtra</button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<!-- Tabella -->
|
||||
<div class="table-responsive">
|
||||
<table class="table table-hover align-middle">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Utente</th>
|
||||
<th>Ruolo</th>
|
||||
<th>Stato</th>
|
||||
<th>Saloni</th>
|
||||
<th>Ultimo accesso</th>
|
||||
<th class="text-end">Azioni</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php if (empty($users)): ?>
|
||||
<tr>
|
||||
<td colspan="6" class="text-center text-muted py-4">Nessun utente trovato.</td>
|
||||
</tr>
|
||||
<?php else: foreach ($users as $u): ?>
|
||||
<?php
|
||||
$fullName = trim(($u['first_name'] ?? '') . ' ' . ($u['last_name'] ?? '')) ?: '—';
|
||||
$initial = strtoupper(mb_substr($u['first_name'] ?: $u['email'], 0, 1));
|
||||
$isActive = ($u['status'] === 'Active');
|
||||
$isSelf = ((int)$u['id'] === (int)$iduserlogin);
|
||||
?>
|
||||
<tr>
|
||||
<td>
|
||||
<div class="d-flex align-items-center gap-2">
|
||||
<?php if (!empty($u['avatar'])): ?>
|
||||
<img src="<?= e($u['avatar']) ?>" class="avatar-sm" alt="">
|
||||
<?php else: ?>
|
||||
<span class="avatar-sm"><?= e($initial) ?></span>
|
||||
<?php endif; ?>
|
||||
<div>
|
||||
<div class="fw-bold"><?= e($fullName) ?> <?php if ($isSelf): ?><span class="badge bg-light text-dark ms-1">tu</span><?php endif; ?></div>
|
||||
<div class="user-email"><?= e($u['email']) ?></div>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
<td><span class="badge <?= roleBadge((int)$u['role_id']) ?>"><?= e($u['role_label'] ?: ('Ruolo ' . $u['role_id'])) ?></span></td>
|
||||
<td>
|
||||
<span class="dot-status <?= $isActive ? 'st-active' : 'st-banned' ?>"></span>
|
||||
<?= $isActive ? 'Attivo' : 'Bloccato' ?>
|
||||
</td>
|
||||
<td><?= (int)$u['shops_count'] > 0 ? (int)$u['shops_count'] : '—' ?></td>
|
||||
<td class="text-muted small"><?= $u['last_login'] ? date('d/m/Y H:i', strtotime($u['last_login'])) : 'Mai' ?></td>
|
||||
<td class="text-end">
|
||||
<div class="dropdown">
|
||||
<button class="btn btn-sm btn-outline-secondary dropdown-toggle" data-bs-toggle="dropdown" <?= $isSelf ? '' : '' ?>>
|
||||
Gestisci
|
||||
</button>
|
||||
<ul class="dropdown-menu dropdown-menu-end">
|
||||
<li><button class="dropdown-item" data-bs-toggle="modal" data-bs-target="#roleModal"
|
||||
data-id="<?= (int)$u['id'] ?>" data-name="<?= e($fullName) ?>" data-role="<?= (int)$u['role_id'] ?>"
|
||||
<?= $isSelf ? 'disabled' : '' ?>><i class="bx bx-user-pin me-1"></i> Cambia ruolo</button></li>
|
||||
<li><button class="dropdown-item" data-bs-toggle="modal" data-bs-target="#pwModal"
|
||||
data-id="<?= (int)$u['id'] ?>" data-name="<?= e($fullName) ?>"><i class="bx bx-key me-1"></i> Reset password</button></li>
|
||||
<?php if (!$isSelf): ?>
|
||||
<li>
|
||||
<form method="POST" action="admin_user_action.php" class="d-inline">
|
||||
<input type="hidden" name="action" value="set_status">
|
||||
<input type="hidden" name="user_id" value="<?= (int)$u['id'] ?>">
|
||||
<input type="hidden" name="status" value="<?= $isActive ? 'banned' : 'Active' ?>">
|
||||
<input type="hidden" name="ret" value="<?= e($ret) ?>">
|
||||
<button class="dropdown-item">
|
||||
<?php if ($isActive): ?><i class="bx bx-block me-1"></i> Blocca<?php else: ?><i class="bx bx-check-circle me-1"></i> Attiva<?php endif; ?>
|
||||
</button>
|
||||
</form>
|
||||
</li>
|
||||
<li>
|
||||
<hr class="dropdown-divider">
|
||||
</li>
|
||||
<li>
|
||||
<form method="POST" action="admin_user_action.php" onsubmit="return confirm('Eliminare definitivamente questo utente?');">
|
||||
<input type="hidden" name="action" value="delete">
|
||||
<input type="hidden" name="user_id" value="<?= (int)$u['id'] ?>">
|
||||
<input type="hidden" name="ret" value="<?= e($ret) ?>">
|
||||
<button class="dropdown-item text-danger"><i class="bx bx-trash me-1"></i> Elimina</button>
|
||||
</form>
|
||||
</li>
|
||||
<?php endif; ?>
|
||||
</ul>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<?php endforeach;
|
||||
endif; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php include('include/footer.php'); ?>
|
||||
</div>
|
||||
|
||||
<!-- Modale cambio ruolo -->
|
||||
<div class="modal fade" id="roleModal" tabindex="-1" aria-hidden="true">
|
||||
<div class="modal-dialog modal-dialog-centered">
|
||||
<form method="POST" action="admin_user_action.php" class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title">Cambia ruolo</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<p class="text-muted mb-2">Utente: <strong id="roleUserName"></strong></p>
|
||||
<input type="hidden" name="action" value="set_role">
|
||||
<input type="hidden" name="user_id" id="roleUserId">
|
||||
<input type="hidden" name="ret" value="<?= e($ret) ?>">
|
||||
<select name="role_id" id="roleSelect" class="form-select">
|
||||
<option value="1">Admin</option>
|
||||
<option value="2">Owner (titolare)</option>
|
||||
<option value="3">User (cliente)</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Annulla</button>
|
||||
<button class="btn btn-primary">Salva ruolo</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Modale reset password -->
|
||||
<div class="modal fade" id="pwModal" tabindex="-1" aria-hidden="true">
|
||||
<div class="modal-dialog modal-dialog-centered">
|
||||
<form method="POST" action="admin_user_action.php" class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title">Reset password</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<p class="text-muted mb-2">Utente: <strong id="pwUserName"></strong></p>
|
||||
<input type="hidden" name="action" value="reset_password">
|
||||
<input type="hidden" name="user_id" id="pwUserId">
|
||||
<input type="hidden" name="ret" value="<?= e($ret) ?>">
|
||||
<label class="form-label">Nuova password (min. 8 caratteri)</label>
|
||||
<input type="text" name="new_password" class="form-control" minlength="8" required
|
||||
placeholder="Es. HairBook2026!">
|
||||
<small class="text-muted">La password è visibile così puoi copiarla e comunicarla all'utente.</small>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Annulla</button>
|
||||
<button class="btn btn-primary">Reimposta</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php include('jsinclude.php'); ?>
|
||||
<script>
|
||||
// Popola la modale ruolo
|
||||
var roleModal = document.getElementById('roleModal');
|
||||
if (roleModal) roleModal.addEventListener('show.bs.modal', function(ev) {
|
||||
var b = ev.relatedTarget;
|
||||
document.getElementById('roleUserId').value = b.getAttribute('data-id');
|
||||
document.getElementById('roleUserName').textContent = b.getAttribute('data-name');
|
||||
document.getElementById('roleSelect').value = b.getAttribute('data-role');
|
||||
});
|
||||
// Popola la modale password
|
||||
var pwModal = document.getElementById('pwModal');
|
||||
if (pwModal) pwModal.addEventListener('show.bs.modal', function(ev) {
|
||||
var b = ev.relatedTarget;
|
||||
document.getElementById('pwUserId').value = b.getAttribute('data-id');
|
||||
document.getElementById('pwUserName').textContent = b.getAttribute('data-name');
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
Reference in New Issue
Block a user