teacher
This commit is contained in:
@@ -0,0 +1,361 @@
|
||||
<?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>
|
||||
Reference in New Issue
Block a user