477 lines
16 KiB
PHP
477 lines
16 KiB
PHP
<!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>1–2 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>3–6 Monate</span>
|
||
</label>
|
||
<label class="chip">
|
||
<input type="radio" name="verfuegbarkeit" value=">6 Monate">
|
||
<span>> 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>
|