Projektsuche Implementiert mit anbindung an INFRA

This commit is contained in:
2026-03-13 16:49:38 +01:00
parent 91603f1617
commit 1d8ba6a955
10 changed files with 1965 additions and 27 deletions

169
views/project-search.ejs Normal file
View File

@@ -0,0 +1,169 @@
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Projektsuche</title>
<link rel="icon" type="image/png" href="/images/favicon.png">
<link rel="stylesheet" href="/css/style.css">
<%- include('header') %>
</head>
<body>
<div class="navbar">
<div class="container">
<div class="navbar-brand">
<img src="/images/header.png" alt="Logo" class="navbar-logo">
<h1>Stundenerfassung - Projektsuche</h1>
</div>
<div class="nav-right">
<span><%= user.firstname %> <%= user.lastname %></span>
<a href="/logout" class="btn btn-logout">Abmelden</a>
</div>
</div>
</div>
<div class="container" style="margin-top: 30px;">
<h2>Projektsuche</h2>
<p>
Suchen Sie nach Projekten über die Beschreibung (<code>Proj</code>).
Die Projektnummer stammt aus <code>Auftrag</code>, die Kundenbezeichnung aus <code>KUNDE.Bez</code>.
</p>
<% if (error) { %>
<div class="alert alert-danger"><%= error %></div>
<% } %>
<form id="searchForm" class="form-inline" style="margin-top: 15px; margin-bottom: 15px;">
<label for="searchTerm" style="margin-right: 10px;">Suchbegriff in Projektbeschreibung:</label>
<input type="text" id="searchTerm" name="term" required style="min-width: 250px; margin-right: 10px;">
<button type="submit" class="btn btn-primary">Suchen</button>
</form>
<div id="message" style="margin-top: 10px; color: #c00;"></div>
<table id="resultsTable" style="width:100%; margin-top:1rem; border-collapse: collapse; display:none;">
<thead>
<tr>
<th style="border-bottom:1px solid #ccc; text-align:left;">Projektnummer (Auftrag)</th>
<th style="border-bottom:1px solid #ccc; text-align:left;">Beschreibung (Proj)</th>
<th style="border-bottom:1px solid #ccc; text-align:left;">Seriennummer</th>
<th style="border-bottom:1px solid #ccc; text-align:left;">Kundennummer (Knd)</th>
<th style="border-bottom:1px solid #ccc; text-align:left;">Kundenbezeichnung (Bez)</th>
<th style="border-bottom:1px solid #ccc; text-align:left;">Aktion</th>
</tr>
</thead>
<tbody></tbody>
</table>
</div>
<script>
const form = document.getElementById('searchForm');
const messageEl = document.getElementById('message');
const table = document.getElementById('resultsTable');
const tbody = table.querySelector('tbody');
form.addEventListener('submit', async (e) => {
e.preventDefault();
const term = document.getElementById('searchTerm').value.trim();
messageEl.style.color = '#c00';
messageEl.textContent = '';
tbody.innerHTML = '';
table.style.display = 'none';
if (!term) {
messageEl.textContent = 'Bitte einen Suchbegriff eingeben.';
return;
}
try {
const params = new URLSearchParams({ term });
const response = await fetch('/api/projects/search?' + params.toString(), {
headers: {
'Accept': 'application/json'
}
});
const result = await response.json();
if (!response.ok) {
messageEl.textContent = result.error || 'Fehler bei der Projektsuche.';
return;
}
const rows = result.results || [];
if (rows.length === 0) {
messageEl.textContent = 'Keine Projekte gefunden.';
return;
}
rows.forEach(row => {
const tr = document.createElement('tr');
const auftrag = row.auftrag || '';
const proj = row.proj || '';
const such = row.such || '';
const knd = row.knd || '';
const bez = row.bez || '';
tr.innerHTML = `
<td>${auftrag}</td>
<td>${proj}</td>
<td>${such}</td>
<td>${knd}</td>
<td>${bez}</td>
<td><button type="button" class="btn btn-secondary btn-sm copy-btn" data-auftrag="${auftrag}">Kopieren</button></td>
`;
tbody.appendChild(tr);
});
table.style.display = '';
} catch (err) {
console.error('Fehler bei der Projektsuche:', err);
messageEl.textContent = 'Fehler bei der Projektsuche. Bitte später erneut versuchen.';
}
});
function copyToClipboard(text) {
if (navigator.clipboard && typeof navigator.clipboard.writeText === 'function') {
return navigator.clipboard.writeText(text);
}
var ta = document.createElement('textarea');
ta.value = text;
ta.setAttribute('readonly', '');
ta.style.position = 'absolute';
ta.style.left = '-9999px';
document.body.appendChild(ta);
ta.select();
try {
document.execCommand('copy');
return Promise.resolve();
} catch (e) {
return Promise.reject(e);
} finally {
document.body.removeChild(ta);
}
}
tbody.addEventListener('click', (ev) => {
const btn = ev.target.closest('button.copy-btn');
if (!btn) return;
const value = btn.getAttribute('data-auftrag');
if (!value) return;
copyToClipboard(value).then(() => {
messageEl.style.color = 'green';
messageEl.textContent = 'Projektnummer wurde in die Zwischenablage kopiert.';
setTimeout(() => {
messageEl.textContent = '';
messageEl.style.color = '#c00';
}, 2000);
}).catch(() => {
messageEl.textContent = 'Kopieren nicht möglich.';
});
});
</script>
<%- include('footer') %>
</body>
</html>