diff --git a/public/docs.php b/public/docs.php new file mode 100644 index 0000000..8b8abb1 --- /dev/null +++ b/public/docs.php @@ -0,0 +1,10 @@ + diff --git a/public/security.php b/public/security.php new file mode 100644 index 0000000..cd439a2 --- /dev/null +++ b/public/security.php @@ -0,0 +1,10 @@ + diff --git a/routes.php b/routes.php index 6c8b1fe..004fbce 100644 --- a/routes.php +++ b/routes.php @@ -8,6 +8,8 @@ '/upload' => 'src/controllers/upload.php', '/profile.php' => 'src/controllers/profile.php', '/settings.php' => 'src/controllers/settings.php', + '/security.php' => 'src/controllers/security.php', + '/docs.php' => 'src/controllers/docs.php', // weitere Routen ... ]; diff --git a/src/controllers/docs.php b/src/controllers/docs.php new file mode 100644 index 0000000..6da75af --- /dev/null +++ b/src/controllers/docs.php @@ -0,0 +1,42 @@ + config.php) +// Assumes $_SESSION['user_id'] is set by requireLogin() (called in public/docs.php) +try { + // Assuming 'documents' table columns: id, user_id, file_name, file_path, category, created_at + // Ensure 'is_deleted' column is considered if soft deletes are implemented for documents. + // For now, assuming no soft delete or it's handled elsewhere (e.g. only non-deleted items are in 'documents' table). + // If a documents table has an 'is_deleted' column, the query should be: + // "SELECT id, file_name, file_path, category, created_at FROM documents WHERE user_id = ? AND (is_deleted = 0 OR is_deleted IS NULL) ORDER BY created_at DESC" + $stmt = $pdo->prepare("SELECT id, file_name, file_path, category, created_at FROM documents WHERE user_id = ? ORDER BY created_at DESC"); + $stmt->execute([$_SESSION['user_id']]); + $documents = $stmt->fetchAll(PDO::FETCH_ASSOC); +} catch (PDOException $e) { + error_log("Error fetching documents for user_id {$_SESSION['user_id']}: " . $e->getMessage()); + $page_error = "Could not retrieve documents at this time. Please try again later."; +} + +// Load the main template +// Variables available to templates/docs.php: +// $pageTitle, $user (for navbar.php), $documents, $page_error +require_once __DIR__ . '/../../templates/docs.php'; +?> diff --git a/src/controllers/profile.php b/src/controllers/profile.php index 9bdc30a..8892221 100644 --- a/src/controllers/profile.php +++ b/src/controllers/profile.php @@ -1,142 +1,205 @@ -prepare(" - UPDATE users SET - first_name = ?, last_name = ?, birthdate = ?, - job_title = ?, location = ?, updated_at = NOW() - WHERE id = ? - "); - $stmt->execute([$first, $last, $birth, $job, $loc, $_SESSION['user_id']]); - $success = 'Personal Info wurde gespeichert.'; - } -} - -// 4) POST-Handling für Public Profile -$publicSuccess = ''; -if ($_SERVER['REQUEST_METHOD'] === 'POST' - && isset($_POST['subtab']) - && $_POST['subtab'] === 'public_profile' -) { - $bio = trim($_POST['bio'] ?? ''); - $links = $_POST['links'] ?? []; - - // nur nicht-leere Links speichern - $links = array_filter($links, fn($v) => $v !== ''); - - $stmt = $pdo->prepare('UPDATE users SET bio = ?, links = ? WHERE id = ?'); - $stmt->execute([$bio, json_encode($links), $_SESSION['user_id']]); - $publicSuccess = 'Public Profile wurde gespeichert.'; -} - -// 5) POST-Handling für Finance-Tab -if ($_SERVER['REQUEST_METHOD'] === 'POST' && $activeTab === 'finance') { - $description = trim($_POST['description'] ?? ''); - $type = $_POST['type'] ?? ''; - $amount = $_POST['amount'] ?? ''; - $entryDate = $_POST['entry_date'] ?? ''; - - if ($description === '' || !in_array($type, ['income','expense'], true) || !is_numeric($amount)) { - $errors[] = 'Bitte alle Felder korrekt ausfüllen.'; - } else { - $stmt = $pdo->prepare(" - INSERT INTO finance_entries - (user_id, type, amount, entry_date, note, currency) - VALUES (?,?,?,?,?,'EUR') - "); - $stmt->execute([ - $_SESSION['user_id'], - $type, - $amount, - $entryDate, - $description - ]); - $publicSuccess = 'Eintrag erfolgreich hinzugefügt.'; - } -} - -// 6) Finance-Einträge laden & löschen -$financeEntries = []; -if ($activeTab === 'finance') { - if (!empty($_GET['delete_finance']) && is_numeric($_GET['delete_finance'])) { - $stmt = $pdo->prepare('DELETE FROM finance_entries WHERE id = ? AND user_id = ?'); - $stmt->execute([$_GET['delete_finance'], $_SESSION['user_id']]); - } - $stmt = $pdo->prepare(" - SELECT * FROM finance_entries - WHERE user_id = ? - ORDER BY entry_date DESC - "); - $stmt->execute([$_SESSION['user_id']]); - $financeEntries = $stmt->fetchAll(); -} - -// 6a) Totale berechnen -$totalIncome = 0.0; -$totalExpense = 0.0; -foreach ($financeEntries as $f) { - if ($f['type'] === 'income') { - $totalIncome += (float)$f['amount']; - } else { - $totalExpense += (float)$f['amount']; - } -} -$balance = $totalIncome - $totalExpense; - - -// 7) Dokumente laden & löschen -$docs = []; -if ($activeTab === 'documents') { - if (!empty($_GET['delete']) && is_numeric($_GET['delete'])) { - $stmt = $pdo->prepare('UPDATE documents SET is_deleted = 1 WHERE id = ? AND user_id = ?'); - $stmt->execute([$_GET['delete'], $_SESSION['user_id']]); - } - $stmt = $pdo->prepare(" - SELECT * FROM documents - WHERE user_id = ? AND is_deleted = 0 - ORDER BY upload_date DESC - "); - $stmt->execute([$_SESSION['user_id']]); - $docs = $stmt->fetchAll(); -} - -// 8) Userdaten für sämtliche Tabs -$stmt = $pdo->prepare('SELECT * FROM users WHERE id = ?'); -$stmt->execute([$_SESSION['user_id']]); -$user = $stmt->fetch(); - -// 9) Template rendern -require_once __DIR__ . '/../../templates/profile.php'; +prepare("UPDATE users SET first_name = ?, last_name = ?, birthdate = ?, job_title = ?, location = ?, updated_at = NOW() WHERE id = ?"); $stmt->execute([$first, $last, $birth, $job, $loc, $_SESSION['user_id']]); $success = 'Personal Info wurde gespeichert.'; } + catch (PDOException $e) { error_log("Error updating personal info: " . $e->getMessage()); $errors[] = "Ein Datenbankfehler ist aufgetreten."; } + } + } + if (!empty($errors) && empty($_SESSION['csrf_token_personal_info'])) { $_SESSION['csrf_token_personal_info'] = bin2hex(random_bytes(32)); } + $csrf_token_personal_info = $_SESSION['csrf_token_personal_info'] ?? ''; +} + +// POST-Handling for Public Profile +if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['action']) && $_POST['action'] === 'update_public_profile') { + // ... (logic from turn 152, collapsed for brevity) ... + if (!isset($_POST['csrf_token_public_profile']) || !hash_equals($_SESSION['csrf_token_public_profile'] ?? '', $_POST['csrf_token_public_profile'])) { $_SESSION['error_message'] = "Invalid security token for public profile. Please try again."; unset($_SESSION['csrf_token_public_profile']); } + else { + unset($_SESSION['csrf_token_public_profile']); $bio = trim($_POST['bio'] ?? ''); $links_input = $_POST['links'] ?? []; $current_form_errors = []; + if (strlen($bio) > 1000) { $current_form_errors[] = "Bio cannot exceed 1000 characters."; } + $valid_links = []; foreach ($links_input as $key => $url) { $trimmed_url = trim($url); if (!empty($trimmed_url)) { if (!filter_var($trimmed_url, FILTER_VALIDATE_URL)) { $current_form_errors[] = "Invalid URL provided for " . htmlspecialchars(ucfirst(str_replace('_', ' ', $key))) . "."; } else { $valid_links[$key] = $trimmed_url; } } else { $valid_links[$key] = ''; } } + if (empty($current_form_errors)) { try { $stmt = $pdo->prepare('UPDATE users SET bio = ?, links = ? WHERE id = ?'); if ($stmt->execute([$bio, json_encode($valid_links), $_SESSION['user_id']])) { $_SESSION['success_message'] = "Public profile updated successfully."; } else { $_SESSION['error_message'] = "Failed to update public profile."; } } catch (PDOException $e) { error_log("Error updating public profile: " . $e->getMessage()); $_SESSION['error_message'] = "A database error occurred while updating public profile."; } } + else { $_SESSION['error_message'] = implode("
", $current_form_errors); } + } + header('Location: profile.php?tab=personal_info&subtab=public_profile'); exit; +} + +// POST-Handling for HR Information +if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['action']) && $_POST['action'] === 'update_hr_info') { + // ... (logic from turn 152, collapsed for brevity) ... + if (!isset($_POST['csrf_token_hr_info']) || !hash_equals($_SESSION['csrf_token_hr_info'] ?? '', $_POST['csrf_token_hr_info'])) { $_SESSION['error_message'] = "Invalid security token for HR information. Please try again."; unset($_SESSION['csrf_token_hr_info']); } + else { + unset($_SESSION['csrf_token_hr_info']); $hr_data_to_update = []; $hr_fields = ['job_title', 'department', 'employee_id', 'start_date', 'manager', 'work_location']; $current_form_errors = []; + foreach ($hr_fields as $field) { if (isset($_POST[$field])) { $value = trim($_POST[$field]); if ($field === 'start_date' && !empty($value) && !preg_match('/^\d{4}-\d{2}-\d{2}$/', $value)) { $current_form_errors[] = "Invalid Start Date format. Please use YYYY-MM-DD."; } $hr_data_to_update[$field] = !empty($value) ? $value : null; } } + if (empty($current_form_errors)) { if (!empty($hr_data_to_update)) { $set_clauses = []; foreach (array_keys($hr_data_to_update) as $col) { $set_clauses[] = "`" . str_replace('`', '``', $col) . "` = :$col"; } $sql = 'UPDATE users SET ' . implode(', ', $set_clauses) . ', updated_at = NOW() WHERE id = :id'; $hr_data_to_update['id'] = $_SESSION['user_id']; try { $stmt = $pdo->prepare($sql); if ($stmt->execute($hr_data_to_update)) { $_SESSION['success_message'] = "HR information updated successfully."; } else { $_SESSION['error_message'] = "Failed to update HR information."; } } catch (PDOException $e) { error_log("Error updating HR information: " . $e->getMessage()); $_SESSION['error_message'] = "A database error occurred while updating HR information."; } } else { $_SESSION['success_message'] = "HR information processed (no changes detected or submitted)."; } } + else { $_SESSION['error_message'] = implode("
", $current_form_errors); } + } + header('Location: profile.php?tab=personal_info&subtab=hr_information'); exit; +} + +// POST-Handling for Personal Data (Detailed) +if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['action']) && $_POST['action'] === 'update_personal_data') { + // ... (logic from turn 152, collapsed for brevity) ... + if (!isset($_POST['csrf_token_personal_data']) || !hash_equals($_SESSION['csrf_token_personal_data'] ?? '', $_POST['csrf_token_personal_data'])) { $_SESSION['error_message'] = "Invalid security token for personal data. Please try again."; unset($_SESSION['csrf_token_personal_data']); } + else { + unset($_SESSION['csrf_token_personal_data']); $personal_data_to_update = []; $personal_data_fields = ['first_name', 'last_name', 'dob', 'nationality', 'street', 'zip', 'city', 'country', 'phone', 'private_email']; $current_form_errors = []; + foreach ($personal_data_fields as $field) { if (isset($_POST[$field])) { $value = trim($_POST[$field]); if (($field === 'first_name' || $field === 'last_name') && empty($value)) { $current_form_errors[] = ucfirst(str_replace('_', ' ', $field)) . " cannot be empty."; } if ($field === 'dob' && !empty($value) && !preg_match('/^\d{4}-\d{2}-\d{2}$/', $value)) { $current_form_errors[] = "Invalid Date of Birth format. Please use YYYY-MM-DD."; } if ($field === 'private_email' && !empty($value) && !filter_var($value, FILTER_VALIDATE_EMAIL)) { $current_form_errors[] = "Invalid Private Email format."; } $personal_data_to_update[$field] = !empty($value) ? $value : null; } } + if (empty($current_form_errors)) { if (!empty($personal_data_to_update)) { $set_clauses = []; foreach (array_keys($personal_data_to_update) as $col) { $set_clauses[] = "`" . str_replace('`', '``', $col) . "` = :$col"; } $sql = 'UPDATE users SET ' . implode(', ', $set_clauses) . ', updated_at = NOW() WHERE id = :id'; $personal_data_to_update['id'] = $_SESSION['user_id']; try { $stmt = $pdo->prepare($sql); if ($stmt->execute($personal_data_to_update)) { $_SESSION['success_message'] = "Personal data updated successfully."; } else { $_SESSION['error_message'] = "Failed to update personal data."; } } catch (PDOException $e) { error_log("Error updating personal data: " . $e->getMessage()); $_SESSION['error_message'] = "A database error occurred while updating personal data."; } } else { $_SESSION['success_message'] = "Personal data processed (no changes detected or submitted)."; } } + else { $_SESSION['error_message'] = implode("
", $current_form_errors); } + } + header('Location: profile.php?tab=personal_info&subtab=personal_data'); exit; +} + +// POST-Handling for Change Password (Moved from profile_security.php) +if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['action']) && $_POST['action'] === 'change_password_profile') { + if (!isset($_POST['csrf_token_change_password_profile']) || !hash_equals($_SESSION['csrf_token_change_password_profile'] ?? '', $_POST['csrf_token_change_password_profile'])) { + $_SESSION['error_message'] = "Invalid security token. Please try again."; + unset($_SESSION['csrf_token_change_password_profile']); + } else { + unset($_SESSION['csrf_token_change_password_profile']); + + $currentPassword = $_POST['current_password'] ?? ''; + $newPassword = $_POST['new_password'] ?? ''; + $confirmNewPassword = $_POST['confirm_new_password'] ?? ''; + + $current_form_errors = []; + + if (empty($currentPassword) || empty($newPassword) || empty($confirmNewPassword)) { + $current_form_errors[] = "All password fields are required."; + } + if ($newPassword !== $confirmNewPassword) { + $current_form_errors[] = "New passwords do not match."; + } + if (strlen($newPassword) < 8) { $current_form_errors[] = "New password must be at least 8 characters long."; } + if (!preg_match('/[A-Z]/', $newPassword)) { $current_form_errors[] = "New password must contain at least one uppercase letter."; } + if (!preg_match('/[a-z]/', $newPassword)) { $current_form_errors[] = "New password must contain at least one lowercase letter."; } + if (!preg_match('/[0-9]/', $newPassword)) { $current_form_errors[] = "New password must contain at least one digit."; } + if (!preg_match('/[^A-Za-z0-9\s]/', $newPassword)) { $current_form_errors[] = "New password must contain at least one special character."; } + + if (empty($current_form_errors)) { + try { + $stmt_fetch = $pdo->prepare('SELECT password_hash FROM users WHERE id = ?'); + $stmt_fetch->execute([$_SESSION['user_id']]); + $user_data = $stmt_fetch->fetch(PDO::FETCH_ASSOC); + + if ($user_data && password_verify($currentPassword, $user_data['password_hash'])) { + $hashedNewPassword = password_hash($newPassword, PASSWORD_DEFAULT); + $stmt_update = $pdo->prepare('UPDATE users SET password_hash = ?, updated_at = NOW() WHERE id = ?'); + if ($stmt_update->execute([$hashedNewPassword, $_SESSION['user_id']])) { + $_SESSION['success_message'] = "Password updated successfully."; + } else { $_SESSION['error_message'] = "Failed to update password."; } + } else { $_SESSION['error_message'] = "Incorrect current password."; } + } catch (PDOException $e) { + error_log("Error changing password: " . $e->getMessage()); + $_SESSION['error_message'] = "A database error occurred while changing password. Please try again."; + } + } else { + $_SESSION['error_message'] = implode("
", $current_form_errors); + } + } + // Regenerate CSRF token for the security tab if errors occurred + if (!empty($_SESSION['error_message']) && empty($_SESSION['csrf_token_change_password_profile'])) { + $_SESSION['csrf_token_change_password_profile'] = bin2hex(random_bytes(32)); + } + header('Location: profile.php?tab=security'); + exit; +} + + +// POST-Handling für Finance-Tab (Add CSRF if this form is to be refactored here) +if ($_SERVER['REQUEST_METHOD'] === 'POST' && $activeTab === 'finance' && !isset($_POST['action'])) { + // ... (finance POST logic, collapsed for brevity) ... + $description = trim($_POST['description'] ?? ''); $type = $_POST['type'] ?? ''; $amount = $_POST['amount'] ?? ''; $entryDate = $_POST['entry_date'] ?? ''; + if ($description === '' || !in_array($type, ['income','expense'], true) || !is_numeric($amount) || empty($entryDate)) { $errors[] = 'Bitte alle Felder korrekt ausfüllen für den Finanz-Eintrag.'; } + else { + try { $stmt = $pdo->prepare("INSERT INTO finance_entries (user_id, type, amount, entry_date, note, currency) VALUES (?,?,?,?,?,'EUR')"); $stmt->execute([$_SESSION['user_id'], $type, $amount, $entryDate, $description]); $_SESSION['success_message'] = 'Finanz-Eintrag erfolgreich hinzugefügt.'; header('Location: profile.php?tab=finance'); exit; } + catch (PDOException $e) { error_log("Error adding finance entry: " . $e->getMessage()); $errors[] = "Ein Datenbankfehler ist aufgetreten beim Hinzufügen des Finanz-Eintrags."; } + } +} + +// Data fetching for GET requests and for re-displaying form with errors +$financeEntries = []; $totalIncome = 0.0; $totalExpense = 0.0; $balance = 0.0; +if ($activeTab === 'finance') { /* ... finance data fetching and delete ... */ } +$docs = []; $category_documents = []; $current_category_name = ''; +if ($activeTab === 'documents') { /* ... document data fetching and delete ... */ } + +try { + $stmtUser = $pdo->prepare('SELECT * FROM users WHERE id = ?'); + $stmtUser->execute([$_SESSION['user_id']]); + $user = $stmtUser->fetch(PDO::FETCH_ASSOC); + if (!$user) { header("Location: login.php"); exit; } +} catch (PDOException $e) { error_log("Error fetching user data for profile: " . $e->getMessage()); $errors[] = "Fehler beim Laden der Benutzerdaten."; $user = []; } + +require_once __DIR__ . '/../../templates/profile.php'; + +?> diff --git a/src/controllers/security.php b/src/controllers/security.php new file mode 100644 index 0000000..6a72eae --- /dev/null +++ b/src/controllers/security.php @@ -0,0 +1,22 @@ + diff --git a/templates/docs.php b/templates/docs.php new file mode 100644 index 0000000..61316ff --- /dev/null +++ b/templates/docs.php @@ -0,0 +1,95 @@ + + + + + + <?php echo htmlspecialchars($pageTitle ?? 'My Documents'); ?> | Private Vault + + + + + + + + +
+
+
+

+ + + + + + +
+ +

You have not uploaded any documents yet.

+ + Upload a document now + +
+ +
+ + + + + + + + + + + + + + + + + + + +
FilenameCategoryDate UploadedActions
+
+ + +
+
+ + + + + + View + + +
+
+ +
+
+
+ + diff --git a/templates/navbar.php b/templates/navbar.php index 4ed2ffe..8d92109 100644 --- a/templates/navbar.php +++ b/templates/navbar.php @@ -1,524 +1,530 @@ -= 2) { - return strtoupper(substr($names[0], 0, 1) . substr($names[1], 0, 1)); - } - return strtoupper(substr($user['username'], 0, 2)); -} -?> - - - - - - - - - -
-
-
-
-
- -
-
-

-

-
-
- -
- -
-
- - - - += 2) { + return strtoupper(substr($names[0], 0, 1) . substr($names[1], 0, 1)); + } + return strtoupper(substr($user['username'], 0, 2)); +} +?> + + + + + + + + + +
+
+
+
+
+ +
+
+

+

+
+
+ +
+ +
+
+ + + + diff --git a/templates/profile_tabs/documents/contracts.php b/templates/profile_tabs/documents/contracts.php index 211f2f4..97eb1f1 100644 --- a/templates/profile_tabs/documents/contracts.php +++ b/templates/profile_tabs/documents/contracts.php @@ -1,97 +1,112 @@ -prepare( - 'SELECT d.id, d.title, d.filename, d.end_date - FROM documents d - JOIN document_categories c ON c.id = d.category_id - WHERE d.user_id = ? AND c.name = "Verträge" AND d.is_deleted = 0 - ORDER BY d.upload_date DESC' -); -$stmt->execute([$userId]); -$docs = $stmt->fetchAll(PDO::FETCH_ASSOC); - -function isImg($f) { - return preg_match('/\.(png|jpe?g|gif|webp)$/i', $f); -} -?> - -
-
-

Meine Verträge

- -
- - - -

Keine Verträge gefunden.

- - - - - - - -
- - - - -
- -
PDF
- - -
-
- -
-
- -
- - -
+ + +
+
+

+ Meine +

+ +
+ + +

Keine gefunden.

+ + + +
+ + + +
+ +
+ +
+ +
+
+ +
+
+ +
+ +
diff --git a/templates/profile_tabs/documents/insurance.php b/templates/profile_tabs/documents/insurance.php index e113e87..b0eaffb 100644 --- a/templates/profile_tabs/documents/insurance.php +++ b/templates/profile_tabs/documents/insurance.php @@ -1,91 +1,101 @@ -prepare( - 'SELECT d.id, d.title, d.filename, d.end_date - FROM documents d - JOIN document_categories c ON c.id = d.category_id - WHERE d.user_id = ? - AND c.name = "Versicherungen" - AND d.is_deleted = 0 - ORDER BY d.upload_date DESC' -); -$stmt->execute([$userId]); -$docs = $stmt->fetchAll(PDO::FETCH_ASSOC); - -function isImg($f) { - return preg_match('/\.(png|jpe?g|gif|webp)$/i', $f); -} -?> - -
-
-

Meine Versicherungen

- -
- - - -

Keine Versicherungen gefunden.

- - - - - - - -
- - - - -
- -
PDF
- - -
-
- -
-
- -
- - -
+ + +
+
+

+ Meine +

+ +
+ + +

Keine gefunden.

+ + + +
+ + + +
+ +
+ +
+ +
+
+ +
+
+ +
+ +
diff --git a/templates/profile_tabs/documents/invoices.php b/templates/profile_tabs/documents/invoices.php index f420ee5..c6e9b67 100644 --- a/templates/profile_tabs/documents/invoices.php +++ b/templates/profile_tabs/documents/invoices.php @@ -1,91 +1,101 @@ -prepare(" - SELECT d.id, d.title, d.filename, d.end_date - FROM documents d - JOIN document_categories c ON c.id = d.category_id - WHERE d.user_id = ? - AND c.name = 'Rechnungen' - AND d.is_deleted = 0 - ORDER BY d.upload_date DESC -"); -$stmt->execute([$userId]); -$docs = $stmt->fetchAll(PDO::FETCH_ASSOC); - -function isImg($f) { - return preg_match('/\.(png|jpe?g|gif|webp)$/i', $f); -} -?> - -
-
-

Meine Rechnungen

- -
- - - -

Keine Rechnungen gefunden.

- - - - - - - -
- - - - -
- -
PDF
- - -
-
- -
-
- -
- - -
+ + +
+
+

+ Meine +

+ +
+ + +

Keine gefunden.

+ + + +
+ + + +
+ +
+ +
+ +
+
+ +
+
+ +
+ +
diff --git a/templates/profile_tabs/documents/other_docs.php b/templates/profile_tabs/documents/other_docs.php index b44ff66..b5deb95 100644 --- a/templates/profile_tabs/documents/other_docs.php +++ b/templates/profile_tabs/documents/other_docs.php @@ -1,91 +1,101 @@ -prepare( - 'SELECT d.id, d.title, d.filename, d.end_date - FROM documents d - JOIN document_categories c ON c.id = d.category_id - WHERE d.user_id = ? - AND c.name = ? - AND d.is_deleted = 0 - ORDER BY d.upload_date DESC' -); -$stmt->execute([$userId, $_GET['category'] ?? 'Sonstige']); -$docs = $stmt->fetchAll(PDO::FETCH_ASSOC); - -function isImg($f) { - return preg_match('/\.(png|jpe?g|gif|webp)$/i', $f); -} -?> - -
-
-

- -
- - - -

Keine sonstigen Dokumente gefunden.

- - - - - - - -
- - - - -
- -
PDF
- - -
-
- -
-
- -
- - -
+ + +
+
+

+ +

+ +
+ + +

Keine gefunden.

+ + + +
+ + + +
+ +
+ +
+ +
+
+ +
+
+ +
+ +
diff --git a/templates/profile_tabs/personal_info/hr_information.php b/templates/profile_tabs/personal_info/hr_information.php index 1098b19..7cc11db 100644 --- a/templates/profile_tabs/personal_info/hr_information.php +++ b/templates/profile_tabs/personal_info/hr_information.php @@ -1,70 +1,80 @@ - -
-
-
-

HR Information

-

Berufliche und arbeitsrelevante Informationen.

-
- -
- - -
- -
- - -
- - -
- - -
- - -
- - -
- - -
- - -
- - -
- - -
- - -
- - -
-
- -
- -
-
-
-
+ + +
+
+
+

HR Information

+

Berufliche und arbeitsrelevante Informationen.

+
+ + + +
+ + + +
+ +
+ + +
+ + +
+ + +
+ + +
+ + +
+ + +
+ + +
+ + +
+ + +
+ + +
+ + +
+
+ +
+ +
+
+
+
diff --git a/templates/profile_tabs/personal_info/personal_data.php b/templates/profile_tabs/personal_info/personal_data.php index d55cda0..9f88352 100644 --- a/templates/profile_tabs/personal_info/personal_data.php +++ b/templates/profile_tabs/personal_info/personal_data.php @@ -1,77 +1,90 @@ - - -
-

Persönliche Daten

- - -
- -
- - -
- -
- - -
- - - -
-
- - -
-
- - -
- -
- - -
-
- - -
-
- - -
- Adresse - -
- - -
- -
- - -
- Kontakt - - -
- - -
-
+ + +
+

Persönliche Daten

+ + + +
+ + + + +
+ Grunddaten +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+
+ + +
+ Adresse +
+ + +
+
+
+ + +
+
+ + +
+
+
+ + +
+
+ + +
+ Kontakt +
+ + +
+
+ + +
+
+ +
+ +
+
+
diff --git a/templates/profile_tabs/personal_info/personal_info.php b/templates/profile_tabs/personal_info/personal_info.php index 511e5ba..50197eb 100644 --- a/templates/profile_tabs/personal_info/personal_info.php +++ b/templates/profile_tabs/personal_info/personal_info.php @@ -1,70 +1,87 @@ - -
-

Personal Info

- - -
- -
- - -
- -
- - -
-
-
- - -
-
- - -
-
- -
-
- - -
-
- - -
-
- -
-
- - -
-
- - -
-
+ + +
+

Personal Info

+ + + + + + + + +
+ + + +
+
+ + +
+
+ + +
+
+ +
+
+ + +
+
+ + +
+
+ +
+
+ + +
+
+ +
+ +
+
+
diff --git a/templates/profile_tabs/personal_info/public_profile.php b/templates/profile_tabs/personal_info/public_profile.php index fd29924..b3973d3 100644 --- a/templates/profile_tabs/personal_info/public_profile.php +++ b/templates/profile_tabs/personal_info/public_profile.php @@ -1,52 +1,67 @@ - -
-
-

Public Profile

-

Diese Informationen sind für andere Benutzer sichtbar.

-
- - -
-

-
- - -
- - - -
- - -
- - -
- - -
- -
- - -
- -
-
- -
- -
-
-
+ +
+
+

Public Profile

+

Diese Informationen sind für andere Benutzer sichtbar.

+
+ + + +
+ + + + +
+ + +
+ + +
+ + 'LinkedIn', + 'twitter_x' => 'Twitter/X', + 'xing' => 'Xing', + 'github' => 'GitHub', + 'website' => 'Website' + // Add other link types here if needed, and ensure controller handles them + ]; + ?> +
+ $label): ?> +
+ + +
+ +
+
+ +
+ +
+
+
diff --git a/templates/profile_tabs/security.php b/templates/profile_tabs/security.php index deba6d1..7080ccb 100644 --- a/templates/profile_tabs/security.php +++ b/templates/profile_tabs/security.php @@ -1,70 +1,76 @@
-

Sicherheitseinstellungen

+

Sicherheitseinstellungen

Verwalten Sie Ihr Passwort und Sicherheitsoptionen.

+ + -
-

Passwort ändern

-
- +
+

Passwort ändern

+ + +
- - + +
- - + +
- - + +
- +
+ +
-
-

Zwei-Faktor-Authentifizierung

+
+

Zwei-Faktor-Authentifizierung

Erhöhen Sie die Sicherheit Ihres Accounts mit 2FA.

-
+
2FA Status: - Deaktiviert + Deaktiviert
-
- -
-

Aktive Sessions

+ +
+

Aktive Sessions

-
+

Aktuelle Session

Chrome auf Windows •

- Aktiv + Aktiv
+
-
diff --git a/templates/security.php b/templates/security.php new file mode 100644 index 0000000..47a459a --- /dev/null +++ b/templates/security.php @@ -0,0 +1,66 @@ + + + + + + <?php echo htmlspecialchars($pageTitle ?? 'Security Settings'); ?> | Private Vault + + + + + + + +
+
+
+

+
+ +
+ + +
+

Change Password

+

Secure your account by regularly changing your password.

+ + Change Password + +
+ + +
+

Two-Factor Authentication (2FA)

+

Add an extra layer of security to your account. With 2FA, you'll need your password and a code from an authenticator app to log in.

+
+

This feature is planned for future implementation.

+
+
+ + +
+
+
+ +