Quelltext des aktuellen Standes
<?php
$this->layout('layouts/main', [
'page_title' => $page_title,
'current_route' => $current_route,
'full_width' => true,
]);
$checkedOutAccessories = array_filter($accessories, fn($a) => (bool)$a['checked_out']);
?>
<style>
a { text-decoration: none; }
a:hover { text-decoration: none; }
.ldr-wrap { padding:0; }
.ldr-layout { display:grid; grid-template-columns:1fr 300px; gap:1.75rem; align-items:start; }
/* Accessory check items */
.ldr-acc-item {
display:flex; align-items:center; gap:0.75rem;
padding:0.75rem; border-radius:0.25rem; margin-bottom:0.5rem;
border:2px solid var(--gray-200); background:var(--color-bg); cursor:pointer;
transition:border-color 0.15s, background 0.15s;
}
.ldr-acc-item.checked { border-color:var(--green-600); background:var(--green-50); }
.ldr-acc-item.unchecked { border-color:var(--gray-200); background:var(--color-bg); }
.ldr-acc-item input[type=checkbox] { width:18px; height:18px; accent-color:var(--green-600); flex-shrink:0; cursor:pointer; }
.ldr-acc-name { font-size:0.9rem; font-weight:600; color:var(--gray-700); flex:1; }
.ldr-acc-desc { font-size:0.75rem; color:var(--gray-400); margin-top:0.1rem; }
.ldr-acc-status { font-size:0.72rem; font-weight:700; padding:0.15rem 0.5rem; border-radius:9999px; }
/* Warning if not all checked */
.ldr-warning { background:var(--amber-100); border:1px solid var(--amber-200); border-radius:0.25rem;
padding:0.75rem 1rem; font-size:0.85rem; color:var(--amber-800); margin-bottom:1rem;
display:flex; align-items:center; gap:0.5rem; }
.ldr-warning.hidden { display:none; }
/* Progress indicator */
.ldr-progress { margin-bottom:1rem; }
.ldr-progress-bar { height:6px; background:var(--gray-200); border-radius:9999px; overflow:hidden; }
.ldr-progress-fill { height:100%; background:var(--green-600); border-radius:9999px; transition:width 0.3s; }
.ldr-progress-label { font-size:0.78rem; color:var(--gray-500); margin-top:0.35rem; }
.ldr-notes textarea { width:100%; padding:0.55rem 0.75rem; border:1px solid var(--gray-300); border-radius:0.25rem; font-size:0.88rem; outline:none; resize:vertical; min-height:80px; font-family:inherit; }
.ldr-notes textarea:focus { border-color:var(--blue-700); box-shadow:0 0 0 2px rgba(29,78,216,0.15); }
/* Submit bar */
.ldr-submit-bar { padding:1.25rem 1.75rem; background:var(--gray-50); border-top:1px solid var(--gray-200); display:flex; gap:0.75rem; justify-content:flex-end; align-items:center; }
/* Info sidebar */
.ldr-info-list { display:flex; flex-direction:column; gap:0.75rem; }
.ldr-info-row { display:flex; flex-direction:column; gap:0.15rem; }
.ldr-info-label { font-size:0.72rem; font-weight:700; text-transform:uppercase; letter-spacing:0.05em; color:var(--gray-400); }
.ldr-info-value { font-size:0.88rem; color:var(--gray-700); }
.ldr-device-img { width:100%; height:140px; object-fit:cover; border-radius:0.25rem; margin-bottom:1rem; background:var(--gray-100); display:flex; align-items:center; justify-content:center; overflow:hidden; border:1px solid var(--gray-200); }
.ldr-device-img img { width:100%; height:100%; object-fit:cover; }
@media(max-width:960px) {
.ldr-layout { grid-template-columns:1fr; }
}
@media(max-width:640px) {
.ldr-layout .detail-card-header { flex-direction:column; align-items:flex-start; gap:0.25rem; }
.ldr-notes textarea { min-height:100px; }
}
@media(max-width:480px) {
.ldr-device-img { height:100px; }
.ldr-acc-item { padding:0.5rem 0.6rem; }
}
</style>
<div class="ldr-wrap">
<!-- Content Header -->
<div class="content-header">
<div>
<h1><?= $this->te('Gerät zurücknehmen') ?></h1>
<ol class="breadcrumb">
<li class="breadcrumb-item"><a href="/"><?= $this->te('Home') ?></a></li>
<li class="breadcrumb-item"><a href="/loans"><?= $this->te('Leihgeräte') ?></a></li>
<li class="breadcrumb-item"><a href="/loans/lendings/<?= $lending['id'] ?>">Vorgang #<?= $lending['id'] ?></a></li>
<li class="breadcrumb-item active"><?= $this->te('Rücknahme') ?></li>
</ol>
</div>
<div class="content-header-actions">
<a href="/loans/lendings/<?= $lending['id'] ?>" class="btn btn-default">
<svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M19 12H5M12 5l-7 7 7 7"/></svg>
<?= $this->te('Zum Vorgang') ?>
</a>
</div>
</div>
<form method="POST" action="/loans/lendings/<?= $lending['id'] ?>/return" id="returnForm">
<input type="hidden" name="_csrf" value="<?= $this->csrf() ?>">
<div class="page-body ldr-layout">
<div class="ldr-main">
<!-- Accessory checklist -->
<div class="detail-card">
<div class="detail-card-header">
<span class="detail-card-title"><?= $this->te('Zubehör prüfen') ?></span>
<span style="font-size:0.78rem;color:var(--gray-400);" id="accCount">0 / <?= count($checkedOutAccessories) ?> geprüft</span>
</div>
<div class="detail-card-body">
<?php if (empty($checkedOutAccessories)): ?>
<p style="font-size:0.88rem;color:var(--gray-400);text-align:center;padding:1rem 0;"><?= $this->te('Kein Zubehör wurde bei der Ausgabe mitgegeben.') ?></p>
<?php else: ?>
<!-- Warning -->
<div class="ldr-warning" id="accWarning">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5"><path d="M10.29 3.86L1.82 18a2 2 0 001.71 3h16.94a2 2 0 001.71-3L13.71 3.86a2 2 0 00-3.42 0z"/><line x1="12" y1="9" x2="12" y2="13"/><line x1="12" y1="17" x2="12.01" y2="17"/></svg>
<?= $this->te('Nicht alle Teile sind abgehakt. Fehlende oder defekte Teile können zurückgenommen werden – dokumentieren Sie den Verbleib dann bitte in der Rücknahme-Notiz (Pflicht).') ?>
</div>
<!-- Progress -->
<div class="ldr-progress">
<div class="ldr-progress-bar"><div class="ldr-progress-fill" id="progressFill" style="width:0%"></div></div>
<div class="ldr-progress-label" id="progressLabel"><?= $this->te('Bitte alle Teile prüfen') ?></div>
</div>
<!-- Items -->
<?php foreach ($checkedOutAccessories as $acc): ?>
<label class="ldr-acc-item unchecked" id="accItem_<?= $acc['accessory_id'] ?>">
<input type="checkbox" name="accessories[<?= $acc['accessory_id'] ?>]" value="1"
onchange="updateProgress()" id="accChk_<?= $acc['accessory_id'] ?>">
<div style="flex:1;">
<div class="ldr-acc-name"><?= $this->e($acc['name']) ?></div>
<?php if (!empty($acc['description'])): ?>
<div class="ldr-acc-desc"><?= $this->e($acc['description']) ?></div>
<?php endif; ?>
</div>
<span class="ldr-acc-status" id="accBadge_<?= $acc['accessory_id'] ?>"
style="background:var(--gray-100);color:var(--gray-500);"><?= $this->te('Ausstehend') ?></span>
</label>
<?php endforeach; ?>
<?php endif; ?>
</div>
</div>
<!-- Return notes -->
<div class="detail-card">
<div class="detail-card-header">
<span class="detail-card-title"><?= $this->te('Rücknahme-Notiz') ?>
<span id="notesReq" style="display:none;color:var(--red-600);"><?= $this->te('(Pflicht – Zubehör fehlt)') ?></span>
<span id="notesOpt"><?= $this->te('(optional)') ?></span>
</span>
</div>
<div class="detail-card-body ldr-notes">
<textarea name="return_notes" id="returnNotes" placeholder="<?= $this->te('Zustand des Geräts, Beschädigungen, Verbleib fehlender Teile…') ?>"></textarea>
<div id="notesError" style="display:none;color:var(--red-600);font-size:0.8rem;margin-top:0.4rem;"><?= $this->te('Bitte dokumentieren Sie den Verbleib der fehlenden Teile.') ?></div>
</div>
</div>
<div class="detail-card">
<div class="ldr-submit-bar">
<a href="/loans/lendings/<?= $lending['id'] ?>" class="btn btn-default"><?= $this->te('Abbrechen') ?></a>
<button type="submit" class="btn btn-success" id="submitBtn">
<?= $this->te('Rücknahme bestätigen') ?>
</button>
</div>
</div>
</div>
<!-- Sidebar -->
<div class="ldr-aside">
<div class="detail-card">
<div class="detail-card-header"><span class="detail-card-title"><?= $this->te('Gerät') ?></span></div>
<div class="detail-card-body">
<?php if (!empty($lending['device_image'])): ?>
<div class="ldr-device-img">
<img src="<?= $this->e($lending['device_image']) ?>" alt="">
</div>
<?php endif; ?>
<div class="ldr-info-list">
<div class="ldr-info-row">
<span class="ldr-info-label"><?= $this->te('Gerät') ?></span>
<span class="ldr-info-value" style="font-weight:700;"><?= $this->e($lending['device_title']) ?></span>
</div>
<?php if ($lending['device_type']): ?>
<div class="ldr-info-row">
<span class="ldr-info-label"><?= $this->te('Typ') ?></span>
<span class="ldr-info-value"><?= $this->e($lending['device_type']) ?></span>
</div>
<?php endif; ?>
<?php if (!empty($lending['serial_number'])): ?>
<div class="ldr-info-row">
<span class="ldr-info-label"><?= $this->te('Seriennummer') ?></span>
<span class="ldr-info-value" style="font-family:monospace;"><?= $this->e($lending['serial_number']) ?></span>
</div>
<?php endif; ?>
<div class="ldr-info-row">
<span class="ldr-info-label"><?= $this->te('Ausleiher') ?></span>
<span class="ldr-info-value" style="font-weight:600;"><?= $this->e($lending['borrower_name']) ?></span>
</div>
<div class="ldr-info-row">
<span class="ldr-info-label"><?= $this->te('Ausgegeben') ?></span>
<span class="ldr-info-value"><?= date('d.m.Y', strtotime($lending['planned_start'])) ?></span>
</div>
<div class="ldr-info-row">
<span class="ldr-info-label"><?= $this->te('Geplante Rückgabe') ?></span>
<span class="ldr-info-value"><?= date('d.m.Y', strtotime($lending['planned_end'])) ?></span>
</div>
</div>
</div>
</div>
</div>
</div>
</form>
</div>
<script>
var totalAcc = <?= count($checkedOutAccessories) ?>;
function countChecked() {
var checked = 0;
document.querySelectorAll('#returnForm input[type=checkbox][name^="accessories"]').forEach(function(cb) {
if (cb.checked) checked++;
});
return checked;
}
function updateProgress() {
var checkboxes = document.querySelectorAll('#returnForm input[type=checkbox][name^="accessories"]');
var checked = 0;
checkboxes.forEach(function(cb) {
var accId = cb.name.match(/\[(\d+)\]/)[1];
var item = document.getElementById('accItem_' + accId);
var badge = document.getElementById('accBadge_' + accId);
if (cb.checked) {
checked++;
item.classList.remove('unchecked');
item.classList.add('checked');
badge.style.background = 'var(--green-100)';
badge.style.color = 'var(--green-700)';
badge.textContent = '✓ Zurück';
} else {
item.classList.remove('checked');
item.classList.add('unchecked');
badge.style.background = 'var(--amber-100)';
badge.style.color = 'var(--amber-800)';
badge.textContent = 'Ausstehend';
}
});
var pct = totalAcc > 0 ? Math.round(checked / totalAcc * 100) : 100;
var fill = document.getElementById('progressFill');
if (fill) fill.style.width = pct + '%';
var cnt = document.getElementById('accCount');
if (cnt) cnt.textContent = checked + ' / ' + totalAcc + ' zurück';
var allDone = (checked === totalAcc);
var label = document.getElementById('progressLabel');
if (label) label.textContent = allDone
? '✓ Alle Teile zurück – Rücknahme kann gespeichert werden.'
: (totalAcc - checked) + ' Teil(e) fehlen – bitte in der Notiz dokumentieren.';
var warning = document.getElementById('accWarning');
if (warning) warning.classList.toggle('hidden', allDone);
// Notiz-Pflicht-Hinweis + Button-Label umschalten
var notesReq = document.getElementById('notesReq');
var notesOpt = document.getElementById('notesOpt');
if (notesReq && notesOpt) {
notesReq.style.display = allDone ? 'none' : 'inline';
notesOpt.style.display = allDone ? 'inline' : 'none';
}
var btn = document.getElementById('submitBtn');
if (btn) btn.textContent = allDone ? 'Rücknahme bestätigen' : 'Rücknahme mit fehlendem Zubehör';
}
// Validierung beim Absenden: bei fehlendem Zubehör ist die Notiz Pflicht
document.getElementById('returnForm').addEventListener('submit', function(e) {
var notes = document.getElementById('returnNotes');
if (countChecked() < totalAcc && notes && notes.value.trim() === '') {
e.preventDefault();
notes.style.borderColor = 'var(--red-600)';
notes.focus();
var err = document.getElementById('notesError');
if (err) err.style.display = 'block';
}
});
// Initialzustand setzen (nur wenn Zubehör vorhanden ist)
<?php if (!empty($checkedOutAccessories)): ?>
updateProgress();
<?php endif; ?>
</script>