Files
2026-03-20 17:13:38 +01:00

477 lines
16 KiB
PHP
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE HTML>
<!--
Alpha by HTML5 UP
html5up.net | @n33co
Free for personal and commercial use under the CCA 3.0 license (html5up.net/license)
-->
<html>
<head>
<?php
include('header.php');
?>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Kurzbewerbung Praxis Creutzburg</title>
<style>
:root { --brand:#0f5585; --accent:#ff6347; }
body{font-family:system-ui,-apple-system,Segoe UI,Roboto,Arial,sans-serif;background:#f7f7f8;margin:0}
.wrap{max-width:580px;margin:0 auto;padding:16px 18px 28px}
.card{background:#fff;border-radius:12px;box-shadow:0 8px 24px rgba(0,0,0,.06);padding:18px}
h1{font-size:1.4rem;margin:6px 0 14px;color:#222}
fieldset{border:0;padding:0;margin:0 0 14px}
legend{font-weight:700;margin-bottom:8px;color:#222}
label{display:block;font-weight:600;margin:10px 0 6px}
input[type="text"],input[type="email"],input[type="tel"],input[type="date"],select{
width:100%;padding:12px 13px;border:1px solid #d6d6db;border-radius:10px;font-size:16px;box-sizing:border-box;background:#fff
}
.hint{font-size:.88rem;color:#666;margin-top:4px}
.grid{display:grid;gap:10px}
.grid-2{grid-template-columns:1fr 1fr}
.chips{display:flex;flex-wrap:wrap;gap:8px}
.chip{position:relative}
.chip input{position:absolute;opacity:0;inset:0;cursor:pointer}
.chip span{display:inline-block;border:1px solid #d6d6db;border-radius:999px;padding:9px 12px;background:#fff}
.chip input:checked + span{background:#e9f3fa;border-color:#9ec9e6;color:#0f5585;font-weight:700}
.actions{margin-top:12px}
button{width:100%;padding:14px 16px;border:0;border-radius:12px;background:var(--accent);color:#fff;font-size:17px;font-weight:700}
button:active{transform:translateY(1px)}
.req{color:#d33;font-weight:700}
@media (min-width:640px){ h1{font-size:1.6rem} }
/* Honeypot (Spam-Schutz) */
.hp{position:absolute;left:-99999px;opacity:0}
</style>
<link rel="stylesheet" href="css/formulare.css" />
</head>
<body >
<!-- Header -->
<header id="header" class="../skel-layers-fixed">
<?php
include('menu.php');
include_once("inc/config.inc.php");
include_once("inc/functions.inc.php");
include_once('inc/functions.impfen.inc.php');
include_once('inc/functions.formulare.inc.php');
?>
</header>
<!-- Main -->
<section id="main" class="container">
<?php
echo showHeaderpraxis();
?>
<section class="box special">
<h2>Kurzbewerbung</h2>
<?php
if(isset($_POST["aktion"])){
if($_POST["aktion"] == "1"){
define('DEBUG_BWERB', true);
// ==== Sicherheits-/Validierungshilfen ====
function in_post($key, $default = '') { return $_POST[$key] ?? $default; }
function norm_str(string $s, int $max = 255): string {
$s = trim($s);
if (mb_strlen($s) > $max) $s = mb_substr($s, 0, $max);
return $s;
}
function norm_phone(string $s): string {
$s = preg_replace('/[^\d+()\s-]/', '', $s ?? '');
return norm_str($s, 40);
}
function norm_email(string $s): string {
$s = filter_var(trim($s), FILTER_SANITIZE_EMAIL);
if (!filter_var($s, FILTER_VALIDATE_EMAIL)) return '';
return $s;
}
function join_array(array $a, int $maxLen = 400): string {
$a = array_map(fn($v) => norm_str((string)$v, 60), $a);
$s = implode(', ', array_filter($a, fn($v) => $v !== ''));
return norm_str($s, $maxLen);
}
function norm_date(?string $s): ?string {
if (!$s) return null;
$s = trim($s);
// Erlaubt: JJJJ-MM-TT
if (preg_match('/^\d{4}-\d{2}-\d{2}$/', $s)) {
$ts = strtotime($s);
}
// Erlaubt: TT.MM.JJJJ
elseif (preg_match('/^\d{2}\.\d{2}\.\d{4}$/', $s)) {
[$d,$m,$y] = explode('.', $s);
$ts = strtotime("$y-$m-$d");
} else {
return null;
}
if ($ts === false) return null;
// Plausibilitätscheck (1900 bis heute)
$min = strtotime('1900-01-01');
$max = strtotime('today');
if ($ts < $min || $ts > $max) return null;
return date('Y-m-d', $ts); // DB-Format
}
// ==== POST-Daten einlesen & validieren ====
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
http_response_code(405); exit('Method not allowed');
}
// Pflichtfelder
$vorname = norm_str(in_post('vorname'));
$nachname = norm_str(in_post('nachname'));
$email = norm_email(in_post('email'));
$phone = norm_phone(in_post('phone'));
$position = norm_str(in_post('position'));
$geburtstag = norm_date(in_post('geburtstag')); // null oder 'YYYY-MM-DD'
if (!$vorname || !$nachname || !$email || !$phone || !$position) {
http_response_code(400);
exit('Bitte alle Pflichtfelder ausfüllen (Vorname, Nachname, E-Mail, Telefon, Stelle).');
}
// Optionale Kontaktangaben
$plz = norm_str(in_post('plz'), 10);
$ort = norm_str(in_post('ort'), 80);
$strasse = norm_str(in_post('strasse'), 120);
// Whitelists (verhindert beliebigen Input)
$allowedPositions = ['MFA (Teilzeit)', 'MFA (Vollzeit)', 'Ausbildung MFA', 'Initiativbewerbung'];
if (!in_array($position, $allowedPositions, true)) {
http_response_code(400); exit('Ungültige Stellenwahl.');
}
$allowedVerf = ['sofort', '1-2 Monate', '3 Monate', '3-6 Monate', '>6 Monate'];
$verf = in_post('verfuegbarkeit', '');
if (!in_array($verf, $allowedVerf, true)) $verf = 'keine Angabe';
// Mehrfachauswahl-Felder
$erfahrung = [];
if (isset($_POST['erfahrung']) && is_array($_POST['erfahrung'])) $erfahrung = $_POST['erfahrung'];
$erfahrungJoined = join_array($erfahrung);
$wichtig = [];
if (isset($_POST['wichtig']) && is_array($_POST['wichtig'])) $wichtig = $_POST['wichtig'];
$wichtigJoined = join_array($wichtig);
$kurzmsg = norm_str(in_post('nachricht'), 400);
// Beschreibung (kommt gesammelt in anfragen.nachricht)
$beschreibung = implode("<br>", array_filter([
"Bewerbung {$position}",
"Stelle: {$position}",
"Erfahrung: " . ($erfahrungJoined ?: 'keine Angabe'),
"Wichtig ist mir: " . ($wichtigJoined ?: 'keine Angabe'),
"Verfügbarkeit: {$verf}",
$kurzmsg ? "Nachricht: {$kurzmsg}" : null
]));
// Anforderungsart
$anforderungart = 19;
// Hash für Dublettenprüfung (optional)
$hashBasis = $vorname . $nachname . $email;
$hash = md5($hashBasis) . date("YmdHs");
// ==== DB-Operationen (PDO + Transaktion) ====
try {
$pdo->beginTransaction();
// 1) USER finden oder anlegen
if ($geburtstag) {
$stmt = $pdo->prepare("
SELECT userid FROM user
WHERE vorname = :vorname AND nachname = :nachname AND mail = :email AND geburtstag = :geb
LIMIT 1
");
$stmt->execute([':vorname'=>$vorname, ':nachname'=>$nachname, ':email'=>$email, ':geb'=>$geburtstag]);
} else {
$stmt = $pdo->prepare("
SELECT userid FROM user
WHERE vorname = :vorname AND nachname = :nachname AND mail = :email
LIMIT 1
");
$stmt->execute([':vorname'=>$vorname, ':nachname'=>$nachname, ':email'=>$email]);
}
$uid = $stmt->fetchColumn();
if (!$uid) {
// neu anlegen
$ins = $pdo->prepare("
INSERT INTO user (vorname, nachname, geburtstag, mail, tele, ort, plz, strasse)
VALUES (:vorname, :nachname, :geburtstag, :mail, :tele, :ort, :plz, :strasse)
");
$ins->execute([
':vorname'=>$vorname, ':nachname'=>$nachname, ':geburtstag'=>$geburtstag,
':mail'=>$email, ':tele'=>$phone, ':ort'=>$ort, ':plz'=>$plz, ':strasse'=>$strasse
]);
$uid = (int)$pdo->lastInsertId();
} else {
// updaten (Geburtsdatum nur setzen/überschreiben, wenn vorhanden)
$upd = $pdo->prepare("
UPDATE user
SET tele = :tele, ort = :ort, plz = :plz, strasse = :strasse
".($geburtstag ? ", geburtstag = :geburtstag " : "")."
WHERE userid = :uid
");
$params = [
':tele'=>$phone, ':ort'=>$ort, ':plz'=>$plz, ':strasse'=>$strasse, ':uid'=>$uid
];
if ($geburtstag) $params[':geburtstag'] = $geburtstag;
$upd->execute($params);
}
// 2) Dublettenprüfung (7 Tage, gleicher Typ + nahezu gleiche Nachricht)
$dup = $pdo->prepare("
SELECT anfrageid FROM anfragen
WHERE personid = :uid
AND anforderungart = :art
AND nachricht = :txt
AND create_time >= DATE_SUB(CURDATE(), INTERVAL 7 DAY)
LIMIT 1
");
$dup->execute([':uid'=>$uid, ':art'=>$anforderungart, ':txt'=>$beschreibung]);
if ($dup->fetchColumn()) {
$pdo->commit();
echo "<h3>Bereits vorhanden</h3><br>Eine sehr ähnliche Bewerbung liegt aus den letzten 7 Tagen bereits vor. Wir melden uns zeitnah bei Ihnen.<br>";
header("refresh:12;formulare.php");
exit;
}
// 3) Bewerbung speichern (ordnungsid ggf. an euer System anpassen)
$insA = $pdo->prepare("
INSERT INTO anfragen (personid, anforderungart, nachricht, create_time, hash, ordnungsid)
VALUES (:uid, :art, :txt, NOW(), :hash, :ord)
");
$insA->execute([
':uid'=>$uid,
':art'=>$anforderungart,
':txt'=>$beschreibung,
':hash'=>$hash,
':ord'=>5 // z. B. 5 = „Bewerbung“; bei euch anpassen, falls nötig
]);
$anfrageid = (int)$pdo->lastInsertId();
$pdo->commit();
// Optional: Bestätigungsmail via eurer Vorlage
SendMailMessageVorlage($pdo, "4", $anfrageid , "48");
echo "<h3>Vielen Dank!</h3><br>Deine Bewerbung wurde gespeichert. Wir melden uns zeitnah bei Dir.<br>";
header("refresh:12;formulare.php");
} catch (Throwable $e) {
if (isset($pdo) && $pdo->inTransaction()) { $pdo->rollBack(); }
error_log('[Bewerbung] '.$e->getMessage().' | Code: '.$e->getCode()); // in Webserver-Log
if (defined('DEBUG_BWERB') && DEBUG_BWERB) {
http_response_code(500);
echo "<pre>DB-Fehler: ".$e->getMessage()."\nCode: ".$e->getCode()."</pre>";
} else {
http_response_code(500);
echo "Es ist ein Fehler aufgetreten. Bitte versuchen Sie es später erneut.";
}
}
}
}else{
?>
<div class="wrap">
<div class="card">
<form action="kurzbewerbung.php" method="POST" novalidate>
<!-- Spam-Honeypot -->
<div class="hp">
<label>Ihre Webseite (leer lassen)</label>
<input type="text" name="website">
<input type="hidden" name="aktion" value="1">
</div>
<fieldset>
<label for="position">Für welche Stelle bewirbst du dich? <span class="req">*</span></label>
<select id="position" name="position" required>
<option value="">Bitte auswählen</option>
<option>MFA (Teilzeit)</option>
<option>MFA (Vollzeit)</option>
<option>Ausbildung MFA</option>
<option>Initiativbewerbung</option>
</select>
</fieldset>
<fieldset>
<legend>Welche Erfahrung hast du? (Mehrfachauswahl möglich)</legend>
<div class="chips">
<label class="chip"><input type="checkbox" name="erfahrung[]" value="Arztpraxis"><span>Arztpraxis</span></label>
<label class="chip"><input type="checkbox" name="erfahrung[]" value="Labor"><span>Labor</span></label>
<label class="chip"><input type="checkbox" name="erfahrung[]" value="EDV / Praxissoftware"><span>EDV / Praxissoftware</span></label>
<label class="chip"><input type="checkbox" name="erfahrung[]" value="Empfang / Telefon"><span>Empfang / Telefon</span></label>
<label class="chip"><input type="checkbox" name="erfahrung[]" value="Abrechnung"><span>Abrechnung</span></label>
<label class="chip"><input type="checkbox" name="erfahrung[]" value="Blutentnahme"><span>Blutentnahme</span></label>
<label class="chip"><input type="checkbox" name="erfahrung[]" value="Impfungen"><span>Impfungen</span></label>
<label class="chip"><input type="checkbox" name="erfahrung[]" value="Noch keine"><span>Noch keine</span></label>
</div>
</fieldset>
<fieldset>
<legend>Welche Punkte im Arbeitsumfeld sind dir besonders wichtig? (Mehrfachauswahl möglich)</legend>
<div class="chips">
<label class="chip"><input type="checkbox" name="wichtig[]" value="Teamkultur"><span>Teamkultur</span></label>
<label class="chip"><input type="checkbox" name="wichtig[]" value="Flexible Zeiten"><span>Flexible Zeiten</span></label>
<label class="chip"><input type="checkbox" name="wichtig[]" value="Fortbildung"><span>Fortbildung</span></label>
<label class="chip"><input type="checkbox" name="wichtig[]" value="Moderne IT / papierlos"><span>Moderne IT / papierlos</span></label>
<label class="chip"><input type="checkbox" name="wichtig[]" value="Flache Hierarchien"><span>Flache Hierarchien</span></label>
<label class="chip"><input type="checkbox" name="wichtig[]" value="Eigenverantwortung"><span>Eigenverantwortung</span></label>
<label class="chip"><input type="checkbox" name="wichtig[]" value="Planbare Dienste"><span>Planbare Dienste</span></label>
</div>
</fieldset>
<fieldset>
<legend>Ab wann wärst du für die neue Stelle verfügbar?</legend>
<div class="chips">
<label class="chip">
<input type="radio" name="verfuegbarkeit" value="sofort" required>
<span>Sofort</span>
</label>
<label class="chip">
<input type="radio" name="verfuegbarkeit" value="1-2 Monate">
<span>12 Monate</span>
</label>
<label class="chip">
<input type="radio" name="verfuegbarkeit" value="3 Monate">
<span>3 Monate</span>
</label>
<label class="chip">
<input type="radio" name="verfuegbarkeit" value="3-6 Monate">
<span>36 Monate</span>
</label>
<label class="chip">
<input type="radio" name="verfuegbarkeit" value=">6 Monate">
<span>&gt; 6 Monate</span>
</label>
</div>
</fieldset>
<fieldset>
<label for="nachricht">Kurze Nachricht (optional)</label>
<textarea id="nachricht" name="nachricht" type="text" placeholder="z. B. Fragen, weitere Informationen"></textarea>
</fieldset>
<fieldset class="grid grid-2">
<div>
<label for="vorname">Vorname <span class="req">*</span></label>
<input id="vorname" name="vorname" type="text" autocomplete="given-name" required />
</div>
<div>
<label for="nachname">Nachname <span class="req">*</span></label>
<input id="nachname" name="nachname" type="text" autocomplete="family-name" required />
</div>
<div>
<label for="geburtstag">Geburtsdatum <span class="req">*</span></label>
<input id="geburtstag" name="geburtstag" type="date" />
<div class="hint">Format: TT.MM.JJJJ oder JJJJ-MM-TT</div>
</div>
</fieldset>
<fieldset class="grid">
<div class="grid grid-2">
<div>
<label for="email">E-Mail <span class="req">*</span></label>
<input id="email" name="email" type="email" inputmode="email" autocomplete="email" required />
</div>
<div>
<label for="phone">Telefon <span class="req">*</span></label>
<input id="phone" name="phone" type="tel" inputmode="tel" autocomplete="tel" required />
</div>
</div>
<div class="grid grid-2">
<div>
<label for="plz">PLZ <span class="req">*</span></label>
<input id="plz" name="plz" type="text" inputmode="numeric" autocomplete="postal-code" required />
</div>
<div>
<label for="ort">Ort <span class="req">*</span></label>
<input id="ort" name="ort" type="text" autocomplete="address-level2" required />
</div>
</div>
<div>
<label for="strasse">Straße & Nr. <span class="req">*</span></label>
<input id="strasse" name="strasse" type="text" autocomplete="address-line1" required />
</div>
</fieldset>
<fieldset>
<label>
Ich habe die Datenschutzhinweise gelesen und stimme der Kontaktaufnahme zu.
</label>
</fieldset>
<div class="actions">
<button type="submit">Jetzt bewerben</button>
</div>
</form>
</div>
</div>
<script>
// Verfügbarkeit: Datum nur zeigen, wenn „Ab Datum“ gewählt
const radios = document.querySelectorAll('input[name="verf_typ"]');
const wrap = document.getElementById('verf_datum_wrap');
radios.forEach(r => r.addEventListener('change', () => {
wrap.style.display = (document.querySelector('input[name="verf_typ"]:checked').value === 'ab_datum') ? 'block' : 'none';
}));
</script>
<?php
}
?>
</div>
</div>
</section>
<?php
include_once('footer.php');
?>
</body>
</html>