OpenNIT

Quelltext des aktuellen Standes

Fassung 1.1.1

movements.php

10 KB
<?php $this->layout('layouts/main', [
    'page_title'    => $page_title,
    'current_route' => 'stock',
    'full_width'    => true,
]); ?>

<div class="sk-wrap">

    <!-- Content Header -->
    <div class="content-header">
        <div>
            <h1><?= $this->e($item['category_icon']) ?> <?= $this->e($item['name']) ?></h1>
            <ol class="breadcrumb">
                <li class="breadcrumb-item"><a href="/"><?= $this->te('Home') ?></a></li>
                <li class="breadcrumb-item"><a href="/stock"><?= $this->te('Lagerbestand') ?></a></li>
                <li class="breadcrumb-item active"><?= $this->e($item['name']) ?></li>
            </ol>
        </div>
        <div class="content-header-actions">
            <?php if ($can_manage): ?>
            <button class="btn btn-default sk-hdr-in"
                    onclick="openModal('in',<?= (int)$item['id'] ?>,<?= htmlspecialchars(json_encode($item['name'])) ?>)">
                <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" width="14" height="14"><line x1="12" y1="5" x2="12" y2="19"/><line x1="5" y1="12" x2="19" y2="12"/></svg>
                <?= $this->te('Einbuchen') ?>
            </button>
            <button class="btn btn-default sk-hdr-out" <?= (int)$item['quantity'] === 0 ? 'disabled' : '' ?>
                    onclick="openModal('out',<?= (int)$item['id'] ?>,<?= htmlspecialchars(json_encode($item['name'])) ?>,<?= (int)$item['quantity'] ?>)">
                <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" width="14" height="14"><line x1="5" y1="12" x2="19" y2="12"/></svg>
                <?= $this->te('Ausbuchen') ?>
            </button>
            <button type="button" class="btn btn-default"
                    onclick="skOpenArticle(this)"
                    data-id="<?= (int)$item['id'] ?>"
                    data-category="<?= (int)($item['category_id'] ?? 0) ?>"
                    data-name="<?= $this->e($item['name'] ?? '') ?>"
                    data-model="<?= $this->e($item['model'] ?? '') ?>"
                    data-desc="<?= $this->e($item['description'] ?? '') ?>"
                    data-min="<?= (int)($item['min_quantity'] ?? 0) ?>"
                    data-location="<?= $this->e($item['location'] ?? '') ?>">
                <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" width="14" height="14"><path d="M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7"/><path d="M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z"/></svg>
                <?= $this->te('Bearbeiten') ?>
            </button>
            <?php endif; ?>
        </div>
    </div>

    <div class="page-body">

        <!-- KPI Small Boxes -->
        <div class="kpi-row">
            <div class="kpi-col">
                <div class="small-box <?= (int)$item['quantity'] === 0 ? 'bg-danger' : 'bg-teal' ?>">
                    <div class="inner">
                        <h3><?= (int)$item['quantity'] ?> Stück</h3>
                        <p><?= $this->te('Aktueller Bestand') ?></p>
                    </div>
                    <div class="icon"><i class="fas fa-boxes"></i></div>
                </div>
            </div>
            <?php if ((int)$item['min_quantity'] > 0): ?>
            <div class="kpi-col">
                <div class="small-box bg-secondary">
                    <div class="inner">
                        <h3><?= (int)$item['min_quantity'] ?></h3>
                        <p><?= $this->te('Mindestbestand') ?></p>
                    </div>
                    <div class="icon"><i class="fas fa-exclamation-triangle"></i></div>
                </div>
            </div>
            <?php endif; ?>
            <div class="kpi-col">
                <div class="small-box bg-info">
                    <div class="inner">
                        <h3><?= count($movements) ?></h3>
                        <p><?= $this->te('Buchungen') ?></p>
                    </div>
                    <div class="icon"><i class="fas fa-history"></i></div>
                </div>
            </div>
        </div>

        <!-- Meta-Zeile: Modell / Lagerort -->
        <?php if (!empty($item['model']) || !empty($item['location']) || !empty($item['description'])): ?>
        <div class="sk-meta-card">
            <?php if (!empty($item['model'])): ?>
            <div class="sk-meta"><span class="sk-meta-label"><?= $this->te('Modell') ?></span><span class="sk-meta-val sk-mono"><?= $this->e($item['model']) ?></span></div>
            <?php endif; ?>
            <?php if (!empty($item['location'])): ?>
            <div class="sk-meta"><span class="sk-meta-label"><?= $this->te('Lagerort') ?></span><span class="sk-meta-val"><?= $this->e($item['location']) ?></span></div>
            <?php endif; ?>
            <?php if (!empty($item['description'])): ?>
            <div class="sk-meta sk-meta-wide"><span class="sk-meta-label"><?= $this->te('Beschreibung') ?></span><span class="sk-meta-val"><?= $this->e($item['description']) ?></span></div>
            <?php endif; ?>
        </div>
        <?php endif; ?>

        <!-- Buchungshistorie -->
        <?php if (empty($movements)): ?>
        <div class="empty-state">
            <span class="empty-icon"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.25" width="44" height="44"><polyline points="12 8 12 12 14 14"/><path d="M3.05 11a9 9 0 1 1 .5 4"/></svg></span>
            <h2><?= $this->te('Noch keine Buchungen') ?></h2>
            <?php if ($can_manage): ?>
            <p><?= $this->te('Buchen Sie Ihren ersten Zu- oder Abgang.') ?></p>
            <?php endif; ?>
        </div>
        <?php else: ?>
        <div class="sk-section-head">
            <h2><?= $this->te('Buchungshistorie') ?></h2>
            <span class="sk-section-badge"><?= count($movements) ?> Buchung<?= count($movements) !== 1 ? 'en' : '' ?></span>
        </div>
        <div class="table-wrapper">
            <table class="data-table">
                <thead>
                    <tr>
                        <th scope="col" style="width:160px"><?= $this->te('Datum') ?></th>
                        <th scope="col" style="width:120px"><?= $this->te('Typ') ?></th>
                        <th scope="col" style="width:100px"><?= $this->te('Anzahl') ?></th>
                        <th scope="col"><?= $this->te('Bemerkung / Empfänger') ?></th>
                        <th scope="col" style="width:160px"><?= $this->te('Nutzer') ?></th>
                    </tr>
                </thead>
                <tbody>
                <?php foreach ($movements as $mv): ?>
                <tr>
                    <td class="sk-muted" style="font-size:.825rem;white-space:nowrap;">
                        <?= date('d.m.Y H:i', strtotime($mv['created_at'])) ?>
                    </td>
                    <td>
                        <?php if ($mv['type'] === 'in'): ?>
                        <span class="status-pill status-pill--success"><?= $this->te('+ Eingang') ?></span>
                        <?php else: ?>
                        <span class="status-pill status-pill--danger"><?= $this->te('− Ausgang') ?></span>
                        <?php endif; ?>
                    </td>
                    <td style="font-weight:800;font-variant-numeric:tabular-nums;<?= $mv['type'] === 'out' ? 'color:var(--red-600)' : 'color:var(--emerald-600)' ?>">
                        <?= $mv['type'] === 'out' ? '−' : '+' ?><?= (int)$mv['quantity'] ?>
                    </td>
                    <td><?= $this->e($mv['reason'] ?? '—') ?></td>
                    <td class="sk-muted" style="font-size:.825rem;"><?= $this->e($mv['user_name'] ?? '—') ?></td>
                </tr>
                <?php endforeach; ?>
                </tbody>
            </table>
        </div>
        <?php endif; ?>

    </div>
</div>

<?php include __DIR__ . '/_modals.php'; ?>

<style>
/* ====================================================
   Lager-Buchungen  ·  Prefix: sk- / mv-
   ==================================================== */
.sk-wrap { display: flex; flex-direction: column; }

/* Header-Buchungsbuttons farblich akzentuieren */
.sk-hdr-in  { border-color: var(--emerald-200) !important; background: var(--emerald-50) !important; color: var(--emerald-700) !important; }
.sk-hdr-in:hover  { background: var(--emerald-100) !important; }
.sk-hdr-out { border-color: var(--red-200) !important; background: var(--red-50) !important; color: var(--red-700) !important; }
.sk-hdr-out:hover { background: var(--red-100) !important; }
.sk-hdr-out:disabled { opacity: .5; }

/* ── Meta-Karte ───────────────────────────────────── */
.sk-meta-card {
    display: flex;
    flex-wrap: wrap;
    gap: 1.5rem 2.5rem;
    background: var(--color-bg);
    border: 1px solid var(--gray-200);
    border-radius: 0.25rem;
    padding: 1rem 1.25rem;
    margin-bottom: 1.25rem;
    box-shadow: 0 1px 3px rgba(0,0,0,0.04), 0 1px 2px rgba(0,0,0,0.03);
}
.sk-meta { display: flex; flex-direction: column; gap: 0.2rem; min-width: 0; }
.sk-meta-wide { flex: 1 1 100%; }
.sk-meta-label { font-size: 0.68rem; font-weight: 600; color: var(--gray-400); text-transform: uppercase; letter-spacing: 0.05em; }
.sk-meta-val { font-size: 0.9rem; color: var(--gray-700); }
.sk-mono { font-variant-numeric: tabular-nums; }

/* ── Abschnitts-Überschrift ───────────────────────── */
.sk-section-head {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    margin: 0 0 0.75rem 0.1rem;
}
.sk-section-head h2 { font-size: 1rem; font-weight: 600; color: var(--gray-700); margin: 0; }
.sk-section-badge {
    background: var(--gray-200);
    color: var(--gray-600);
    font-size: 0.72rem;
    font-weight: 600;
    padding: 0.1rem 0.55rem;
    border-radius: 9999px;
}

.sk-muted { color: var(--gray-500); }
</style>