This commit is contained in:
2026-07-15 08:57:41 +02:00
parent 6a4c576bde
commit a4d857fcec
2 changed files with 10 additions and 10 deletions
+6 -6
View File
@@ -10,7 +10,7 @@
<main> <main>
<header> <header>
<h1>Service-Ticket anlegen</h1> <h1>Service-Ticket anlegen</h1>
<p>Zuerst den Kunden waehlen, dann das Anliegen erfassen. Das Ticket landet direkt in Redmine.</p> <p>Zuerst den Kunden wählen, dann das Anliegen erfassen. Das Ticket landet direkt in Redmine.</p>
</header> </header>
<section class="step" id="stepCustomer"> <section class="step" id="stepCustomer">
@@ -27,7 +27,7 @@
<div class="customer-chip" id="customerChip"> <div class="customer-chip" id="customerChip">
<span class="cnum" id="chipNumber"></span> <span class="cnum" id="chipNumber"></span>
<span class="cname" id="chipName"></span> <span class="cname" id="chipName"></span>
<button type="button" id="chipReset">Aendern</button> <button type="button" id="chipReset">Ändern</button>
</div> </div>
</section> </section>
@@ -35,7 +35,7 @@
<div class="step-label"><span class="num">2</span> Anliegen</div> <div class="step-label"><span class="num">2</span> Anliegen</div>
<label for="subject">Betreff</label> <label for="subject">Betreff</label>
<input type="text" id="subject" maxlength="200" placeholder="Kurze Zusammenfassung der Stoerung"> <input type="text" id="subject" maxlength="200" placeholder="Kurze Zusammenfassung der Störung">
<label for="description">Beschreibung</label> <label for="description">Beschreibung</label>
<textarea id="description" placeholder="Was ist passiert? Fehlermeldungen, betroffene Systeme, Ansprechpartner ..."></textarea> <textarea id="description" placeholder="Was ist passiert? Fehlermeldungen, betroffene Systeme, Ansprechpartner ..."></textarea>
@@ -46,7 +46,7 @@
<div class="feedback" id="feedback"></div> <div class="feedback" id="feedback"></div>
</section> </section>
<footer>Der Kundenbezug wird serverseitig gegen die Stammdaten geprueft, bevor das Ticket erstellt wird.</footer> <footer>Der Kundenbezug wird serverseitig gegen die Stammdaten geprüft, bevor das Ticket erstellt wird.</footer>
</main> </main>
<script> <script>
@@ -87,7 +87,7 @@
if (currentResults.length === 0) { if (currentResults.length === 0) {
const empty = document.createElement("div"); const empty = document.createElement("div");
empty.className = "suggestion-empty"; empty.className = "suggestion-empty";
empty.textContent = "Kein Kunde gefunden. Nummer und Schreibweise pruefen."; empty.textContent = "Kein Kunde gefunden. Nummer und Schreibweise prüfen.";
suggestionsBox.appendChild(empty); suggestionsBox.appendChild(empty);
} else { } else {
currentResults.forEach((customer, index) => { currentResults.forEach((customer, index) => {
@@ -207,7 +207,7 @@
} }
} catch (error) { } catch (error) {
feedback.className = "feedback error"; feedback.className = "feedback error";
feedback.textContent = "Server nicht erreichbar. Bitte spaeter erneut versuchen."; feedback.textContent = "Server nicht erreichbar. Bitte später erneut versuchen.";
} finally { } finally {
submitButton.textContent = "Ticket anlegen"; submitButton.textContent = "Ticket anlegen";
updateSubmitState(); updateSubmitState();
+4 -4
View File
@@ -16,7 +16,7 @@ const config = {
customersFile: process.env.CUSTOMERS_FILE || path.join(__dirname, "data", "customers.csv"), customersFile: process.env.CUSTOMERS_FILE || path.join(__dirname, "data", "customers.csv"),
}; };
// Ohne API-Key laeuft der Server im Trockenlauf: Tickets werden nur simuliert. // Ohne API-Key läuft der Server im Trockenlauf: Tickets werden nur simuliert.
const dryRun = config.redmineApiKey === ""; const dryRun = config.redmineApiKey === "";
// --- Kundenstammdaten laden (CSV: Kundennummer;Firmenname) --- // --- Kundenstammdaten laden (CSV: Kundennummer;Firmenname) ---
@@ -97,7 +97,7 @@ const app = express();
app.use(express.json()); app.use(express.json());
app.use(express.static(path.join(__dirname, "public"))); app.use(express.static(path.join(__dirname, "public")));
// GET /api/customers?search=... -> Trefferliste fuer das Autocomplete // GET /api/customers?search=... -> Trefferliste für das Autocomplete
app.get("/api/customers", (request, response) => { app.get("/api/customers", (request, response) => {
const query = String(request.query.search || "").trim(); const query = String(request.query.search || "").trim();
if (query.length < 2) { if (query.length < 2) {
@@ -113,7 +113,7 @@ app.post("/api/tickets", async (request, response) => {
const customer = customersByNumber.get(String(customerNumber || "").trim()); const customer = customersByNumber.get(String(customerNumber || "").trim());
if (!customer) { if (!customer) {
return response.status(422).json({ error: "Unbekannte Kundennummer. Bitte einen Kunden aus der Vorschlagsliste waehlen." }); return response.status(422).json({ error: "Unbekannte Kundennummer. Bitte einen Kunden aus der Vorschlagsliste wählen." });
} }
if (!subject || String(subject).trim().length < 5) { if (!subject || String(subject).trim().length < 5) {
return response.status(422).json({ error: "Der Betreff muss mindestens 5 Zeichen lang sein." }); return response.status(422).json({ error: "Der Betreff muss mindestens 5 Zeichen lang sein." });
@@ -150,5 +150,5 @@ app.use((error, request, response, next) => {
app.listen(config.port, () => { app.listen(config.port, () => {
const mode = dryRun ? "TROCKENLAUF (kein REDMINE_API_KEY gesetzt, Tickets werden simuliert)" : `verbunden mit ${config.redmineUrl}`; const mode = dryRun ? "TROCKENLAUF (kein REDMINE_API_KEY gesetzt, Tickets werden simuliert)" : `verbunden mit ${config.redmineUrl}`;
console.log(`Ticket-Portal laeuft auf http://localhost:${config.port} - Modus: ${mode}`); console.log(`Ticket-Portal läuft auf http://localhost:${config.port} - Modus: ${mode}`);
}); });