|
|
|
@@ -18,14 +18,31 @@
|
|
|
|
|
align-items: center;
|
|
|
|
|
margin-bottom: 20px;
|
|
|
|
|
flex-wrap: wrap;
|
|
|
|
|
gap: 10px;
|
|
|
|
|
gap: 15px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Neu strukturiertes Layout für Formular & Import */
|
|
|
|
|
.dashboard-grid {
|
|
|
|
|
display: grid;
|
|
|
|
|
grid-template-columns: 2fr 1fr;
|
|
|
|
|
gap: 20px;
|
|
|
|
|
margin-bottom: 30px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.student-card-form {
|
|
|
|
|
background: var(--ui-bg);
|
|
|
|
|
padding: 20px;
|
|
|
|
|
border-radius: 8px;
|
|
|
|
|
margin-bottom: 30px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.import-card {
|
|
|
|
|
border: 1px solid #dbe4ee;
|
|
|
|
|
border-radius: 8px;
|
|
|
|
|
padding: 20px;
|
|
|
|
|
background: #f8fbff;
|
|
|
|
|
display: flex;
|
|
|
|
|
flex-direction: column;
|
|
|
|
|
justify-content: space-between;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.form-row {
|
|
|
|
@@ -35,6 +52,10 @@
|
|
|
|
|
margin-bottom: 15px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.form-row.full-width {
|
|
|
|
|
grid-template-columns: 1fr;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.form-group {
|
|
|
|
|
display: flex;
|
|
|
|
|
flex-direction: column;
|
|
|
|
@@ -47,7 +68,8 @@
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.form-group input,
|
|
|
|
|
.form-group select {
|
|
|
|
|
.form-group select,
|
|
|
|
|
.form-group textarea {
|
|
|
|
|
padding: 10px;
|
|
|
|
|
border: 1px solid #ddd;
|
|
|
|
|
border-radius: 4px;
|
|
|
|
@@ -55,7 +77,8 @@
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.form-group input:focus,
|
|
|
|
|
.form-group select:focus {
|
|
|
|
|
.form-group select:focus,
|
|
|
|
|
.form-group textarea:focus {
|
|
|
|
|
outline: none;
|
|
|
|
|
border-color: #007bff;
|
|
|
|
|
box-shadow: 0 0 5px rgba(0, 123, 255, 0.3);
|
|
|
|
@@ -65,14 +88,16 @@
|
|
|
|
|
display: flex;
|
|
|
|
|
gap: 10px;
|
|
|
|
|
justify-content: flex-end;
|
|
|
|
|
margin-top: 10px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.form-actions button {
|
|
|
|
|
.form-actions button, .form-actions a {
|
|
|
|
|
padding: 10px 20px;
|
|
|
|
|
border: none;
|
|
|
|
|
border-radius: 4px;
|
|
|
|
|
cursor: pointer;
|
|
|
|
|
font-weight: 600;
|
|
|
|
|
text-decoration: none;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.btn-save {
|
|
|
|
@@ -126,15 +151,18 @@
|
|
|
|
|
.card-actions {
|
|
|
|
|
display: flex;
|
|
|
|
|
gap: 8px;
|
|
|
|
|
align-items: center;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.btn-edit, .btn-delete {
|
|
|
|
|
.btn-edit, .btn-delete, .btn-export {
|
|
|
|
|
padding: 6px 12px;
|
|
|
|
|
border: none;
|
|
|
|
|
border-radius: 4px;
|
|
|
|
|
cursor: pointer;
|
|
|
|
|
font-size: 13px;
|
|
|
|
|
font-weight: 600;
|
|
|
|
|
text-decoration: none;
|
|
|
|
|
display: inline-block;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.btn-edit {
|
|
|
|
@@ -164,9 +192,6 @@
|
|
|
|
|
font-weight: 600;
|
|
|
|
|
text-decoration: none;
|
|
|
|
|
display: inline-block;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.btn-print {
|
|
|
|
|
background: #17a2b8;
|
|
|
|
|
color: white;
|
|
|
|
|
}
|
|
|
|
@@ -188,6 +213,7 @@
|
|
|
|
|
display: flex;
|
|
|
|
|
gap: 10px;
|
|
|
|
|
flex-wrap: wrap;
|
|
|
|
|
align-items: center;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.empty-state {
|
|
|
|
@@ -201,6 +227,12 @@
|
|
|
|
|
margin: 10px 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@media (max-width: 992px) {
|
|
|
|
|
.dashboard-grid {
|
|
|
|
|
grid-template-columns: 1fr;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@media (max-width: 768px) {
|
|
|
|
|
.form-row {
|
|
|
|
|
grid-template-columns: 1fr;
|
|
|
|
@@ -222,14 +254,16 @@
|
|
|
|
|
|
|
|
|
|
.card-actions {
|
|
|
|
|
flex-direction: column;
|
|
|
|
|
align-items: stretch;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
</style>
|
|
|
|
|
|
|
|
|
|
<div class="container">
|
|
|
|
|
<!-- Header mit Aktionen -->
|
|
|
|
|
<div class="student-card-header">
|
|
|
|
|
<div>
|
|
|
|
|
<h1>📚 Bibliotheksausweise (Bibliothek)</h1>
|
|
|
|
|
<h1 style="margin: 0;">📚 Bibliotheksausweise</h1>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="export-buttons">
|
|
|
|
|
<form method="GET" action="{{ url_for('student_card_class_barcode_download') }}" style="display: inline-flex; gap: 5px; align-items: center; background: white; padding: 2px; border-radius: 4px; border: 1px solid #ddd;">
|
|
|
|
@@ -239,7 +273,7 @@
|
|
|
|
|
<option value="{{ cls }}">{{ cls }}</option>
|
|
|
|
|
{% endfor %}
|
|
|
|
|
</select>
|
|
|
|
|
<button type="submit" class="btn-print" style="background: #17a2b8; padding: 8px 12px; margin: 0;">📤 PDF</button>
|
|
|
|
|
<button type="submit" class="btn-print" style="padding: 8px 12px; margin: 0;">📤 PDF</button>
|
|
|
|
|
</form>
|
|
|
|
|
|
|
|
|
|
<a href="{{ url_for('student_card_barcode_download') }}" class="btn-print" style="background: #28a745;">📥 Alle Ausweise (PDF)</a>
|
|
|
|
@@ -247,93 +281,105 @@
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<div style="border:1px solid #dbe4ee; border-radius:8px; padding:14px; margin-bottom:16px; background:#f8fbff;">
|
|
|
|
|
<h3 style="margin:0 0 8px 0;">Excel-Import Bibliotheksausweise</h3>
|
|
|
|
|
<p style="margin:0 0 10px 0; color:#555;">Laden Sie eine <strong>.xlsx</strong>- oder <strong>.csv</strong>-Datei hoch, zum Beispiel aus <strong>ASV (Amtliche Schuldaten)</strong>. Erkannt werden automatisch Spalten wie <strong>Name</strong>, <strong>Nachname</strong, <strong>Klasse</strong>, <strong>Ausweis-ID (optional)</strong>, <strong>lokales Differenzierungsmerkmal (optional aber empfohlen)</strong>, <strong>Notizen (optional)</strong> und <strong>Standard-Ausleihdauer (optional)</strong>.</p>
|
|
|
|
|
<form method="POST" action="{{ url_for('upload_student_cards_excel') }}" enctype="multipart/form-data" style="display:flex; gap:10px; flex-wrap:wrap; align-items:center;">
|
|
|
|
|
<input type="file" name="student_cards_excel" accept=".xlsx,.csv" required>
|
|
|
|
|
<button type="submit" class="btn btn-secondary" name="excel_action" value="validate">Nur validieren</button>
|
|
|
|
|
<button type="submit" class="btn btn-primary" name="excel_action" value="import">Ausweise importieren</button>
|
|
|
|
|
</form>
|
|
|
|
|
</div>
|
|
|
|
|
<!-- Hauptbereich Grid: Formular + Import -->
|
|
|
|
|
<div class="dashboard-grid">
|
|
|
|
|
<!-- Add/Edit Form -->
|
|
|
|
|
<div class="student-card-form">
|
|
|
|
|
<h2 style="margin-top:0;">{% if edit_mode %}Ausweis bearbeiten{% else %}Neuer Bibliotheksausweis{% endif %}</h2>
|
|
|
|
|
|
|
|
|
|
<!-- Add/Edit Form -->
|
|
|
|
|
<div class="student-card-form">
|
|
|
|
|
<h2>{% if edit_mode %}Ausweis bearbeiten{% else %}Neuer Bibliotheksausweis{% endif %}</h2>
|
|
|
|
|
|
|
|
|
|
<form method="POST" action="{{ url_for('student_cards_admin') }}">
|
|
|
|
|
{% if edit_mode %}
|
|
|
|
|
<input type="hidden" name="action" value="edit">
|
|
|
|
|
<input type="hidden" name="card_id" value="{{ form_data.get('card_id', '') }}">
|
|
|
|
|
{% else %}
|
|
|
|
|
<input type="hidden" name="action" value="add">
|
|
|
|
|
{% endif %}
|
|
|
|
|
|
|
|
|
|
<div class="form-row">
|
|
|
|
|
<div class="form-group">
|
|
|
|
|
<label for="ausweis_id">Ausweis-ID</label>
|
|
|
|
|
<input type="text" id="ausweis_id" name="ausweis_id"
|
|
|
|
|
value="{{ form_data.get('ausweis_id', '') }}"
|
|
|
|
|
placeholder="z.B. SIS2024001">
|
|
|
|
|
</div>
|
|
|
|
|
<div class="form-group">
|
|
|
|
|
<label for="ausweis_ident">Lokales Differenzierungsmerkmal</label>
|
|
|
|
|
<input type="text" id="ausweis_ident" name="ausweis_ident"
|
|
|
|
|
value="{{ form_data.get('ausweis_ident', '') }}"
|
|
|
|
|
placeholder="z.B. xw5oo123bbe">
|
|
|
|
|
</div>
|
|
|
|
|
<div class="form-group">
|
|
|
|
|
<label for="student_name">Schüler Name *</label>
|
|
|
|
|
<input type="text" id="student_name" name="student_name" required
|
|
|
|
|
value="{{ form_data.get('student_name', '') }}"
|
|
|
|
|
placeholder="z.B. Max Mustermann">
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<div class="form-row">
|
|
|
|
|
<div class="form-group">
|
|
|
|
|
<label for="default_borrow_days">Standard Ausleihdauer (Tage) *</label>
|
|
|
|
|
<input type="number" id="default_borrow_days" name="default_borrow_days"
|
|
|
|
|
min="1" max="365" required
|
|
|
|
|
value="{{ form_data.get('default_borrow_days', config.get('default', 14)) }}">
|
|
|
|
|
</div>
|
|
|
|
|
<div class="form-group">
|
|
|
|
|
<label for="class_name">Klasse</label>
|
|
|
|
|
<input type="text" id="class_name" name="class_name" list="class_list"
|
|
|
|
|
value="{{ form_data.get('class_name', '') }}"
|
|
|
|
|
placeholder="z.B. 10A (Tippen oder Auswählen)">
|
|
|
|
|
|
|
|
|
|
<datalist id="class_list">
|
|
|
|
|
{% for cls in available_classes %}
|
|
|
|
|
<option value="{{ cls }}">
|
|
|
|
|
{% endfor %}
|
|
|
|
|
</datalist>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<div class="form-row">
|
|
|
|
|
<div class="form-group">
|
|
|
|
|
<label for="notes">Notizen</label>
|
|
|
|
|
<textarea id="notes" name="notes" rows="3"
|
|
|
|
|
placeholder="Optionale Notizen..."
|
|
|
|
|
style="padding: 10px; border: 1px solid #ddd; border-radius: 4px;">{{ form_data.get('notes', '') }}</textarea>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<div class="form-actions">
|
|
|
|
|
<form method="POST" action="{{ url_for('student_cards_admin') }}">
|
|
|
|
|
{% if edit_mode %}
|
|
|
|
|
<a href="{{ url_for('student_cards_admin') }}" class="btn-cancel">Abbrechen</a>
|
|
|
|
|
<input type="hidden" name="action" value="edit">
|
|
|
|
|
<input type="hidden" name="card_id" value="{{ form_data.get('card_id', '') }}">
|
|
|
|
|
{% else %}
|
|
|
|
|
<input type="hidden" name="action" value="add">
|
|
|
|
|
{% endif %}
|
|
|
|
|
<button type="submit" class="btn-save">
|
|
|
|
|
{% if edit_mode %}Speichern{% else %}Hinzufügen{% endif %}
|
|
|
|
|
</button>
|
|
|
|
|
|
|
|
|
|
<div class="form-row">
|
|
|
|
|
<div class="form-group">
|
|
|
|
|
<label for="student_name">Schüler Name *</label>
|
|
|
|
|
<input type="text" id="student_name" name="student_name" required
|
|
|
|
|
value="{{ form_data.get('student_name', '') }}"
|
|
|
|
|
placeholder="z.B. Max Mustermann">
|
|
|
|
|
</div>
|
|
|
|
|
<div class="form-group">
|
|
|
|
|
<label for="class_name">Klasse (optional)</label>
|
|
|
|
|
<input type="text" id="class_name" name="class_name" list="class_list"
|
|
|
|
|
value="{{ form_data.get('class_name', '') }}"
|
|
|
|
|
placeholder="z.B. 10A (Tippen oder Auswählen)">
|
|
|
|
|
|
|
|
|
|
<datalist id="class_list">
|
|
|
|
|
{% for cls in available_classes %}
|
|
|
|
|
<option value="{{ cls }}">
|
|
|
|
|
{% endfor %}
|
|
|
|
|
</datalist>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<div class="form-row">
|
|
|
|
|
<div class="form-group">
|
|
|
|
|
<label for="ausweis_id">Ausweis-ID (optional)</label>
|
|
|
|
|
<input type="text" id="ausweis_id" name="ausweis_id"
|
|
|
|
|
value="{{ form_data.get('ausweis_id', '') }}"
|
|
|
|
|
placeholder="z.B. SIS2024001">
|
|
|
|
|
</div>
|
|
|
|
|
<div class="form-group">
|
|
|
|
|
<label for="ausweis_ident">Lokales Differenzierungsmerkmal (optional aber empfohlen)</label>
|
|
|
|
|
<input type="text" id="ausweis_ident" name="ausweis_ident"
|
|
|
|
|
value="{{ form_data.get('ausweis_ident', '') }}"
|
|
|
|
|
placeholder="z.B. xw5oo123bbe">
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<div class="form-row">
|
|
|
|
|
<div class="form-group">
|
|
|
|
|
<label for="default_borrow_days">Standard Ausleihdauer (Tage) (optional)</label>
|
|
|
|
|
<input type="number" id="default_borrow_days" name="default_borrow_days"
|
|
|
|
|
min="1" max="365" required
|
|
|
|
|
value="{{ form_data.get('default_borrow_days', config.get('default', 14)) }}">
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<div class="form-row full-width">
|
|
|
|
|
<div class="form-group">
|
|
|
|
|
<label for="notes">Notizen</label>
|
|
|
|
|
<textarea id="notes" name="notes" rows="2"
|
|
|
|
|
placeholder="Optionale Notizen...">{{ form_data.get('notes', '') }}</textarea>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<div class="form-actions">
|
|
|
|
|
{% if edit_mode %}
|
|
|
|
|
<a href="{{ url_for('student_cards_admin') }}" class="btn-cancel">Abbrechen</a>
|
|
|
|
|
{% endif %}
|
|
|
|
|
<button type="submit" class="btn-save">
|
|
|
|
|
{% if edit_mode %}Speichern{% else %}Hinzufügen{% endif %}
|
|
|
|
|
</button>
|
|
|
|
|
</div>
|
|
|
|
|
</form>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<!-- Excel-Import -->
|
|
|
|
|
<div class="import-card">
|
|
|
|
|
<div>
|
|
|
|
|
<h3 style="margin:0 0 8px 0;">Excel-Import</h3>
|
|
|
|
|
<p style="margin:0 0 15px 0; color:#555; font-size:13px; line-height:1.4;">
|
|
|
|
|
Laden Sie eine <strong>.xlsx</strong>- oder <strong>.csv</strong>-Datei hoch (z. B. aus <strong>ASV</strong>). Erkannt werden Name, Nachname, Klasse, Ausweis-ID, lokales Differenzierungsmerkmal, Notizen & Ausleihdauer.
|
|
|
|
|
</p>
|
|
|
|
|
</div>
|
|
|
|
|
</form>
|
|
|
|
|
<form method="POST" action="{{ url_for('upload_student_cards_excel') }}" enctype="multipart/form-data" style="display:flex; flex-direction:column; gap:12px;">
|
|
|
|
|
<input type="file" name="student_cards_excel" accept=".xlsx,.csv" required style="font-size:13px;">
|
|
|
|
|
<div style="display:flex; gap:8px;">
|
|
|
|
|
<button type="submit" class="btn btn-secondary" name="excel_action" value="validate" style="flex:1;">Validieren</button>
|
|
|
|
|
<button type="submit" class="btn btn-primary" name="excel_action" value="import" style="flex:1;">Importieren</button>
|
|
|
|
|
</div>
|
|
|
|
|
</form>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<!-- Cards List -->
|
|
|
|
|
<div>
|
|
|
|
|
<h2>Registrierte Ausweise</h2>
|
|
|
|
|
<h2 style="margin-bottom: 15px;">Registrierte Ausweise</h2>
|
|
|
|
|
{% if student_cards %}
|
|
|
|
|
<table class="cards-table">
|
|
|
|
|
<thead>
|
|
|
|
@@ -360,7 +406,7 @@
|
|
|
|
|
<input type="hidden" name="edit" value="{{ card._id }}">
|
|
|
|
|
<button type="submit" class="btn-edit">Bearbeiten</button>
|
|
|
|
|
</form>
|
|
|
|
|
<a href="{{ url_for('student_card_single_barcode_download', card_id=card._id) }}" class="btn-export" style="text-decoration: none; display: inline-block;">📥 PDF</a>
|
|
|
|
|
<a href="{{ url_for('student_card_single_barcode_download', card_id=card._id) }}" class="btn-export">📥 PDF</a>
|
|
|
|
|
<form method="POST" style="display: inline;" onsubmit="return confirm('Wirklich löschen?');">
|
|
|
|
|
<input type="hidden" name="action" value="delete">
|
|
|
|
|
<input type="hidden" name="card_id" value="{{ card._id }}">
|
|
|
|
@@ -386,5 +432,4 @@
|
|
|
|
|
// All PDF exports now go through backend routes
|
|
|
|
|
</script>
|
|
|
|
|
|
|
|
|
|
{% endblock %}
|
|
|
|
|
|
|
|
|
|
{% endblock %}
|