361 lines
16 KiB
PHP
361 lines
16 KiB
PHP
<?php
|
||
// clients_situation.php
|
||
|
||
ini_set('display_errors', 1);
|
||
ini_set('display_startup_errors', 1);
|
||
error_reporting(E_ALL);
|
||
|
||
include('include/headscript.php');
|
||
require_once 'class/mailer.php'; // assumo sia incluso qui o in headscript
|
||
|
||
$dbHandler = DBHandlerSelect::getInstance();
|
||
$pdo = $dbHandler->getConnection();
|
||
|
||
if (!isset($iduserlogin)) {
|
||
die("Errore: ID utente non definito.");
|
||
}
|
||
|
||
// Scuola corrente
|
||
$stmt = $pdo->prepare("
|
||
SELECT id, name, email AS school_email
|
||
FROM schools
|
||
WHERE owner_id = ?
|
||
");
|
||
$stmt->execute([$iduserlogin]);
|
||
$school = $stmt->fetch(PDO::FETCH_ASSOC);
|
||
|
||
if (!$school) {
|
||
die("Nessuna scuola trovata per questo proprietario.");
|
||
}
|
||
|
||
$school_id = $school['id'];
|
||
$school_name = $school['name'];
|
||
$school_email = $school['school_email'];
|
||
|
||
// =============================================
|
||
// INVIO EMAIL da modale
|
||
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['action']) && $_POST['action'] === 'send_email_to_user') {
|
||
|
||
$user_id = (int)($_POST['user_id'] ?? 0);
|
||
$subject = trim($_POST['subject'] ?? '');
|
||
$message = trim($_POST['message'] ?? '');
|
||
|
||
if ($user_id <= 0 || empty($subject) || empty($message)) {
|
||
$error = "Dati mancanti per l'invio email.";
|
||
} else {
|
||
// Recupera email utente
|
||
$stmt = $pdo->prepare("SELECT email, first_name, last_name FROM auth_users WHERE id = ?");
|
||
$stmt->execute([$user_id]);
|
||
$user = $stmt->fetch(PDO::FETCH_ASSOC);
|
||
|
||
if (!$user) {
|
||
$error = "Utente non trovato.";
|
||
} else {
|
||
$to = $user['email'];
|
||
$body = "
|
||
<h2>Comunicazione da {$school_name}</h2>
|
||
<p>Gentile {$user['first_name']} {$user['last_name']},</p>
|
||
<div style='margin: 20px 0; padding: 15px; border-left: 4px solid #0d6efd; background: #f8f9fa;'>
|
||
" . nl2br(htmlspecialchars($message)) . "
|
||
</div>
|
||
<p style='color:#555; font-size:0.95em;'>
|
||
Questa è una comunicazione ufficiale da parte della scuola.<br>
|
||
Per qualsiasi dubbio rispondi direttamente a questa email o contatta: {$school_email}
|
||
</p>
|
||
<hr style='border-color:#eee;'>
|
||
<small style='color:#777;'>YogiBoook – piattaforma per scuole yoga</small>
|
||
";
|
||
|
||
$result = sendEmail($to, $subject, $body);
|
||
|
||
if ($result['success']) {
|
||
$success = "Email inviata con successo a {$user['first_name']} {$user['last_name']}";
|
||
} else {
|
||
$error = "Errore nell'invio: " . $result['message'];
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
// =============================================
|
||
// Lista clienti + statistiche aggregate
|
||
$clients = $pdo->prepare("
|
||
SELECT
|
||
au.id,
|
||
au.first_name,
|
||
au.last_name,
|
||
au.email,
|
||
COUNT(DISTINCT o.id) AS num_orders,
|
||
COALESCE(SUM(o.total_entries), 0) AS total_entries,
|
||
|
||
-- Praticate = prenotate nel passato (booked + data < oggi)
|
||
(SELECT COUNT(*)
|
||
FROM session_bookings sb
|
||
JOIN class_sessions cs ON sb.session_id = cs.id
|
||
WHERE sb.user_id = au.id
|
||
AND cs.school_id = ?
|
||
AND sb.status = 'booked'
|
||
AND cs.session_date < CURDATE()
|
||
) AS lezioni_praticate,
|
||
|
||
-- Perse (missed + data passata)
|
||
(SELECT COUNT(*)
|
||
FROM session_bookings sb
|
||
JOIN class_sessions cs ON sb.session_id = cs.id
|
||
WHERE sb.user_id = au.id
|
||
AND cs.school_id = ?
|
||
AND sb.status = 'missed'
|
||
AND cs.session_date < CURDATE()
|
||
) AS lezioni_perse,
|
||
|
||
-- Prenotate future (booked + data >= oggi)
|
||
(SELECT COUNT(*)
|
||
FROM session_bookings sb
|
||
JOIN class_sessions cs ON sb.session_id = cs.id
|
||
WHERE sb.user_id = au.id
|
||
AND cs.school_id = ?
|
||
AND sb.status = 'booked'
|
||
AND cs.session_date >= CURDATE()
|
||
) AS prenotazioni_future
|
||
|
||
FROM auth_users au
|
||
INNER JOIN user_schools us ON au.id = us.user_id
|
||
LEFT JOIN orders o ON au.id = o.user_id AND o.school_id = ?
|
||
WHERE us.school_id = ?
|
||
AND us.status = 'active'
|
||
GROUP BY au.id
|
||
ORDER BY au.last_name, au.first_name
|
||
");
|
||
$clients->execute([$school_id, $school_id, $school_id, $school_id, $school_id]);
|
||
$client_list = $clients->fetchAll(PDO::FETCH_ASSOC);
|
||
?>
|
||
|
||
<!doctype html>
|
||
<html lang="it">
|
||
|
||
<head>
|
||
<meta charset="utf-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||
<title>Situazione Clienti - <?= htmlspecialchars($school_name) ?></title>
|
||
<?php include('cssinclude.php'); ?>
|
||
</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="page-breadcrumb d-none d-sm-flex align-items-center mb-3">
|
||
<div class="breadcrumb-title pe-3">Clienti</div>
|
||
<div class="ps-3">
|
||
<nav aria-label="breadcrumb">
|
||
<ol class="breadcrumb mb-0 p-0">
|
||
<li class="breadcrumb-item"><a href="school_dashboard.php"><i class="bx bx-home-alt"></i></a></li>
|
||
<li class="breadcrumb-item active" aria-current="page">Situazione Clienti</li>
|
||
</ol>
|
||
</nav>
|
||
</div>
|
||
</div>
|
||
|
||
<h4 class="mb-4">Situazione Clienti – <?= htmlspecialchars($school_name) ?></h4>
|
||
|
||
<?php if (isset($success)): ?>
|
||
<div class="alert alert-success alert-dismissible fade show">
|
||
<?= htmlspecialchars($success) ?>
|
||
<button type="button" class="btn-close" data-bs-dismiss="alert"></button>
|
||
</div>
|
||
<?php endif; ?>
|
||
|
||
<?php if (isset($error)): ?>
|
||
<div class="alert alert-danger alert-dismissible fade show">
|
||
<?= htmlspecialchars($error) ?>
|
||
<button type="button" class="btn-close" data-bs-dismiss="alert"></button>
|
||
</div>
|
||
<?php endif; ?>
|
||
|
||
<div class="card radius-10">
|
||
<div class="card-body">
|
||
<div class="table-responsive">
|
||
<table class="table table-hover table-striped align-middle" id="clientsTable">
|
||
<thead class="table-light">
|
||
<tr>
|
||
<th>Cliente</th>
|
||
<th>Ordini</th>
|
||
<th>Entrate totali</th>
|
||
<th>Praticate</th>
|
||
<th>Perse</th>
|
||
<th>Prenotate (future)</th>
|
||
<th>Rimanenti</th>
|
||
<th>Azioni</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<?php foreach ($client_list as $c):
|
||
$rimanenti = $c['total_entries'] - $c['lezioni_praticate'] - $c['lezioni_perse'];
|
||
?>
|
||
<tr>
|
||
<td>
|
||
<strong>
|
||
<?= htmlspecialchars($c['first_name'] . ' ' . $c['last_name']) ?>
|
||
</strong>
|
||
<br>
|
||
<small class="text-muted"><?= htmlspecialchars($c['email']) ?></small>
|
||
</td>
|
||
<td class="text-center"><?= $c['num_orders'] ?></td>
|
||
<td class="text-center"><?= $c['total_entries'] ?: '—' ?></td>
|
||
<td class="text-center text-success"><?= $c['lezioni_praticate'] ?></td>
|
||
<td class="text-center text-danger"><?= $c['lezioni_perse'] ?></td>
|
||
<td class="text-center text-primary"><?= $c['prenotazioni_future'] ?></td>
|
||
<td class="text-center fw-bold <?= $rimanenti <= 0 ? 'text-danger' : '' ?>">
|
||
<?= $rimanenti > 0 ? $rimanenti : '0' ?>
|
||
</td>
|
||
<td>
|
||
<button class="btn btn-sm btn-outline-primary me-1"
|
||
data-bs-toggle="modal"
|
||
data-bs-target="#detailModal"
|
||
data-userid="<?= $c['id'] ?>"
|
||
data-name="<?= htmlspecialchars($c['first_name'] . ' ' . $c['last_name']) ?>">
|
||
<i class="bx bx-detail"></i> Dettaglio
|
||
</button>
|
||
|
||
<button class="btn btn-sm btn-outline-info"
|
||
data-bs-toggle="modal"
|
||
data-bs-target="#emailModal"
|
||
data-userid="<?= $c['id'] ?>"
|
||
data-name="<?= htmlspecialchars($c['first_name'] . ' ' . $c['last_name']) ?>"
|
||
data-email="<?= htmlspecialchars($c['email']) ?>">
|
||
<i class="bx bx-envelope"></i>
|
||
</button>
|
||
</td>
|
||
</tr>
|
||
<?php endforeach; ?>
|
||
|
||
<?php if (empty($client_list)): ?>
|
||
<tr>
|
||
<td colspan="8" class="text-center py-5 text-muted">
|
||
Nessun cliente associato trovato.
|
||
</td>
|
||
</tr>
|
||
<?php endif; ?>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
</div>
|
||
</div>
|
||
|
||
<!-- MODALE DETTAGLIO PRENOTAZIONI -->
|
||
<div class="modal fade" id="detailModal" tabindex="-1" aria-labelledby="detailModalLabel" aria-hidden="true">
|
||
<div class="modal-dialog modal-xl">
|
||
<div class="modal-content">
|
||
<div class="modal-header">
|
||
<h5 class="modal-title" id="detailModalLabel">Storico prenotazioni di <span id="modalClientName"></span></h5>
|
||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||
</div>
|
||
<div class="modal-body" id="detailBody">
|
||
<div class="text-center py-4">
|
||
<div class="spinner-border text-primary" role="status"></div>
|
||
<p class="mt-2">Caricamento...</p>
|
||
</div>
|
||
</div>
|
||
<div class="modal-footer">
|
||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Chiudi</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- MODALE INVIO EMAIL -->
|
||
<div class="modal fade" id="emailModal" tabindex="-1" aria-labelledby="emailModalLabel" aria-hidden="true">
|
||
<div class="modal-dialog">
|
||
<div class="modal-content">
|
||
<div class="modal-header">
|
||
<h5 class="modal-title" id="emailModalLabel">Invia comunicazione a <span id="emailClientName"></span></h5>
|
||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||
</div>
|
||
<form method="post">
|
||
<div class="modal-body">
|
||
<input type="hidden" name="action" value="send_email_to_user">
|
||
<input type="hidden" name="user_id" id="emailUserId">
|
||
|
||
<div class="mb-3">
|
||
<label class="form-label">Oggetto</label>
|
||
<input type="text" name="subject" class="form-control" value="Comunicazione da YogiBoook" required>
|
||
</div>
|
||
|
||
<div class="mb-3">
|
||
<label class="form-label">Messaggio</label>
|
||
<textarea name="message" class="form-control" rows="8" required placeholder="Scrivi qui il messaggio per il cliente..."></textarea>
|
||
</div>
|
||
|
||
<small class="text-muted d-block">
|
||
Il messaggio verrà inviato da sistema e includerà automaticamente il nome della scuola e il tuo indirizzo email di contatto.
|
||
</small>
|
||
</div>
|
||
<div class="modal-footer">
|
||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Annulla</button>
|
||
<button type="submit" class="btn btn-primary">Invia Email</button>
|
||
</div>
|
||
</form>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<?php include('include/footer.php'); ?>
|
||
</div>
|
||
|
||
<?php include('jsinclude.php'); ?>
|
||
|
||
<script>
|
||
$(document).ready(function() {
|
||
$('#clientsTable').DataTable({
|
||
language: {
|
||
url: '//cdn.datatables.net/plug-ins/1.13.7/i18n/it-IT.json'
|
||
},
|
||
pageLength: 15,
|
||
order: [
|
||
[0, 'asc']
|
||
]
|
||
});
|
||
|
||
// Dettaglio cliente
|
||
$('[data-bs-target="#detailModal"]').on('click', function() {
|
||
const userid = $(this).data('userid');
|
||
const name = $(this).data('name');
|
||
|
||
$('#modalClientName').text(name);
|
||
$('#detailBody').html('<div class="text-center py-4"><div class="spinner-border text-primary" role="status"></div><p class="mt-2">Caricamento storico...</p></div>');
|
||
|
||
$.ajax({
|
||
url: 'ajax_client_bookings.php',
|
||
method: 'POST',
|
||
data: {
|
||
user_id: userid,
|
||
school_id: <?= $school_id ?>
|
||
},
|
||
success: function(response) {
|
||
$('#detailBody').html(response);
|
||
},
|
||
error: function() {
|
||
$('#detailBody').html('<div class="alert alert-danger">Errore durante il caricamento dei dati.</div>');
|
||
}
|
||
});
|
||
});
|
||
|
||
// Precompila modale email
|
||
$('[data-bs-target="#emailModal"]').on('click', function() {
|
||
const userid = $(this).data('userid');
|
||
const name = $(this).data('name');
|
||
$('#emailUserId').val(userid);
|
||
$('#emailClientName').text(name);
|
||
});
|
||
});
|
||
</script>
|
||
</body>
|
||
|
||
</html>
|