getConnection(); /* ========================================== PERMISSIONS ========================================== */ $isHrManager = Auth::user()->hasRole('Admin') || Auth::user()->hasRole('Superuser') || Auth::user()->hasRole('employee-hr') || Auth::user()->hasRole('manager'); /* ========================================== RESOLVE TARGET EMPLOYEE ========================================== */ $requestedId = isset($_GET['id']) ? (int)$_GET['id'] : 0; $isOwnProfile = ($requestedId === 0); if ($isOwnProfile) { $stmt = $pdo->prepare("SELECT id FROM employees WHERE auth_user_id = :uid LIMIT 1"); $stmt->execute(['uid' => $iduserlogin]); $employeeId = (int)$stmt->fetchColumn(); } else { if (!$isHrManager) { // Non-HR users can only view their own profile. header('Location: employee-profile.php'); exit; } $employeeId = $requestedId; } /* ========================================== LOAD EMPLOYEE DATA ========================================== */ $employee = null; if ($employeeId > 0) { $stmt = $pdo->prepare(" SELECT e.*, d.name AS department_name, d.color AS department_color, jr.name AS job_role_name, au.first_name AS auth_first_name, au.last_name AS auth_last_name, au.email AS auth_email, au.username AS auth_username, au.avatar AS auth_avatar FROM employees e LEFT JOIN departments d ON d.id = e.department_id LEFT JOIN job_roles jr ON jr.id = e.job_role_id LEFT JOIN auth_users au ON au.id = e.auth_user_id WHERE e.id = :id LIMIT 1 "); $stmt->execute(['id' => $employeeId]); $employee = $stmt->fetch(PDO::FETCH_ASSOC) ?: null; } /* Authorization: own profile must match auth_user_id (defence in depth) */ if (!$isHrManager && $employee && (int)$employee['auth_user_id'] !== (int)$iduserlogin) { header('Location: employee-profile.php'); exit; } $canEdit = $isHrManager; /* ========================================== DOCUMENTS (File Repository) ========================================== */ $documents = []; if ($employee) { $stmt = $pdo->prepare(" SELECT d.*, TRIM(CONCAT(COALESCE(au.first_name,''),' ',COALESCE(au.last_name,''))) AS uploader_name, au.email AS uploader_email FROM employee_documents d LEFT JOIN auth_users au ON au.id = d.uploaded_by WHERE d.employee_id = :eid ORDER BY d.created_at DESC "); $stmt->execute(['eid' => $employeeId]); $documents = $stmt->fetchAll(PDO::FETCH_ASSOC); } /* ========================================== TRAINING HISTORY ========================================== */ $trainings = []; $trainingTopicsAll = []; $missingMandatoryTopics = []; if ($employee) { $stmt = $pdo->prepare(" SELECT et.*, tt.name AS topic_name, tt.default_frequency_months AS topic_default_freq, tt.default_reminder_days AS topic_default_rem, (SELECT COUNT(*) FROM employee_training_attachments a WHERE a.training_id = et.id) AS attachments_count FROM employee_trainings et JOIN training_topics tt ON tt.id = et.training_topic_id WHERE et.employee_id = :eid ORDER BY et.completed_date DESC, et.id DESC "); $stmt->execute(['eid' => $employeeId]); $trainings = $stmt->fetchAll(PDO::FETCH_ASSOC); // Mark the most recent record per topic — older ones are history, not "expired". $seenTopics = []; foreach ($trainings as &$t) { $tid = (int)$t['training_topic_id']; $t['_is_latest'] = !isset($seenTopics[$tid]); $seenTopics[$tid] = true; } unset($t); if ($canEdit) { $trainingTopicsAll = $pdo->query(" SELECT id, name, default_frequency_months, default_reminder_days FROM training_topics WHERE is_active = 1 ORDER BY sort_order, name ")->fetchAll(PDO::FETCH_ASSOC); } $missingStmt = $pdo->prepare(" SELECT tt.id, tt.name FROM training_topics tt WHERE tt.is_active = 1 AND tt.is_mandatory = 1 AND NOT EXISTS ( SELECT 1 FROM employee_trainings et WHERE et.employee_id = :eid AND et.training_topic_id = tt.id ) ORDER BY tt.sort_order, tt.name "); $missingStmt->execute(['eid' => $employeeId]); $missingMandatoryTopics = $missingStmt->fetchAll(PDO::FETCH_ASSOC); } /* ========================================== PPE (Assigned) ========================================== */ $ppeList = []; if ($employee) { $stmt = $pdo->prepare(" SELECT * FROM employee_ppe WHERE employee_id = :eid ORDER BY delivery_date DESC, created_at DESC "); $stmt->execute(['eid' => $employeeId]); $ppeList = $stmt->fetchAll(PDO::FETCH_ASSOC); } /* ========================================== DROPDOWN DATA FOR EDIT MODAL ========================================== */ $departments = $isHrManager ? $pdo->query("SELECT id, name FROM departments WHERE is_active = 1 ORDER BY sort_order, name")->fetchAll(PDO::FETCH_ASSOC) : []; $jobRoles = $isHrManager ? $pdo->query("SELECT id, name FROM job_roles WHERE is_active = 1 ORDER BY sort_order, name")->fetchAll(PDO::FETCH_ASSOC) : []; $authUsers = $isHrManager ? $pdo->query("SELECT id, username, first_name, last_name, email, role_id FROM auth_users ORDER BY first_name, last_name")->fetchAll(PDO::FETCH_ASSOC) : []; $rolesList = $isHrManager ? $pdo->query("SELECT id, name, display_name FROM auth_roles ORDER BY display_name, name")->fetchAll(PDO::FETCH_ASSOC) : []; /* ========================================== HELPERS ========================================== */ function statusBadge(string $status): array { switch ($status) { case 'active': return ['label' => 'Attivo', 'class' => 'success']; case 'inactive': return ['label' => 'Cessato', 'class' => 'secondary']; case 'suspended': return ['label' => 'Sospeso', 'class' => 'warning']; default: return ['label' => htmlspecialchars($status), 'class' => 'secondary']; } } function fmtDate(?string $d): string { if (!$d || $d === '0000-00-00') return '—'; $ts = strtotime($d); return $ts ? date('d/m/Y', $ts) : '—'; } function valOrDash($v): string { $v = (string)($v ?? ''); return $v !== '' ? htmlspecialchars($v) : '—'; } function categoryLabel(string $c): string { switch ($c) { case 'job_description': return 'Mansionario'; case 'contract': return 'Contratto'; case 'rules': return 'Regolamento'; case 'other': return 'Altro'; default: return htmlspecialchars($c); } } function trainingStatus(?string $nextDue, ?int $reminderDays, ?int $topicDefaultRem): array { if (!$nextDue) { return ['code' => 'compliant', 'label' => 'Conforme', 'class' => 'success']; } $rem = $reminderDays !== null ? $reminderDays : ($topicDefaultRem !== null ? $topicDefaultRem : 30); $today = new DateTime('today'); $due = DateTime::createFromFormat('Y-m-d', $nextDue); if (!$due) return ['code' => 'compliant', 'label' => 'Conforme', 'class' => 'success']; $daysLeft = (int)$today->diff($due)->format('%r%a'); if ($daysLeft < 0) return ['code' => 'expired', 'label' => 'Scaduto', 'class' => 'danger']; if ($daysLeft <= $rem) return ['code' => 'due_soon', 'label' => 'Da aggiornare', 'class' => 'warning']; return ['code' => 'compliant', 'label' => 'Conforme', 'class' => 'success']; } function fmtFileSize(?int $bytes): string { if ($bytes === null || $bytes <= 0) return '—'; if ($bytes < 1024) return $bytes . ' B'; if ($bytes < 1024 * 1024) return number_format($bytes / 1024, 1) . ' KB'; if ($bytes < 1024 * 1024 * 1024) return number_format($bytes / 1024 / 1024, 1) . ' MB'; return number_format($bytes / 1024 / 1024 / 1024, 1) . ' GB'; } ?> Profilo Dipendente - <?= htmlspecialchars($titlewebsite, ENT_QUOTES, 'UTF-8'); ?>

user avatar

Codice:
💼 🏢
Nome
Cognome
Codice Dipendente
Data di Assunzione
Indirizzo
Telefono
Email
Reparto
Mansione
Stato
Utente collegato
Nessun utente collegato
Nessun documento

Categoria Nome File Dimensione Caricato da Data Azioni
⬇️ Scarica
Dim.: Da:
⬇️ Scarica
Nessun DPI assegnato

DPI Data Consegna Consegnato da Note Azioni
🦺
Consegnato da: Note:
⚠️ obbligator:
Nessuna formazione registrata

'storico', 'label' => 'Storico', 'class' => 'secondary']; $typeLabel = $t['training_type'] === 'refresher' ? 'Aggiornamento' : 'Iniziale'; ?>
Corso Tipo Completato Prossimo agg. Stato Allegati Azioni
'storico', 'label' => 'Storico', 'class' => 'secondary']; $typeLabel = $t['training_type'] === 'refresher' ? 'Aggiornamento' : 'Iniziale'; ?>
📖
Tipo: Completato: Prossimo: 0): ?> Allegati: