284 lines
11 KiB
PHP
284 lines
11 KiB
PHP
<div class="arbeitsberichte-wrapper">
|
|
<div class="vergabe-form">
|
|
<form id="addForm" class="vergabe-grid">
|
|
|
|
<div class="form-group">
|
|
<label>Wann ausgeliehen</label>
|
|
<input type="date" name="wann" id="in-wann" required>
|
|
</div>
|
|
|
|
<div class="form-group">
|
|
<label>Rückgabe</label>
|
|
<input type="date" name="rueckgabe" id="in-rueckgabe" required>
|
|
</div>
|
|
|
|
<div class="form-group autocomplete-wrapper">
|
|
<label>An wen</label>
|
|
<input type="text" id="wer-input" placeholder="Name eingeben" required autocomplete="off">
|
|
<div class="autocomplete-suggestions" id="wer-suggestions"></div>
|
|
</div>
|
|
|
|
<div class="form-group autocomplete-wrapper">
|
|
<label>Was</label>
|
|
<input type="text" id="was-input" placeholder="Gegenstand eingeben" required autocomplete="off">
|
|
<div class="autocomplete-suggestions" id="was-suggestions"></div>
|
|
</div>
|
|
|
|
<button type="submit" class="btn-submit-vergabe">Speichern</button>
|
|
|
|
</form>
|
|
</div>
|
|
|
|
<div class="vergabe-form" style="margin-top: 30px;">
|
|
<form id="searchForm" class="vergabe-grid">
|
|
|
|
<div class="form-group autocomplete-wrapper">
|
|
<label for="search-wer-input">Nach Person filtern</label>
|
|
<input type="text" id="search-wer-input" placeholder="Name eingeben..." autocomplete="off">
|
|
<div class="autocomplete-suggestions" id="search-wer-suggestions"></div>
|
|
</div>
|
|
|
|
<div class="form-group autocomplete-wrapper">
|
|
<label for="search-was-input">Nach Gegenstand filtern</label>
|
|
<input type="text" id="search-was-input" placeholder="Gegenstand eingeben..." autocomplete="off">
|
|
<div class="autocomplete-suggestions" id="search-was-suggestions"></div>
|
|
</div>
|
|
|
|
<div style="display: flex; gap: 10px; align-items: flex-end;">
|
|
<button type="submit" class="btn-submit-vergabe" style="margin: 0; flex-grow: 1;">Suchen</button>
|
|
<button type="button" id="resetSearch" class="btn-delete" style="margin: 0;">Zurücksetzen</button>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
|
|
<div class="table-container" style="margin-top: 30px;">
|
|
<h3 id="tableHeading">Aktuelle Vergaben</h3>
|
|
<div id="tableWrapper">
|
|
<p>Lade Daten...</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<script src="/js/AjaxMethods.js"></script>
|
|
<script src="/js/ajaxApi/VergabeAjaxMethods.js"></script>
|
|
<script src="/js/AjaxRenderTables.js"></script>
|
|
<script>
|
|
document.addEventListener('DOMContentLoaded', () => {
|
|
const tableWrapper = document.getElementById('tableWrapper');
|
|
const tableHeading = document.getElementById('tableHeading');
|
|
|
|
let aktuellSearchWer = '';
|
|
let aktuellSearchWas = '';
|
|
|
|
// -----------------------------------------------------------
|
|
// Tabelle rendern (eigene Render-Funktion, da "Zurückgeben"
|
|
// eine andere Aktion ist als das generische Löschen)
|
|
// -----------------------------------------------------------
|
|
function renderVergabeTabelle(entries) {
|
|
if (!entries || entries.length === 0) {
|
|
tableWrapper.innerHTML = '<p>Keine Einträge vorhanden.</p>';
|
|
return;
|
|
}
|
|
|
|
let html = `
|
|
<table class="db-table mobile-responsive-table">
|
|
<thead>
|
|
<tr>
|
|
<th>Was</th><th>Wer</th><th>Wann ausgeliehen</th><th>Rückgabe</th>
|
|
<th style="width: 100px;">Aktion</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
`;
|
|
for (const e of entries) {
|
|
html += `
|
|
<tr data-id="${escapeHtml(e.ID)}">
|
|
<td data-label="Was">${escapeHtml(e.WAS)}</td>
|
|
<td data-label="Wer">${escapeHtml(e.WER)}</td>
|
|
<td data-label="Wann">${escapeHtml(e.WANN)}</td>
|
|
<td data-label="Rückgabe">${escapeHtml(e.RUECKGABE)}</td>
|
|
<td data-label="Aktion">
|
|
<button type="button" class="btn-delete" data-id="${escapeHtml(e.ID)}">Löschen</button>
|
|
</td>
|
|
</tr>`;
|
|
}
|
|
html += `</tbody></table>`;
|
|
tableWrapper.innerHTML = html;
|
|
|
|
tableWrapper.querySelectorAll('.btn-delete').forEach(btn => {
|
|
btn.addEventListener('click', async () => {
|
|
if (!confirm('Möchtest du diesen Eintrag wirklich löschen?')) return;
|
|
try {
|
|
await returnVergabeEntry(btn.dataset.id);
|
|
await ladeListe();
|
|
} catch (err) {
|
|
alert('Fehler beim Löschen: ' + err.message);
|
|
}
|
|
});
|
|
});
|
|
}
|
|
|
|
function aktualisiereUeberschrift() {
|
|
if (aktuellSearchWer && aktuellSearchWas) {
|
|
tableHeading.textContent = `Gefiltert nach: ${aktuellSearchWer} ➔ ${aktuellSearchWas}`;
|
|
} else if (aktuellSearchWer) {
|
|
tableHeading.textContent = `Vergaben für: ${aktuellSearchWer}`;
|
|
} else if (aktuellSearchWas) {
|
|
tableHeading.textContent = `Ausgeliehene Gegenstände: ${aktuellSearchWas}`;
|
|
} else {
|
|
tableHeading.textContent = 'Aktuelle Vergaben';
|
|
}
|
|
}
|
|
|
|
async function ladeListe() {
|
|
try {
|
|
const data = await getVergabeEntries(aktuellSearchWer, aktuellSearchWas);
|
|
aktualisiereUeberschrift();
|
|
renderVergabeTabelle(data.entries);
|
|
} catch (err) {
|
|
tableWrapper.innerHTML = `<p>❌ ${escapeHtml(err.message)}</p>`;
|
|
}
|
|
}
|
|
|
|
// -----------------------------------------------------------
|
|
// Eintrag hinzufügen
|
|
// -----------------------------------------------------------
|
|
document.getElementById('addForm').addEventListener('submit', async (e) => {
|
|
e.preventDefault();
|
|
const wann = document.getElementById('in-wann').value;
|
|
const rueckgabe = document.getElementById('in-rueckgabe').value;
|
|
const wer = document.getElementById('wer-input').value.trim();
|
|
const was = document.getElementById('was-input').value.trim();
|
|
|
|
if (!wann || !rueckgabe || !wer || !was) return;
|
|
|
|
try {
|
|
await addVergabeEntry(was, wer, wann, rueckgabe);
|
|
e.target.reset();
|
|
document.getElementById('in-wann').value = new Date().toISOString().slice(0, 10);
|
|
document.getElementById('in-rueckgabe').value = new Date().toISOString().slice(0, 10);
|
|
await ladeVorschlaege(); // neue WAS/WER-Werte könnten dazugekommen sein
|
|
await ladeListe();
|
|
} catch (err) {
|
|
alert('Fehler beim Speichern: ' + err.message);
|
|
}
|
|
});
|
|
|
|
// -----------------------------------------------------------
|
|
// Suche
|
|
// -----------------------------------------------------------
|
|
document.getElementById('searchForm').addEventListener('submit', async (e) => {
|
|
e.preventDefault();
|
|
aktuellSearchWer = document.getElementById('search-wer-input').value.trim();
|
|
aktuellSearchWas = document.getElementById('search-was-input').value.trim();
|
|
await ladeListe();
|
|
});
|
|
|
|
document.getElementById('resetSearch').addEventListener('click', async () => {
|
|
aktuellSearchWer = '';
|
|
aktuellSearchWas = '';
|
|
document.getElementById('search-wer-input').value = '';
|
|
document.getElementById('search-was-input').value = '';
|
|
await ladeListe();
|
|
});
|
|
|
|
// -----------------------------------------------------------
|
|
// Autocomplete (unverändert zu deiner Logik, nur Datenquelle
|
|
// kommt jetzt per AJAX statt server-seitig eingebettet)
|
|
// -----------------------------------------------------------
|
|
function setupAutocomplete(inputId, suggestionsId, data, submitOnSelect = false) {
|
|
const input = document.getElementById(inputId);
|
|
const box = document.getElementById(suggestionsId);
|
|
if (!input || !box) return;
|
|
|
|
let items = [];
|
|
let activeIndex = -1;
|
|
|
|
function render(list) {
|
|
box.innerHTML = '';
|
|
items = list;
|
|
activeIndex = -1;
|
|
if (list.length === 0) {
|
|
box.style.display = 'none';
|
|
return;
|
|
}
|
|
list.forEach((val, i) => {
|
|
const div = document.createElement('div');
|
|
div.textContent = val;
|
|
div.addEventListener('mousedown', (e) => {
|
|
e.preventDefault();
|
|
selectItem(i);
|
|
});
|
|
box.appendChild(div);
|
|
});
|
|
box.style.display = 'block';
|
|
}
|
|
|
|
function updateActive() {
|
|
[...box.children].forEach((el, i) => el.classList.toggle('active', i === activeIndex));
|
|
if (activeIndex >= 0) box.children[activeIndex].scrollIntoView({
|
|
block: 'nearest'
|
|
});
|
|
}
|
|
|
|
function selectItem(i) {
|
|
if (items[i] !== undefined) input.value = items[i];
|
|
box.style.display = 'none';
|
|
activeIndex = -1;
|
|
if (submitOnSelect) {
|
|
input.closest('form').dispatchEvent(new Event('submit', {
|
|
cancelable: true
|
|
}));
|
|
}
|
|
}
|
|
|
|
input.addEventListener('input', () => {
|
|
const val = input.value.toLowerCase();
|
|
if (val.length === 0) {
|
|
box.style.display = 'none';
|
|
return;
|
|
}
|
|
render(data.filter(d => d.toLowerCase().includes(val)));
|
|
});
|
|
|
|
input.addEventListener('keydown', (e) => {
|
|
if (box.style.display !== 'block') return;
|
|
if (e.key === 'ArrowDown') {
|
|
e.preventDefault();
|
|
activeIndex = Math.min(activeIndex + 1, items.length - 1);
|
|
updateActive();
|
|
} else if (e.key === 'ArrowUp') {
|
|
e.preventDefault();
|
|
activeIndex = Math.max(activeIndex - 1, 0);
|
|
updateActive();
|
|
} else if (e.key === 'Tab' || e.key === 'Enter') {
|
|
if (activeIndex >= 0) {
|
|
e.preventDefault();
|
|
selectItem(activeIndex);
|
|
} else box.style.display = 'none';
|
|
} else if (e.key === 'Escape') box.style.display = 'none';
|
|
});
|
|
|
|
document.addEventListener('click', (e) => {
|
|
if (e.target !== input) box.style.display = 'none';
|
|
});
|
|
}
|
|
|
|
async function ladeVorschlaege() {
|
|
const data = await getVergabeSuggestions();
|
|
setupAutocomplete('was-input', 'was-suggestions', data.was);
|
|
setupAutocomplete('wer-input', 'wer-suggestions', data.wer);
|
|
setupAutocomplete('search-wer-input', 'search-wer-suggestions', data.wer, true);
|
|
setupAutocomplete('search-was-input', 'search-was-suggestions', data.was, true);
|
|
}
|
|
|
|
// -----------------------------------------------------------
|
|
// Initialisierung
|
|
// -----------------------------------------------------------
|
|
document.getElementById('in-wann').value = new Date().toISOString().slice(0, 10);
|
|
document.getElementById('in-rueckgabe').value = new Date().toISOString().slice(0, 10);
|
|
|
|
ladeVorschlaege();
|
|
ladeListe();
|
|
});
|
|
</script> |