783 lines
34 KiB
PHP
783 lines
34 KiB
PHP
<?php ob_start();
|
|
require_once('include/headscript.php');
|
|
/**
|
|
* YogiBook - Gestione insegnanti (CRUD)
|
|
* Tabella: employee
|
|
* - un solo titolare (is_owner = 'Y'), non eliminabile né disattivabile
|
|
* - notifiche email attivabili/disattivabili
|
|
* - foto opzionale (JPG/PNG/WEBP, max 3 MB) in assets/images/teachers/
|
|
*/
|
|
$pdo = DBHandlerSelect::getInstance()->getConnection();
|
|
|
|
if (!function_exists('e')) {
|
|
function e($value): string
|
|
{
|
|
return htmlspecialchars((string) $value, ENT_QUOTES, 'UTF-8');
|
|
}
|
|
}
|
|
|
|
if (session_status() !== PHP_SESSION_ACTIVE) {
|
|
session_start();
|
|
}
|
|
if (empty($_SESSION['csrf_teachers'])) {
|
|
$_SESSION['csrf_teachers'] = bin2hex(random_bytes(16));
|
|
}
|
|
$csrf = $_SESSION['csrf_teachers'];
|
|
|
|
define('PHOTO_DIR_REL', 'assets/images/teachers/');
|
|
$photoDirAbs = __DIR__ . '/' . PHOTO_DIR_REL;
|
|
|
|
/* ================================================================ helper */
|
|
|
|
function flashRedirect(string $type, string $msg): void
|
|
{
|
|
$_SESSION['teachers_flash'] = [$type, $msg];
|
|
header('Location: insegnanti.php');
|
|
exit;
|
|
}
|
|
|
|
function teacherInitials(string $first, string $last): string
|
|
{
|
|
$ini = mb_strtoupper(mb_substr(trim($first), 0, 1) . mb_substr(trim($last), 0, 1));
|
|
return $ini !== '' ? $ini : '?';
|
|
}
|
|
|
|
function teacherColor(string $seed): string
|
|
{
|
|
$palette = ['#1ebf73', '#2980b9', '#8e44ad', '#e67e22', '#16a085', '#c0392b', '#2c3e50', '#b08d57'];
|
|
return $palette[abs(crc32($seed)) % count($palette)];
|
|
}
|
|
|
|
function deletePhotoFile(string $dir, ?string $name): void
|
|
{
|
|
if ($name && preg_match('/^teacher_[a-f0-9]{16}\.(jpg|png|webp)$/', $name) && is_file($dir . $name)) {
|
|
@unlink($dir . $name);
|
|
}
|
|
}
|
|
|
|
/** Ritorna il nome file salvato, null se nessun file caricato. Lancia RuntimeException se non valido. */
|
|
function handlePhotoUpload(array $file, string $dir): ?string
|
|
{
|
|
if (($file['error'] ?? UPLOAD_ERR_NO_FILE) === UPLOAD_ERR_NO_FILE) {
|
|
return null;
|
|
}
|
|
if ($file['error'] !== UPLOAD_ERR_OK) {
|
|
throw new RuntimeException('Errore nel caricamento della foto.');
|
|
}
|
|
if ($file['size'] > 3 * 1024 * 1024) {
|
|
throw new RuntimeException('La foto supera i 3 MB.');
|
|
}
|
|
$mime = (new finfo(FILEINFO_MIME_TYPE))->file($file['tmp_name']);
|
|
$ext = ['image/jpeg' => 'jpg', 'image/png' => 'png', 'image/webp' => 'webp'][$mime] ?? null;
|
|
if (!$ext || @getimagesize($file['tmp_name']) === false) {
|
|
throw new RuntimeException('Formato foto non valido: usa JPG, PNG o WEBP.');
|
|
}
|
|
if (!is_dir($dir) && !@mkdir($dir, 0755, true)) {
|
|
throw new RuntimeException('La cartella delle foto non è scrivibile.');
|
|
}
|
|
$name = 'teacher_' . bin2hex(random_bytes(8)) . '.' . $ext;
|
|
if (!move_uploaded_file($file['tmp_name'], $dir . $name)) {
|
|
throw new RuntimeException('Impossibile salvare la foto.');
|
|
}
|
|
return $name;
|
|
}
|
|
|
|
function findTeacher(PDO $pdo, int $id): ?array
|
|
{
|
|
$st = $pdo->prepare("SELECT * FROM employee WHERE idemployee = :id");
|
|
$st->execute([':id' => $id]);
|
|
$row = $st->fetch();
|
|
return $row ?: null;
|
|
}
|
|
|
|
/* ================================================================ azioni POST */
|
|
|
|
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
|
if (!hash_equals($csrf, (string) ($_POST['csrf'] ?? ''))) {
|
|
flashRedirect('danger', 'Sessione scaduta, riprova.');
|
|
}
|
|
|
|
$action = $_POST['action'] ?? '';
|
|
$id = (int) ($_POST['id'] ?? 0);
|
|
|
|
try {
|
|
/* ---------- crea / modifica */
|
|
if ($action === 'save') {
|
|
$name = trim((string) ($_POST['nameemployee'] ?? ''));
|
|
$surname = trim((string) ($_POST['surnameemployee'] ?? ''));
|
|
$email = trim((string) ($_POST['email'] ?? ''));
|
|
$phone = trim((string) ($_POST['phone'] ?? ''));
|
|
$notify = isset($_POST['notifications']) ? 'Y' : 'N';
|
|
$active = isset($_POST['active']) ? 'Y' : 'N';
|
|
|
|
if ($name === '' || $surname === '') {
|
|
flashRedirect('danger', 'Nome e cognome sono obbligatori.');
|
|
}
|
|
if (mb_strlen($name) > 100 || mb_strlen($surname) > 100) {
|
|
flashRedirect('danger', 'Nome o cognome troppo lunghi.');
|
|
}
|
|
if ($email !== '' && !filter_var($email, FILTER_VALIDATE_EMAIL)) {
|
|
flashRedirect('danger', 'Indirizzo email non valido.');
|
|
}
|
|
if ($phone !== '' && !preg_match('/^[0-9 +().\/-]{5,40}$/', $phone)) {
|
|
flashRedirect('danger', 'Numero di telefono non valido.');
|
|
}
|
|
if ($email !== '') {
|
|
$dup = $pdo->prepare("SELECT COUNT(*) AS c FROM employee WHERE email = :email AND idemployee <> :id");
|
|
$dup->execute([':email' => $email, ':id' => $id]);
|
|
if ((int) $dup->fetch()['c'] > 0) {
|
|
flashRedirect('danger', 'Questa email è già usata da un altro insegnante.');
|
|
}
|
|
}
|
|
|
|
if ($id > 0) {
|
|
$current = findTeacher($pdo, $id);
|
|
if (!$current) {
|
|
flashRedirect('danger', 'Insegnante non trovato.');
|
|
}
|
|
if ($current['is_owner'] === 'Y' && $active === 'N') {
|
|
flashRedirect('danger', 'Il titolare non può essere disattivato.');
|
|
}
|
|
|
|
$photo = $current['photo'];
|
|
$newPhoto = handlePhotoUpload($_FILES['photo'] ?? [], $photoDirAbs);
|
|
if ($newPhoto !== null) {
|
|
deletePhotoFile($photoDirAbs, $photo);
|
|
$photo = $newPhoto;
|
|
} elseif (isset($_POST['remove_photo'])) {
|
|
deletePhotoFile($photoDirAbs, $photo);
|
|
$photo = null;
|
|
}
|
|
|
|
$st = $pdo->prepare("UPDATE employee SET nameemployee = :n, surnameemployee = :s, email = :e,
|
|
phone = :p, photo = :ph, notifications = :nt, active = :a
|
|
WHERE idemployee = :id");
|
|
$st->execute([
|
|
':n' => $name,
|
|
':s' => $surname,
|
|
':e' => $email ?: null,
|
|
':p' => $phone ?: null,
|
|
':ph' => $photo,
|
|
':nt' => $notify,
|
|
':a' => $active,
|
|
':id' => $id,
|
|
]);
|
|
flashRedirect('success', 'Insegnante aggiornato.');
|
|
}
|
|
|
|
// nuovo
|
|
$photo = handlePhotoUpload($_FILES['photo'] ?? [], $photoDirAbs);
|
|
$hasOwner = (int) $pdo->query("SELECT COUNT(*) AS c FROM employee WHERE is_owner = 'Y'")->fetch()['c'] > 0;
|
|
|
|
$st = $pdo->prepare("INSERT INTO employee
|
|
(nameemployee, surnameemployee, email, phone, photo, is_owner, notifications, active, idlocation)
|
|
VALUES (:n, :s, :e, :p, :ph, :o, :nt, :a, 0)");
|
|
$st->execute([
|
|
':n' => $name,
|
|
':s' => $surname,
|
|
':e' => $email ?: null,
|
|
':p' => $phone ?: null,
|
|
':ph' => $photo,
|
|
':o' => $hasOwner ? 'N' : 'Y',
|
|
':nt' => $notify,
|
|
':a' => $hasOwner ? $active : 'Y',
|
|
]);
|
|
flashRedirect('success', 'Insegnante aggiunto' . ($hasOwner ? '.' : ' e impostato come titolare.'));
|
|
}
|
|
|
|
/* ---------- imposta titolare */
|
|
if ($action === 'set_owner' && $id > 0) {
|
|
if (!findTeacher($pdo, $id)) {
|
|
flashRedirect('danger', 'Insegnante non trovato.');
|
|
}
|
|
$pdo->beginTransaction();
|
|
$pdo->exec("UPDATE employee SET is_owner = 'N' WHERE is_owner = 'Y'");
|
|
$st = $pdo->prepare("UPDATE employee SET is_owner = 'Y', active = 'Y' WHERE idemployee = :id");
|
|
$st->execute([':id' => $id]);
|
|
$pdo->commit();
|
|
flashRedirect('success', 'Titolare aggiornato.');
|
|
}
|
|
|
|
/* ---------- notifiche on/off */
|
|
if ($action === 'toggle_notifications' && $id > 0) {
|
|
$st = $pdo->prepare("UPDATE employee SET notifications = IF(notifications = 'Y', 'N', 'Y') WHERE idemployee = :id");
|
|
$st->execute([':id' => $id]);
|
|
flashRedirect('success', 'Notifiche aggiornate.');
|
|
}
|
|
|
|
/* ---------- elimina */
|
|
if ($action === 'delete' && $id > 0) {
|
|
$t = findTeacher($pdo, $id);
|
|
if (!$t) {
|
|
flashRedirect('danger', 'Insegnante non trovato.');
|
|
}
|
|
if ($t['is_owner'] === 'Y') {
|
|
flashRedirect('danger', 'Il titolare non può essere eliminato. Imposta prima un altro titolare.');
|
|
}
|
|
$cnt = $pdo->prepare("SELECT COUNT(*) AS c FROM service WHERE idteacher = :id");
|
|
$cnt->execute([':id' => $id]);
|
|
$nServices = (int) $cnt->fetch()['c'];
|
|
if ($nServices > 0) {
|
|
flashRedirect('danger', 'Impossibile eliminare: ha ' . $nServices . ' classi assegnate. Riassegnale oppure disattiva l\'insegnante.');
|
|
}
|
|
$pdo->beginTransaction();
|
|
$pdo->prepare("DELETE FROM dayoff WHERE idteacher = :id")->execute([':id' => $id]);
|
|
$pdo->prepare("DELETE FROM employee WHERE idemployee = :id")->execute([':id' => $id]);
|
|
$pdo->commit();
|
|
deletePhotoFile($photoDirAbs, $t['photo']);
|
|
flashRedirect('success', 'Insegnante eliminato.');
|
|
}
|
|
|
|
flashRedirect('danger', 'Azione non valida.');
|
|
} catch (RuntimeException $ex) {
|
|
flashRedirect('danger', $ex->getMessage());
|
|
} catch (Throwable $ex) {
|
|
if ($pdo->inTransaction()) {
|
|
$pdo->rollBack();
|
|
}
|
|
error_log('insegnanti.php: ' . $ex->getMessage());
|
|
flashRedirect('danger', 'Errore durante il salvataggio. Riprova.');
|
|
}
|
|
}
|
|
|
|
/* ================================================================ lettura */
|
|
|
|
$flash = $_SESSION['teachers_flash'] ?? null;
|
|
unset($_SESSION['teachers_flash']);
|
|
|
|
$teachers = $pdo->query("SELECT e.*,
|
|
(SELECT COUNT(*) FROM service s WHERE s.idteacher = e.idemployee) AS nservices
|
|
FROM employee e
|
|
ORDER BY e.is_owner DESC, e.active DESC, e.surnameemployee, e.nameemployee")->fetchAll();
|
|
?>
|
|
<!doctype html>
|
|
<html lang="it">
|
|
|
|
<head>
|
|
<meta charset="utf-8" />
|
|
<title>YogiBook - Insegnanti</title>
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<meta content="YogiBook - Prenotazione facile YogaSoul" name="description" />
|
|
<meta content="Advanced Creative Solutions" name="author" />
|
|
<link rel="shortcut icon" href="assets/images/favicon.ico">
|
|
<link href="assets/css/bootstrap.min.css" id="bootstrap-style" rel="stylesheet" type="text/css" />
|
|
<link href="assets/css/icons.min.css" rel="stylesheet" type="text/css" />
|
|
<link href="assets/css/app.min.css" id="app-style" rel="stylesheet" type="text/css" />
|
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0-beta3/css/all.min.css">
|
|
<script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script>
|
|
|
|
<style>
|
|
.teachers-head {
|
|
display: flex;
|
|
flex-wrap: wrap;
|
|
gap: 12px;
|
|
align-items: center;
|
|
justify-content: space-between;
|
|
margin-bottom: 20px;
|
|
}
|
|
|
|
.teachers-head h5 {
|
|
margin: 0;
|
|
font-weight: 700;
|
|
color: #374151;
|
|
}
|
|
|
|
.teacher-card {
|
|
background: #fff;
|
|
border-radius: 14px;
|
|
box-shadow: 0 3px 16px rgba(0, 0, 0, 0.06);
|
|
padding: 20px;
|
|
margin-bottom: 20px;
|
|
height: calc(100% - 20px);
|
|
display: flex;
|
|
flex-direction: column;
|
|
border-top: 5px solid #eef0f3;
|
|
transition: box-shadow 0.2s;
|
|
}
|
|
|
|
.teacher-card:hover {
|
|
box-shadow: 0 6px 22px rgba(0, 0, 0, 0.1);
|
|
}
|
|
|
|
.teacher-card.owner {
|
|
border-top-color: #E1D0B8;
|
|
}
|
|
|
|
.teacher-card.inactive {
|
|
opacity: 0.6;
|
|
}
|
|
|
|
.teacher-top {
|
|
display: flex;
|
|
gap: 14px;
|
|
align-items: center;
|
|
margin-bottom: 14px;
|
|
}
|
|
|
|
.teacher-avatar {
|
|
flex: 0 0 64px;
|
|
width: 64px;
|
|
height: 64px;
|
|
border-radius: 50%;
|
|
object-fit: cover;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
color: #fff;
|
|
font-size: 22px;
|
|
font-weight: 800;
|
|
border: 3px solid #f3f4f6;
|
|
}
|
|
|
|
.teacher-name {
|
|
font-size: 17px;
|
|
font-weight: 700;
|
|
color: #1f2937;
|
|
line-height: 1.2;
|
|
}
|
|
|
|
.t-badge {
|
|
display: inline-block;
|
|
font-size: 11px;
|
|
font-weight: 700;
|
|
padding: 3px 10px;
|
|
border-radius: 20px;
|
|
margin-top: 5px;
|
|
margin-right: 4px;
|
|
}
|
|
|
|
.t-badge.owner {
|
|
background: #E1D0B8;
|
|
color: #5a4630;
|
|
}
|
|
|
|
.t-badge.inactive {
|
|
background: #eef0f3;
|
|
color: #6b7280;
|
|
}
|
|
|
|
.teacher-info {
|
|
font-size: 14px;
|
|
color: #4b5563;
|
|
margin-bottom: 4px;
|
|
word-break: break-all;
|
|
}
|
|
|
|
.teacher-info i {
|
|
width: 18px;
|
|
color: #9ca3af;
|
|
}
|
|
|
|
.teacher-info a {
|
|
color: #4b5563;
|
|
}
|
|
|
|
.teacher-info .missing {
|
|
color: #c0c4cc;
|
|
font-style: italic;
|
|
}
|
|
|
|
.teacher-foot {
|
|
margin-top: auto;
|
|
padding-top: 14px;
|
|
border-top: 1px solid #f0f2f5;
|
|
display: flex;
|
|
flex-wrap: wrap;
|
|
gap: 8px;
|
|
align-items: center;
|
|
justify-content: space-between;
|
|
}
|
|
|
|
.notify-form .form-check-label {
|
|
font-size: 13px;
|
|
font-weight: 600;
|
|
color: #4b5563;
|
|
cursor: pointer;
|
|
}
|
|
|
|
.notify-form .form-check-input {
|
|
cursor: pointer;
|
|
}
|
|
|
|
.notify-form .form-check-input:checked {
|
|
background-color: #1ebf73;
|
|
border-color: #1ebf73;
|
|
}
|
|
|
|
.notify-warning {
|
|
font-size: 11px;
|
|
color: #e67e22;
|
|
font-weight: 600;
|
|
}
|
|
|
|
.t-actions {
|
|
display: flex;
|
|
gap: 6px;
|
|
}
|
|
|
|
.t-btn {
|
|
border: none;
|
|
border-radius: 8px;
|
|
padding: 6px 11px;
|
|
font-size: 12px;
|
|
font-weight: 600;
|
|
cursor: pointer;
|
|
transition: filter 0.15s;
|
|
}
|
|
|
|
.t-btn:hover {
|
|
filter: brightness(0.93);
|
|
}
|
|
|
|
.t-btn.edit {
|
|
background: #eef2f7;
|
|
color: #374151;
|
|
}
|
|
|
|
.t-btn.owner {
|
|
background: #f5eee4;
|
|
color: #8a6a3f;
|
|
}
|
|
|
|
.t-btn.del {
|
|
background: #fdecea;
|
|
color: #c0392b;
|
|
}
|
|
|
|
.photo-preview {
|
|
width: 84px;
|
|
height: 84px;
|
|
border-radius: 50%;
|
|
object-fit: cover;
|
|
background: #f3f4f6;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
color: #9ca3af;
|
|
font-size: 28px;
|
|
border: 3px solid #eef0f3;
|
|
overflow: hidden;
|
|
}
|
|
|
|
.photo-preview img {
|
|
width: 100%;
|
|
height: 100%;
|
|
object-fit: cover;
|
|
}
|
|
|
|
.empty-teachers {
|
|
text-align: center;
|
|
color: #9ca3af;
|
|
padding: 50px 10px;
|
|
}
|
|
</style>
|
|
</head>
|
|
|
|
<body>
|
|
<div id="layout-wrapper">
|
|
<header id="page-topbar" class="isvertical-topbar">
|
|
<div class="navbar-header">
|
|
<div class="d-flex">
|
|
<?php include('include/logoarea.php'); ?>
|
|
<button type="button" class="btn btn-sm px-3 font-size-24 header-item waves-effect vertical-menu-btn">
|
|
<i class="bx bx-menu align-middle"></i>
|
|
</button>
|
|
<div class="page-title-box align-self-center d-none d-md-block">
|
|
<h4 class="page-title mb-0">Insegnanti</h4>
|
|
</div>
|
|
</div>
|
|
<div class="d-flex">
|
|
<?php include('include/languageselection.php'); ?>
|
|
<?php include('include/profiletopbar.php'); ?>
|
|
</div>
|
|
</div>
|
|
</header>
|
|
<?php include('include/sidebar.php'); ?>
|
|
<header class="ishorizontal-topbar">
|
|
<div class="navbar-header">
|
|
<div class="d-flex"></div>
|
|
</div>
|
|
<div class="topnav">
|
|
<div class="container-fluid">
|
|
<nav class="navbar navbar-light navbar-expand-lg topnav-menu"></nav>
|
|
</div>
|
|
</div>
|
|
</header>
|
|
|
|
<div class="main-content">
|
|
<div class="page-content">
|
|
<div class="container-fluid">
|
|
|
|
<?php if ($flash) : ?>
|
|
<div class="alert alert-<?php echo e($flash[0]); ?> alert-dismissible fade show" role="alert">
|
|
<?php echo e($flash[1]); ?>
|
|
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Chiudi"></button>
|
|
</div>
|
|
<?php endif; ?>
|
|
|
|
<div class="teachers-head">
|
|
<div>
|
|
<h5>Insegnanti della scuola</h5>
|
|
<small class="text-muted"><?php echo count($teachers); ?> insegnant<?php echo count($teachers) === 1 ? 'e' : 'i'; ?></small>
|
|
</div>
|
|
<button type="button" class="btn btn-primary" onclick="openTeacherModal(null)">
|
|
<i class="fas fa-user-plus me-1"></i> Nuovo insegnante
|
|
</button>
|
|
</div>
|
|
|
|
<?php if (empty($teachers)) : ?>
|
|
<div class="empty-teachers">
|
|
<i class="fas fa-chalkboard-teacher fa-2x mb-2"></i>
|
|
<p>Nessun insegnante. Aggiungi il primo: diventerà automaticamente il titolare.</p>
|
|
</div>
|
|
<?php else : ?>
|
|
<div class="row">
|
|
<?php foreach ($teachers as $t) :
|
|
$tid = (int) $t['idemployee'];
|
|
$isOwner = $t['is_owner'] === 'Y';
|
|
$isActive = $t['active'] === 'Y';
|
|
$fullName = trim($t['nameemployee'] . ' ' . $t['surnameemployee']);
|
|
$photoUrl = $t['photo'] ? PHOTO_DIR_REL . $t['photo'] : '';
|
|
$payload = [
|
|
'id' => $tid,
|
|
'nameemployee' => $t['nameemployee'],
|
|
'surnameemployee' => $t['surnameemployee'],
|
|
'email' => $t['email'],
|
|
'phone' => $t['phone'],
|
|
'photo' => $photoUrl,
|
|
'notifications' => $t['notifications'] === 'Y',
|
|
'active' => $isActive,
|
|
'is_owner' => $isOwner,
|
|
];
|
|
?>
|
|
<div class="col-md-6 col-xl-4">
|
|
<div class="teacher-card <?php echo $isOwner ? 'owner' : ''; ?> <?php echo $isActive ? '' : 'inactive'; ?>">
|
|
<div class="teacher-top">
|
|
<?php if ($photoUrl) : ?>
|
|
<img class="teacher-avatar" src="<?php echo e($photoUrl); ?>" alt="<?php echo e($fullName); ?>">
|
|
<?php else : ?>
|
|
<div class="teacher-avatar" style="background:<?php echo teacherColor($fullName); ?>;"><?php echo e(teacherInitials($t['nameemployee'], $t['surnameemployee'])); ?></div>
|
|
<?php endif; ?>
|
|
<div>
|
|
<div class="teacher-name"><?php echo e($fullName); ?></div>
|
|
<?php if ($isOwner) : ?><span class="t-badge owner"><i class="fas fa-crown me-1"></i>Titolare</span><?php endif; ?>
|
|
<?php if (!$isActive) : ?><span class="t-badge inactive">Non attivo</span><?php endif; ?>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="teacher-info"><i class="far fa-envelope"></i>
|
|
<?php echo $t['email'] ? '<a href="mailto:' . e($t['email']) . '">' . e($t['email']) . '</a>' : '<span class="missing">email non inserita</span>'; ?>
|
|
</div>
|
|
<div class="teacher-info"><i class="fas fa-phone"></i>
|
|
<?php echo $t['phone'] ? '<a href="tel:' . e(preg_replace('/[^0-9+]/', '', $t['phone'])) . '">' . e($t['phone']) . '</a>' : '<span class="missing">telefono non inserito</span>'; ?>
|
|
</div>
|
|
<div class="teacher-info"><i class="fas fa-layer-group"></i>
|
|
<?php echo (int) $t['nservices']; ?> class<?php echo (int) $t['nservices'] === 1 ? 'e' : 'i'; ?> assegnat<?php echo (int) $t['nservices'] === 1 ? 'a' : 'e'; ?>
|
|
</div>
|
|
|
|
<div class="teacher-foot">
|
|
<form method="post" class="notify-form">
|
|
<input type="hidden" name="csrf" value="<?php echo e($csrf); ?>">
|
|
<input type="hidden" name="action" value="toggle_notifications">
|
|
<input type="hidden" name="id" value="<?php echo $tid; ?>">
|
|
<div class="form-check form-switch mb-0">
|
|
<input class="form-check-input" type="checkbox" role="switch" id="notify<?php echo $tid; ?>"
|
|
<?php echo $t['notifications'] === 'Y' ? 'checked' : ''; ?> onchange="this.form.submit()">
|
|
<label class="form-check-label" for="notify<?php echo $tid; ?>">Notifiche email</label>
|
|
</div>
|
|
<?php if ($t['notifications'] === 'Y' && !$t['email']) : ?>
|
|
<div class="notify-warning"><i class="fas fa-exclamation-triangle"></i> manca l'email</div>
|
|
<?php endif; ?>
|
|
</form>
|
|
|
|
<div class="t-actions">
|
|
<button type="button" class="t-btn edit" title="Modifica"
|
|
data-teacher="<?php echo e(json_encode($payload)); ?>"
|
|
onclick="openTeacherModal(JSON.parse(this.dataset.teacher))">
|
|
<i class="fas fa-pen"></i>
|
|
</button>
|
|
<?php if (!$isOwner) : ?>
|
|
<form method="post" class="confirm-form"
|
|
data-title="Impostare come titolare?"
|
|
data-text="<?php echo e($fullName); ?> diventerà il titolare della scuola al posto dell'attuale.">
|
|
<input type="hidden" name="csrf" value="<?php echo e($csrf); ?>">
|
|
<input type="hidden" name="action" value="set_owner">
|
|
<input type="hidden" name="id" value="<?php echo $tid; ?>">
|
|
<button type="submit" class="t-btn owner" title="Imposta come titolare"><i class="fas fa-crown"></i></button>
|
|
</form>
|
|
<form method="post" class="confirm-form" data-danger="1"
|
|
data-title="Eliminare <?php echo e($fullName); ?>?"
|
|
data-text="L'operazione non è reversibile.">
|
|
<input type="hidden" name="csrf" value="<?php echo e($csrf); ?>">
|
|
<input type="hidden" name="action" value="delete">
|
|
<input type="hidden" name="id" value="<?php echo $tid; ?>">
|
|
<button type="submit" class="t-btn del" title="Elimina"><i class="fas fa-trash"></i></button>
|
|
</form>
|
|
<?php endif; ?>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<?php endforeach; ?>
|
|
</div>
|
|
<?php endif; ?>
|
|
|
|
</div>
|
|
<?php include('include/footer.php'); ?>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- ============================================ MODALE CREA / MODIFICA -->
|
|
<div class="modal fade" id="teacherModal" tabindex="-1" aria-hidden="true">
|
|
<div class="modal-dialog modal-dialog-centered">
|
|
<form class="modal-content" method="post" enctype="multipart/form-data" id="teacherForm">
|
|
<div class="modal-header">
|
|
<h5 class="modal-title" id="teacherModalTitle">Nuovo insegnante</h5>
|
|
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Chiudi"></button>
|
|
</div>
|
|
<div class="modal-body">
|
|
<input type="hidden" name="csrf" value="<?php echo e($csrf); ?>">
|
|
<input type="hidden" name="action" value="save">
|
|
<input type="hidden" name="id" id="t_id" value="0">
|
|
|
|
<div class="d-flex align-items-center gap-3 mb-3">
|
|
<div class="photo-preview" id="t_preview"><i class="fas fa-user"></i></div>
|
|
<div class="flex-grow-1">
|
|
<label class="form-label mb-1">Foto <small class="text-muted">(facoltativa, JPG/PNG/WEBP, max 3 MB)</small></label>
|
|
<input type="file" name="photo" id="t_photo" class="form-control form-control-sm" accept="image/jpeg,image/png,image/webp">
|
|
<div class="form-check mt-2" id="t_remove_wrap" style="display:none;">
|
|
<input class="form-check-input" type="checkbox" name="remove_photo" id="t_remove">
|
|
<label class="form-check-label" for="t_remove">Rimuovi foto attuale</label>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="row g-2">
|
|
<div class="col-6">
|
|
<label class="form-label mb-1">Nome *</label>
|
|
<input type="text" name="nameemployee" id="t_name" class="form-control" maxlength="100" required>
|
|
</div>
|
|
<div class="col-6">
|
|
<label class="form-label mb-1">Cognome *</label>
|
|
<input type="text" name="surnameemployee" id="t_surname" class="form-control" maxlength="100" required>
|
|
</div>
|
|
<div class="col-12">
|
|
<label class="form-label mb-1">Email</label>
|
|
<input type="email" name="email" id="t_email" class="form-control" maxlength="150">
|
|
</div>
|
|
<div class="col-12">
|
|
<label class="form-label mb-1">Telefono</label>
|
|
<input type="text" name="phone" id="t_phone" class="form-control" maxlength="40">
|
|
</div>
|
|
</div>
|
|
|
|
<div class="mt-3">
|
|
<div class="form-check form-switch">
|
|
<input class="form-check-input" type="checkbox" name="notifications" id="t_notify" checked>
|
|
<label class="form-check-label" for="t_notify">Riceve notifiche email</label>
|
|
</div>
|
|
<div class="form-check form-switch">
|
|
<input class="form-check-input" type="checkbox" name="active" id="t_active" checked>
|
|
<label class="form-check-label" for="t_active">Attivo</label>
|
|
</div>
|
|
<div class="text-muted" id="t_owner_note" style="font-size:12px;display:none;">
|
|
<i class="fas fa-crown me-1" style="color:#b08d57;"></i> È il titolare: non può essere disattivato.
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="modal-footer">
|
|
<button type="button" class="btn btn-light" data-bs-dismiss="modal">Annulla</button>
|
|
<button type="submit" class="btn btn-primary"><i class="fas fa-save me-1"></i> Salva</button>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
|
|
<script src="assets/libs/bootstrap/js/bootstrap.bundle.min.js"></script>
|
|
<script src="assets/libs/metismenujs/metismenujs.min.js"></script>
|
|
<script src="assets/libs/simplebar/simplebar.min.js"></script>
|
|
<script src="assets/libs/eva-icons/eva.min.js"></script>
|
|
<script src="assets/js/app.js"></script>
|
|
|
|
<script>
|
|
var teacherModal = null;
|
|
|
|
function setPreview(url) {
|
|
var box = document.getElementById('t_preview');
|
|
box.innerHTML = url ? '<img src="' + url + '" alt="">' : '<i class="fas fa-user"></i>';
|
|
}
|
|
|
|
function openTeacherModal(t) {
|
|
var isEdit = !!t;
|
|
document.getElementById('teacherModalTitle').textContent = isEdit ? 'Modifica insegnante' : 'Nuovo insegnante';
|
|
document.getElementById('t_id').value = isEdit ? t.id : 0;
|
|
document.getElementById('t_name').value = isEdit ? (t.nameemployee || '') : '';
|
|
document.getElementById('t_surname').value = isEdit ? (t.surnameemployee || '') : '';
|
|
document.getElementById('t_email').value = isEdit ? (t.email || '') : '';
|
|
document.getElementById('t_phone').value = isEdit ? (t.phone || '') : '';
|
|
document.getElementById('t_notify').checked = isEdit ? t.notifications : true;
|
|
|
|
var active = document.getElementById('t_active');
|
|
active.checked = isEdit ? t.active : true;
|
|
active.disabled = isEdit && t.is_owner;
|
|
document.getElementById('t_owner_note').style.display = (isEdit && t.is_owner) ? 'block' : 'none';
|
|
|
|
document.getElementById('t_photo').value = '';
|
|
document.getElementById('t_remove').checked = false;
|
|
document.getElementById('t_remove_wrap').style.display = (isEdit && t.photo) ? 'block' : 'none';
|
|
setPreview(isEdit ? t.photo : '');
|
|
|
|
if (!teacherModal) teacherModal = new bootstrap.Modal(document.getElementById('teacherModal'));
|
|
teacherModal.show();
|
|
}
|
|
|
|
// il titolare ha "Attivo" disabilitato: lo riabilitiamo al submit così il valore viene inviato
|
|
document.getElementById('teacherForm').addEventListener('submit', function() {
|
|
document.getElementById('t_active').disabled = false;
|
|
});
|
|
|
|
// anteprima foto + controllo dimensione
|
|
document.getElementById('t_photo').addEventListener('change', function() {
|
|
var f = this.files[0];
|
|
if (!f) return;
|
|
if (f.size > 3 * 1024 * 1024) {
|
|
Swal.fire('Foto troppo grande', 'La foto deve essere al massimo di 3 MB.', 'warning');
|
|
this.value = '';
|
|
return;
|
|
}
|
|
var reader = new FileReader();
|
|
reader.onload = function(ev) {
|
|
setPreview(ev.target.result);
|
|
};
|
|
reader.readAsDataURL(f);
|
|
document.getElementById('t_remove').checked = false;
|
|
});
|
|
|
|
// conferma per titolare / elimina
|
|
document.querySelectorAll('.confirm-form').forEach(function(form) {
|
|
form.addEventListener('submit', function(ev) {
|
|
if (form.dataset.confirmed === '1') return;
|
|
ev.preventDefault();
|
|
var danger = form.dataset.danger === '1';
|
|
Swal.fire({
|
|
title: form.dataset.title,
|
|
text: form.dataset.text,
|
|
icon: danger ? 'warning' : 'question',
|
|
showCancelButton: true,
|
|
confirmButtonColor: danger ? '#e74c3c' : '#b08d57',
|
|
cancelButtonColor: '#6b7280',
|
|
confirmButtonText: danger ? 'Sì, elimina' : 'Sì, conferma',
|
|
cancelButtonText: 'Annulla'
|
|
}).then(function(r) {
|
|
if (r.isConfirmed) {
|
|
form.dataset.confirmed = '1';
|
|
form.submit();
|
|
}
|
|
});
|
|
});
|
|
});
|
|
</script>
|
|
</body>
|
|
|
|
</html>
|