Vor dem Generieren waehlen: Anschreiben, Lebenslauf oder beides

Auf der Bewerbungsseite laesst sich jetzt auswaehlen, welche Unterlagen die KI
erzeugt. Standard bleibt beides; die letzte Auswahl wird gemerkt und ist beim
naechsten Generieren vorbelegt. Ohne Haken bricht das Formular ab statt still
beides zu erzeugen.

Nicht gewaehlte Dokumente werden gar nicht erst angefragt: JSON-Schema und
Skelett im Prompt werden auf die gewuenschten Teile reduziert, das spart einen
Gutteil der Generierungszeit. Gerendert wird ebenfalls nur das Gewaehlte - auch
wenn das Modell sich nicht an das Schema haelt und trotzdem alles liefert.

Fuer den E-Mail-Versand mitgedacht:
- Wird kein Lebenslauf erzeugt, fuehrt ihn das Anschreiben nicht mehr unter
  "Anlagen" auf. Sonst kuendigt der Brief eine Anlage an, die nie mitgeht.
- Der Prompt bekommt zusaetzlich die Liste der Dateien, die der Bewerbungsmail
  tatsaechlich anhaengen (inkl. Anschreiben selbst), damit der Begleittext keine
  Unterlagen nennt, die nicht dabei sind.
- Die Anhang-Checkboxen im Mailformular ziehen sich aus den erzeugten Anhaengen,
  greifen also automatisch.

Die REST-API kennt das Feld ebenfalls (POST .../generate, "dokumente"), inkl.
OpenAPI-Doku.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-07-13 02:18:02 +02:00
co-authored by Claude Opus 4.8
parent 66366659d2
commit d1116d522d
5 changed files with 223 additions and 51 deletions
+60 -2
View File
@@ -326,8 +326,9 @@
<!-- LLM notes + generate/regenerate -->
<form action="/bewerbung/<%= application.id %>/generieren" method="POST"
class="mt-6 border-t border-gray-200 dark:border-gray-700 pt-5"
<% if (genStatus === 'fertig') { %>onsubmit="return confirm('Unterlagen neu generieren? Vorhandene generierte Dateien werden ersetzt.');"<% } %>>
id="generierenForm"
data-bestaetigen="<%= genStatus === 'fertig' ? '1' : '' %>"
class="mt-6 border-t border-gray-200 dark:border-gray-700 pt-5">
<label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">
Notizen für die KI
</label>
@@ -339,6 +340,32 @@
class="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md bg-white dark:bg-gray-700 text-gray-800 dark:text-white leading-relaxed"
placeholder="z. B.&#10;Musterfirma GmbH&#10;Musterstraße 12&#10;45128 Essen&#10;Ansprechpartner: Frau Müller"><%= application.llm_notizen || '' %></textarea>
<!-- Which documents to generate (both by default). -->
<div class="mt-4" id="dokumentAuswahl">
<label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">Was soll generiert werden?</label>
<p class="text-xs text-gray-500 dark:text-gray-400 mb-2">
Standardmäßig werden Anschreiben und Lebenslauf erstellt. Wird der Lebenslauf abgewählt,
führt ihn das Anschreiben auch nicht mehr unter „Anlagen“ auf.
</p>
<div class="flex flex-wrap gap-4">
<label class="flex items-center gap-2 text-sm text-gray-700 dark:text-gray-300">
<input type="checkbox" name="dokument" value="anschreiben" data-dokument
<%= dokumentAuswahl.includes('anschreiben') ? 'checked' : '' %>
class="rounded border-gray-300 dark:border-gray-600">
Anschreiben
</label>
<label class="flex items-center gap-2 text-sm text-gray-700 dark:text-gray-300">
<input type="checkbox" name="dokument" value="lebenslauf" data-dokument
<%= dokumentAuswahl.includes('lebenslauf') ? 'checked' : '' %>
class="rounded border-gray-300 dark:border-gray-600">
Lebenslauf
</label>
</div>
<p class="text-xs text-red-600 dark:text-red-400 mt-2 hidden" id="dokumentHinweis">
Bitte mindestens ein Dokument auswählen.
</p>
</div>
<!-- Optional extra attachments to enclose (none by default). -->
<div class="mt-4">
<label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">Zusätzliche Anlagen</label>
@@ -913,6 +940,37 @@
}, 4000);
}
})();
// Generation form: require at least one document, and keep the
// "replace existing files" confirmation when regenerating.
(function () {
const form = document.getElementById('generierenForm');
if (!form) return;
const boxes = Array.from(form.querySelectorAll('[data-dokument]'));
const hinweis = document.getElementById('dokumentHinweis');
form.addEventListener('submit', function (e) {
const gewaehlt = boxes.filter((b) => b.checked);
if (!gewaehlt.length) {
e.preventDefault();
if (hinweis) hinweis.classList.remove('hidden');
return;
}
if (form.dataset.bestaetigen === '1') {
const was = gewaehlt.length === 2
? 'Anschreiben und Lebenslauf'
: (gewaehlt[0].value === 'anschreiben' ? 'das Anschreiben' : 'der Lebenslauf');
if (!confirm('Es ' + (gewaehlt.length === 2 ? 'werden ' : 'wird ') + was
+ ' neu generiert. Vorhandene generierte Dateien werden ersetzt. Fortfahren?')) {
e.preventDefault();
}
}
});
boxes.forEach((b) => b.addEventListener('change', function () {
if (hinweis && boxes.some((x) => x.checked)) hinweis.classList.add('hidden');
}));
})();
</script>
</body>
</html>