486 lines
19 KiB
PHP
486 lines
19 KiB
PHP
<?php
|
||
// teacher_page.php
|
||
|
||
ini_set('display_errors', 1);
|
||
ini_set('display_startup_errors', 1);
|
||
error_reporting(E_ALL);
|
||
|
||
include('include/headscript.php');
|
||
|
||
// QR Code library
|
||
require_once __DIR__ . '/../../vendor/autoload.php';
|
||
|
||
use Endroid\QrCode\QrCode;
|
||
use Endroid\QrCode\Writer\PngWriter;
|
||
|
||
$dbHandler = DBHandlerSelect::getInstance();
|
||
$pdo = $dbHandler->getConnection();
|
||
|
||
if (!isset($iduserlogin)) {
|
||
die("Errore: ID utente non definito.");
|
||
}
|
||
|
||
/**
|
||
* QR helper compatible with older/newer Endroid versions (best-effort)
|
||
*/
|
||
function writeQrPng($text, $filename, $size = 150, $margin = 10)
|
||
{
|
||
// Your installed version seems to require text in constructor
|
||
$qrCode = new \Endroid\QrCode\QrCode($text);
|
||
|
||
if (method_exists($qrCode, 'setSize')) {
|
||
$qrCode->setSize($size);
|
||
} elseif (method_exists($qrCode, 'setModuleSize')) {
|
||
$module = max(3, (int)round($size / 25));
|
||
$qrCode->setModuleSize($module);
|
||
}
|
||
|
||
if (method_exists($qrCode, 'setMargin')) {
|
||
$qrCode->setMargin($margin);
|
||
} elseif (method_exists($qrCode, 'setPadding')) {
|
||
$qrCode->setPadding($margin);
|
||
}
|
||
|
||
$writer = new \Endroid\QrCode\Writer\PngWriter();
|
||
|
||
if (method_exists($writer, 'writeFile')) {
|
||
$writer->writeFile($qrCode, $filename);
|
||
} else {
|
||
$result = $writer->write($qrCode);
|
||
if (is_object($result) && method_exists($result, 'saveToFile')) {
|
||
$result->saveToFile($filename);
|
||
} else {
|
||
file_put_contents($filename, (string)$result);
|
||
}
|
||
}
|
||
}
|
||
|
||
function generateUniqueCode($pdo, $length = 16)
|
||
{
|
||
do {
|
||
$code = bin2hex(random_bytes($length / 2));
|
||
$stmt = $pdo->prepare("SELECT COUNT(*) FROM teachers WHERE unique_code = ?");
|
||
$stmt->execute([$code]);
|
||
} while ($stmt->fetchColumn() > 0);
|
||
return $code;
|
||
}
|
||
|
||
/**
|
||
* Detect view mode
|
||
* - Owner view: teacher_page.php?id=TEACHER_ID (teachers.id)
|
||
* - Teacher self view: teacher_page.php
|
||
*/
|
||
$teacher_id = (int)($_GET['id'] ?? 0);
|
||
$is_owner_view = ($teacher_id > 0);
|
||
|
||
$success_message = $error = null;
|
||
|
||
/**
|
||
* 1) LOAD teacher row
|
||
*/
|
||
if ($is_owner_view) {
|
||
// OWNER VIEW: load teacher by teachers.id only if owner has rights
|
||
$stmt = $pdo->prepare("
|
||
SELECT
|
||
t.*,
|
||
u.first_name, u.last_name, u.email
|
||
FROM teachers t
|
||
JOIN auth_users u ON t.user_id = u.id
|
||
JOIN teacher_schools ts ON ts.teacher_id = t.id
|
||
JOIN schools s ON s.id = ts.school_id
|
||
WHERE t.id = ?
|
||
AND s.owner_id = ?
|
||
LIMIT 1
|
||
");
|
||
$stmt->execute([$teacher_id, $iduserlogin]);
|
||
$teacher = $stmt->fetch(PDO::FETCH_ASSOC);
|
||
|
||
if (!$teacher) {
|
||
die("Errore: insegnante non trovata o non hai permessi.");
|
||
}
|
||
} else {
|
||
// TEACHER SELF VIEW: load by logged user
|
||
$stmt = $pdo->prepare("
|
||
SELECT
|
||
t.*,
|
||
u.first_name, u.last_name, u.email
|
||
FROM auth_users u
|
||
LEFT JOIN teachers t ON t.user_id = u.id
|
||
WHERE u.id = ?
|
||
LIMIT 1
|
||
");
|
||
$stmt->execute([$iduserlogin]);
|
||
$teacher = $stmt->fetch(PDO::FETCH_ASSOC);
|
||
|
||
// If not exists in teachers, CREATE IT before showing the form (auto-create)
|
||
if (empty($teacher['id'])) {
|
||
// ✅ SOLO QUI: quando auto-crei il profilo teacher (SELF VIEW), aggiungi created_by = iduserlogin
|
||
|
||
$unique_code = generateUniqueCode($pdo);
|
||
|
||
$stmtIns = $pdo->prepare("
|
||
INSERT INTO teachers (user_id, unique_code, phone, description, specializations, profile_picture, status, created_by)
|
||
VALUES (?, ?, NULL, '', '', '', 'active', ?)
|
||
");
|
||
$ok = $stmtIns->execute([$iduserlogin, $unique_code, $iduserlogin]);
|
||
|
||
|
||
if (!$ok) {
|
||
die("Errore: impossibile creare il profilo insegnante.");
|
||
}
|
||
|
||
// Reload teacher after insert
|
||
$stmt = $pdo->prepare("
|
||
SELECT
|
||
t.*,
|
||
u.first_name, u.last_name, u.email
|
||
FROM teachers t
|
||
JOIN auth_users u ON t.user_id = u.id
|
||
WHERE t.user_id = ?
|
||
LIMIT 1
|
||
");
|
||
$stmt->execute([$iduserlogin]);
|
||
$teacher = $stmt->fetch(PDO::FETCH_ASSOC);
|
||
}
|
||
}
|
||
|
||
/**
|
||
* Now teacher MUST exist (in owner view and in self view due to auto-create)
|
||
*/
|
||
$is_new = empty($teacher['id']); // should be false at this point
|
||
|
||
/**
|
||
* 2) HANDLE POST (save)
|
||
*/
|
||
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||
|
||
// target user is the teacher being edited
|
||
$target_user_id = $is_owner_view ? (int)$teacher['user_id'] : (int)$iduserlogin;
|
||
|
||
$first_name = trim($_POST['first_name'] ?? '');
|
||
$last_name = trim($_POST['last_name'] ?? '');
|
||
$phone = trim($_POST['phone'] ?? '');
|
||
$description = trim($_POST['description'] ?? '');
|
||
$specializations = trim($_POST['specializations'] ?? '');
|
||
$status = (($_POST['status'] ?? 'active') === 'active') ? 'active' : 'inactive';
|
||
|
||
// Update auth_users names for the target teacher
|
||
$stmt = $pdo->prepare("UPDATE auth_users SET first_name = ?, last_name = ? WHERE id = ?");
|
||
$stmt->execute([$first_name, $last_name, $target_user_id]);
|
||
|
||
// Photo upload (use target user id in filename)
|
||
$profile_picture = $teacher['profile_picture'] ?? '';
|
||
if (!empty($_FILES['profile_picture']['name']) && $_FILES['profile_picture']['error'] === UPLOAD_ERR_OK) {
|
||
|
||
$ext = strtolower(pathinfo($_FILES['profile_picture']['name'], PATHINFO_EXTENSION));
|
||
|
||
if (in_array($ext, ['jpg', 'jpeg', 'png', 'gif'])) {
|
||
$new_name = "phototeachers/{$target_user_id}-" . time() . "-profile.$ext";
|
||
|
||
if (move_uploaded_file($_FILES['profile_picture']['tmp_name'], $new_name)) {
|
||
if ($profile_picture && file_exists($profile_picture)) {
|
||
@unlink($profile_picture);
|
||
}
|
||
$profile_picture = $new_name;
|
||
} else {
|
||
$error = "Errore caricamento foto.";
|
||
}
|
||
} else {
|
||
$error = "Solo JPG, PNG, GIF ammessi.";
|
||
}
|
||
}
|
||
|
||
if (!$error) {
|
||
// Update teachers row (always exists at this point)
|
||
$stmt = $pdo->prepare("
|
||
UPDATE teachers
|
||
SET phone = ?, description = ?, specializations = ?, profile_picture = ?, status = ?
|
||
WHERE user_id = ?
|
||
");
|
||
$success = $stmt->execute([
|
||
$phone ?: null,
|
||
$description,
|
||
$specializations,
|
||
$profile_picture,
|
||
$status,
|
||
$target_user_id
|
||
]);
|
||
|
||
if ($success) {
|
||
$success_message = "Dati aggiornati!";
|
||
|
||
// Reload teacher (with correct target user)
|
||
$stmt = $pdo->prepare("
|
||
SELECT t.*, u.first_name, u.last_name, u.email
|
||
FROM teachers t
|
||
JOIN auth_users u ON t.user_id = u.id
|
||
WHERE t.user_id = ?
|
||
LIMIT 1
|
||
");
|
||
$stmt->execute([$target_user_id]);
|
||
$teacher = $stmt->fetch(PDO::FETCH_ASSOC);
|
||
} else {
|
||
$error = "Errore aggiornamento.";
|
||
}
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 3) QR generation (after teacher is loaded)
|
||
*/
|
||
$qr_code_path = null;
|
||
if (!empty($teacher['unique_code'])) {
|
||
try {
|
||
$unique_code = $teacher['unique_code'];
|
||
|
||
// IMPORTANT: file name uses target user_id (teacher user), not owner id
|
||
$qr_user_id = (int)$teacher['user_id'];
|
||
|
||
$base_dir = __DIR__ . '/../../public/phototeachers/qrcodes/';
|
||
$qr_filename = "{$base_dir}{$qr_user_id}-{$unique_code}.png";
|
||
$qr_code_path = "phototeachers/qrcodes/{$qr_user_id}-{$unique_code}.png";
|
||
|
||
if (!file_exists($qr_filename)) {
|
||
if (!is_dir($base_dir)) mkdir($base_dir, 0755, true);
|
||
writeQrPng($unique_code, $qr_filename, 150, 10);
|
||
}
|
||
} catch (Exception $e) {
|
||
error_log("Errore QR: " . $e->getMessage());
|
||
}
|
||
}
|
||
?>
|
||
|
||
<!doctype html>
|
||
<html lang="it">
|
||
|
||
<head>
|
||
<meta charset="utf-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||
<title>Profilo Insegnante</title>
|
||
<?php include('cssinclude.php'); ?>
|
||
<?php include('siteinfo.php'); ?>
|
||
|
||
<link href="https://cdn.jsdelivr.net/npm/quill@2.0.2/dist/quill.snow.css" rel="stylesheet" />
|
||
|
||
<style>
|
||
.teacher-photo {
|
||
max-width: 100%;
|
||
height: auto;
|
||
max-height: 260px;
|
||
object-fit: contain;
|
||
border: 1px solid #dee2e6;
|
||
border-radius: 8px;
|
||
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.08);
|
||
background: #fff;
|
||
padding: 10px;
|
||
margin-bottom: 1.5rem;
|
||
}
|
||
|
||
.quill-wrapper {
|
||
min-height: 300px;
|
||
display: flex;
|
||
flex-direction: column;
|
||
}
|
||
|
||
.ql-container {
|
||
flex: 1;
|
||
font-size: 15px;
|
||
border: 1px solid #ced4da;
|
||
border-radius: 0 0 0.375rem 0.375rem;
|
||
}
|
||
|
||
.ql-editor {
|
||
min-height: 220px;
|
||
}
|
||
|
||
.ql-toolbar {
|
||
border-radius: 0.375rem 0.375rem 0 0;
|
||
border-color: #ced4da;
|
||
}
|
||
|
||
.form-section {
|
||
margin-bottom: 2rem;
|
||
}
|
||
|
||
.form-label {
|
||
font-weight: 500;
|
||
margin-bottom: 0.5rem;
|
||
}
|
||
</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 radius-10">
|
||
<div class="card-header">
|
||
<h6 class="mb-0">Profilo Insegnante</h6>
|
||
</div>
|
||
|
||
<div class="card-body">
|
||
<?php if (!empty($success_message)): ?>
|
||
<div class="alert alert-success alert-dismissible fade show">
|
||
<?php echo htmlspecialchars($success_message); ?>
|
||
<button type="button" class="btn-close" data-bs-dismiss="alert"></button>
|
||
</div>
|
||
<?php endif; ?>
|
||
|
||
<?php if (!empty($error)): ?>
|
||
<div class="alert alert-danger alert-dismissible fade show">
|
||
<?php echo htmlspecialchars($error); ?>
|
||
<button type="button" class="btn-close" data-bs-dismiss="alert"></button>
|
||
</div>
|
||
<?php endif; ?>
|
||
|
||
<form method="POST" enctype="multipart/form-data" id="teacherForm">
|
||
<div class="row g-4">
|
||
<div class="col-lg-4 text-center">
|
||
<img src="<?php echo $teacher['profile_picture'] ? htmlspecialchars($teacher['profile_picture']) : 'phototeachers/ndphoto.png'; ?>"
|
||
alt="Foto Profilo" class="teacher-photo">
|
||
|
||
<div class="mb-4">
|
||
<label for="profile_picture" class="form-label">Carica nuova foto</label>
|
||
<input type="file" class="form-control" id="profile_picture" name="profile_picture" accept="image/jpeg,image/png,image/gif">
|
||
<small class="text-muted d-block mt-1">Max 2MB – JPG, PNG, GIF</small>
|
||
</div>
|
||
|
||
<?php if (!empty($teacher['unique_code']) && $qr_code_path): ?>
|
||
<div class="mb-3">
|
||
<label class="form-label">Codice Univoco</label>
|
||
<input type="text" class="form-control" value="<?php echo htmlspecialchars($teacher['unique_code']); ?>" readonly>
|
||
</div>
|
||
|
||
<div class="mb-3">
|
||
<label class="form-label">QR Code</label><br>
|
||
<img src="<?php echo htmlspecialchars($qr_code_path); ?>" alt="QR Code" class="img-fluid shadow-sm" style="max-width: 180px;">
|
||
</div>
|
||
<?php endif; ?>
|
||
</div>
|
||
|
||
<div class="col-lg-8">
|
||
<div class="row g-3">
|
||
<div class="col-md-6">
|
||
<label for="first_name" class="form-label">Nome</label>
|
||
<input type="text" class="form-control" id="first_name" name="first_name"
|
||
value="<?php echo htmlspecialchars($teacher['first_name'] ?? ''); ?>" required>
|
||
</div>
|
||
|
||
<div class="col-md-6">
|
||
<label for="last_name" class="form-label">Cognome</label>
|
||
<input type="text" class="form-control" id="last_name" name="last_name"
|
||
value="<?php echo htmlspecialchars($teacher['last_name'] ?? ''); ?>" required>
|
||
</div>
|
||
|
||
<div class="col-12">
|
||
<label for="email" class="form-label">Email</label>
|
||
<input type="email" class="form-control" id="email" name="email"
|
||
value="<?php echo htmlspecialchars($teacher['email'] ?? ''); ?>" readonly>
|
||
</div>
|
||
|
||
<div class="col-md-6">
|
||
<label for="phone" class="form-label">Telefono</label>
|
||
<input type="tel" class="form-control" id="phone" name="phone"
|
||
value="<?php echo htmlspecialchars($teacher['phone'] ?? ''); ?>">
|
||
</div>
|
||
|
||
<div class="col-12 form-section">
|
||
<label class="form-label">Descrizione insegnante</label>
|
||
<div class="quill-wrapper">
|
||
<div id="quill-editor"></div>
|
||
</div>
|
||
<input type="hidden" name="description" id="description-hidden">
|
||
</div>
|
||
|
||
<div class="col-12 form-section">
|
||
<label for="specializations" class="form-label">Specializzazioni</label>
|
||
<textarea class="form-control" id="specializations" name="specializations" rows="3"><?php echo htmlspecialchars($teacher['specializations'] ?? ''); ?></textarea>
|
||
<small class="text-muted">Es: Hatha Yoga, Vinyasa, Yin, Restorative...</small>
|
||
</div>
|
||
|
||
<div class="col-md-6">
|
||
<label class="form-label">Stato</label>
|
||
<div class="form-check form-switch mt-2">
|
||
<input class="form-check-input" type="checkbox" id="status" name="status" value="active"
|
||
<?php echo ($teacher['status'] ?? 'active') === 'active' ? 'checked' : ''; ?>>
|
||
<label class="form-check-label" for="status">
|
||
<?php echo ($teacher['status'] ?? 'active') === 'active' ? 'Attivo' : 'Inattivo'; ?>
|
||
</label>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="col-md-6">
|
||
<label class="form-label">Creato</label>
|
||
<input type="text" class="form-control" value="<?php echo htmlspecialchars($teacher['created_at'] ?? ''); ?>" readonly>
|
||
</div>
|
||
|
||
<div class="col-md-6">
|
||
<label class="form-label">Aggiornato</label>
|
||
<input type="text" class="form-control" value="<?php echo htmlspecialchars($teacher['updated_at'] ?? ''); ?>" readonly>
|
||
</div>
|
||
|
||
<div class="col-12 mt-5">
|
||
<button type="submit" class="btn btn-primary btn-lg px-5">
|
||
Salva Modifiche
|
||
</button>
|
||
</div>
|
||
|
||
</div>
|
||
</div>
|
||
|
||
</div>
|
||
</form>
|
||
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="overlay toggle-icon"></div>
|
||
<a href="javaScript:;" class="back-to-top"><i class='bx bxs-up-arrow-alt'></i></a>
|
||
<?php include('include/footer.php'); ?>
|
||
</div>
|
||
|
||
<?php include('jsinclude.php'); ?>
|
||
|
||
<script src="https://cdn.jsdelivr.net/npm/quill@2.0.2/dist/quill.js"></script>
|
||
<script>
|
||
const quill = new Quill('#quill-editor', {
|
||
theme: 'snow',
|
||
modules: {
|
||
toolbar: [
|
||
['bold', 'italic', 'underline', 'strike'],
|
||
['blockquote', 'code-block'],
|
||
[{
|
||
'header': [1, 2, 3, false]
|
||
}],
|
||
[{
|
||
'color': ['#000000', '#ff0000', '#00ff00', '#0000ff', '#ffff00', '#ff00ff', '#00ffff', '#808080', '#c0c0c0']
|
||
}, {
|
||
'background': []
|
||
}],
|
||
[{
|
||
'list': 'ordered'
|
||
}, {
|
||
'list': 'bullet'
|
||
}],
|
||
[{
|
||
'align': []
|
||
}],
|
||
['link', 'clean']
|
||
]
|
||
}
|
||
});
|
||
|
||
quill.root.innerHTML = `<?php echo addslashes($teacher['description'] ?? ''); ?>`;
|
||
|
||
document.getElementById('teacherForm').addEventListener('submit', function() {
|
||
document.getElementById('description-hidden').value = quill.root.innerHTML;
|
||
});
|
||
</script>
|
||
</body>
|
||
|
||
</html>
|