Refactor terminology and improve clarity across templates

- Updated "Termin" to "Buchung" in admin_dashboard.html and appointments.html for consistency.
- Enhanced language for better understanding in various templates, including base.html, dienstleistungen.html, inventarsystem.html, kontakt.html, login.html, main.html, projekte.html, register.html, team.html, and added a new tutorial.html.
- Corrected spelling and grammatical errors throughout the templates.
- Improved user guidance and descriptions for better user experience.
This commit is contained in:
2026-03-30 21:36:30 +02:00
parent 84185c35ae
commit 2fc49e3dfa
15 changed files with 305 additions and 1259 deletions
+2 -1
View File
@@ -4,4 +4,5 @@ Inventarsystem_Lizenz_Verwaltung
main.dist
.mongo-data
db
build
build
mongodb.log
+76 -17
View File
@@ -114,6 +114,49 @@ def _sanitize_text(text: str, max_length: int = 255) -> str:
return text
def _activate_test_license_for_user(username: str, school_name: str) -> tuple[bool, str]:
"""Create a one-time test license for the user if none exists yet."""
user_name = _sanitize_text(username or "", 80)
school = _sanitize_text(school_name or "", 200)
if not user_name:
return False, "Benutzername fehlt fuer Test-Key."
client = None
try:
client, col = _get_collection("licenses")
existing = col.find_one(
{
"username": user_name,
"plan": "Test",
"status": {"$in": ["Aktiv", "Pausiert"]},
}
)
if existing:
return False, "Ein Test-Key ist fuer dieses Schulkonto bereits vorhanden."
test_key = f"TEST-{verify.key_generator()[:18].upper()}"
col.insert_one(
{
"username": user_name,
"school_name": school or user_name,
"license_key": test_key,
"plan": "Test",
"status": "Aktiv",
"valid_until": (datetime.utcnow() + timedelta(days=30)).date().isoformat(),
"hwid_uuid": "",
"created_at": _utc_now_iso(),
"updated_at": _utc_now_iso(),
}
)
return True, test_key
except PyMongoError:
return False, "Test-Key konnte nicht aktiviert werden."
finally:
if client:
client.close()
def _with_public_id(doc: dict | None) -> dict | None:
if not doc:
return doc
@@ -277,6 +320,11 @@ def inventarsystem():
return render_template("inventarsystem.html")
@app.route('/tutorial')
def tutorial():
return render_template("tutorial.html")
@app.route('/team')
def team():
return render_template("team.html")
@@ -333,11 +381,13 @@ def login():
def register():
if request.method == "POST":
username = (request.form.get("username") or "").strip()
display_name = (request.form.get("display_name") or "").strip()
school_name = (request.form.get("school_name") or "").strip()
contact_person = (request.form.get("contact_person") or "").strip()
activate_test_key = (request.form.get("activate_test_key") or "").strip().lower() in {"1", "on", "true", "yes"}
password = request.form.get("password") or ""
password_repeat = request.form.get("password_repeat") or ""
if not username or not display_name or not password or not password_repeat:
if not username or not school_name or not contact_person or not password or not password_repeat:
flash("Bitte alle Felder ausfuellen.", "error")
return redirect(url_for("register"))
@@ -357,21 +407,30 @@ def register():
flash("Benutzername bereits vergeben.", "error")
return redirect(url_for("register"))
display_name = _sanitize_text(display_name, 100)
school_name = _sanitize_text(school_name, 120)
contact_person = _sanitize_text(contact_person, 120)
try:
existing_users = user_store.get_all_users() or []
is_first_user = len(existing_users) == 0
if not user_store.add_user(username, password, display_name, ""):
if not user_store.add_user(username, password, school_name, contact_person):
flash("Benutzer konnte nicht erstellt werden.", "error")
return redirect(url_for("register"))
if activate_test_key:
activated, message = _activate_test_license_for_user(username, school_name)
if activated:
flash(f"Test-Key aktiviert: {message}", "success")
else:
flash(message, "error")
if is_first_user:
user_store.make_admin(username)
except Exception:
flash("MongoDB ist derzeit nicht erreichbar.", "error")
return redirect(url_for("register"))
flash("Registrierung erfolgreich. Bitte jetzt einloggen.", "success")
flash("Schulregistrierung erfolgreich. Bitte jetzt einloggen.", "success")
return redirect(url_for("login"))
return render_template("register.html")
@@ -401,11 +460,11 @@ def appointments():
try:
date.fromisoformat(selected_date)
except ValueError:
flash("Bitte einen gueltigen Termin im Kalender auswaehlen.", "error")
flash("Bitte eine gueltige Buchung im Kalender auswaehlen.", "error")
return redirect(url_for("appointments", month=month, year=year))
if selected_date in blocked_day_map:
flash("Dieser Tag ist im Kalender gesperrt. Bitte einen anderen Termin waehlen.", "error")
flash("Dieser Tag ist im Kalender gesperrt. Bitte eine andere Buchung waehlen.", "error")
return redirect(url_for("appointments", month=month, year=year))
if not appointment_time or not subject:
@@ -413,11 +472,11 @@ def appointments():
return redirect(url_for("appointments", month=month, year=year))
if meeting_type not in ["digital", "vor_ort"]:
flash("Bitte eine gueltige Terminart waehlen.", "error")
flash("Bitte eine gueltige Buchungsart waehlen.", "error")
return redirect(url_for("appointments", month=month, year=year))
if meeting_type == "vor_ort" and not location_name:
flash("Bei Vor-Ort-Terminen ist ein Ort erforderlich.", "error")
flash("Bei Vor-Ort-Buchungen ist ein Ort erforderlich.", "error")
return redirect(url_for("appointments", month=month, year=year))
if meeting_type == "digital":
@@ -448,13 +507,13 @@ def appointments():
}
)
except PyMongoError:
flash("Termin konnte nicht gespeichert werden.", "error")
flash("Buchung konnte nicht gespeichert werden.", "error")
return redirect(url_for("appointments", month=month, year=year))
finally:
if client:
client.close()
flash("Termin erfolgreich angefragt.", "success")
flash("Buchung erfolgreich angefragt.", "success")
selected = date.fromisoformat(selected_date)
return redirect(url_for("appointments", month=selected.month, year=selected.year))
@@ -482,7 +541,7 @@ def appointments():
for item in user_appointments:
_with_public_id(item)
except PyMongoError:
flash("Termine konnten nicht geladen werden.", "error")
flash("Buchungen konnten nicht geladen werden.", "error")
finally:
if client:
client.close()
@@ -516,7 +575,7 @@ def admin_dashboard():
for item in all_appointments:
_with_public_id(item)
except PyMongoError:
flash("Terminanfragen konnten nicht geladen werden.", "error")
flash("Buchungsanfragen konnten nicht geladen werden.", "error")
finally:
if client:
client.close()
@@ -610,7 +669,7 @@ def update_appointment(appointment_id):
query = _appointment_query_from_id(appointment_id)
if not query:
flash("Termin nicht gefunden.", "error")
flash("Buchung nicht gefunden.", "error")
return redirect(url_for("admin_dashboard"))
new_status = "Bestaetigt" if action == "confirm" else "Abgelehnt"
@@ -630,16 +689,16 @@ def update_appointment(appointment_id):
},
)
if result.matched_count == 0:
flash("Termin nicht gefunden.", "error")
flash("Buchung nicht gefunden.", "error")
return redirect(url_for("admin_dashboard"))
except PyMongoError:
flash("Termin konnte nicht aktualisiert werden.", "error")
flash("Buchung konnte nicht aktualisiert werden.", "error")
return redirect(url_for("admin_dashboard"))
finally:
if client:
client.close()
flash(f"Termin wurde {('bestaetigt' if action == 'confirm' else 'abgelehnt')}.", "success")
flash(f"Buchung wurde {('bestaetigt' if action == 'confirm' else 'abgelehnt')}.", "success")
return redirect(url_for("admin_dashboard"))
-1127
View File
File diff suppressed because it is too large Load Diff
+3 -3
View File
@@ -248,7 +248,7 @@
</section>
<section class="appointments-section">
<h2>Terminanfragen verwalten</h2>
<h2>Buchungsanfragen verwalten</h2>
<div class="block-days-section">
<h3>Kalender-Tage sperren</h3>
<form method="POST" action="{{ url_for('admin_block_day') }}" class="block-form">
@@ -285,7 +285,7 @@
<div class="appointment-info">
<strong>{{ appointment.display_name }} - {{ appointment.subject }}</strong>
<p><strong>Datum:</strong> {{ appointment.date }} um {{ appointment.time }}</p>
<p><strong>Terminart:</strong> {{ appointment.meeting_label or ('Vor Ort' if appointment.meeting_type == 'vor_ort' else 'Digital') }}</p>
<p><strong>Buchungsart:</strong> {{ appointment.meeting_label or ('Vor Ort' if appointment.meeting_type == 'vor_ort' else 'Digital') }}</p>
{% if appointment.location_name %}
<p><strong>Ort:</strong> {{ appointment.location_name }}</p>
{% endif %}
@@ -315,7 +315,7 @@
</article>
{% endfor %}
{% else %}
<p>Keine Terminanfragen vorhanden.</p>
<p>Keine Buchungsanfragen vorhanden.</p>
{% endif %}
</section>
+7 -7
View File
@@ -1,6 +1,6 @@
{% extends "base.html" %}
{% block title %}Termin anfragen{% endblock %}
{% block title %}Buchungsoption{% endblock %}
{% block head %}
{{ super() }}
@@ -283,8 +283,8 @@
</article>
<aside class="panel booking-form">
<h2>Termin anfragen</h2>
<p class="meeting-note">Persoenliches Gespraechstermin: Digital oder Vor Ort.</p>
<h2>Buchung anfragen</h2>
<p class="meeting-note">Persoenliche Buchungsoption: Digital oder Vor Ort.</p>
<span class="selected-date-badge" id="selectedDateBadge">Kein Datum gewählt</span>
<form method="POST" action="{{ url_for('appointments', month=month, year=year) }}">
<input type="hidden" id="selectedDateInput" name="selected_date" required>
@@ -293,7 +293,7 @@
<input id="appointment_time" name="appointment_time" type="time" required>
</div>
<div class="field">
<label for="meeting_type">Terminart</label>
<label for="meeting_type">Buchungsart</label>
<select id="meeting_type" name="meeting_type" required>
<option value="digital">Digital</option>
<option value="vor_ort">Vor Ort</option>
@@ -316,13 +316,13 @@
<label for="note">Notiz (optional)</label>
<textarea id="note" name="note" placeholder="Kurzbeschreibung der Anfrage"></textarea>
</div>
<button class="submit-btn" type="submit">Termin anfragen</button>
<button class="submit-btn" type="submit">Buchung anfragen</button>
</form>
</aside>
</section>
<section class="panel appointment-list" style="margin-top: 1rem;">
<h2>Meine Terminanfragen</h2>
<h2>Meine Buchungsanfragen</h2>
{% if user_appointments %}
{% for item in user_appointments %}
<article class="entry">
@@ -330,7 +330,7 @@
{% if item.note %}
<p>{{ item.note }}</p>
{% endif %}
<p class="entry-meta"><strong>Terminart:</strong> {{ item.meeting_label or ('Vor Ort' if item.meeting_type == 'vor_ort' else 'Digital') }}</p>
<p class="entry-meta"><strong>Buchungsart:</strong> {{ item.meeting_label or ('Vor Ort' if item.meeting_type == 'vor_ort' else 'Digital') }}</p>
{% if item.location_name %}
<p class="entry-meta"><strong>Ort:</strong> {{ item.location_name }}</p>
{% endif %}
+8 -6
View File
@@ -354,15 +354,16 @@
<div class="site-shell site-nav-inner">
<a class="brand" href="{{ url_for('default') }}">Invario Schule</a>
<div class="nav-links" aria-label="Main Navigation">
<a href="{{ url_for('dienstleistungen') }}">Leistungen fuer Schulen</a>
<a href="{{ url_for('dienstleistungen') }}">Leistungen für Schulen</a>
<a href="{{ url_for('projekte') }}">Praxisbeispiele</a>
<a href="{{ url_for('tutorial') }}">Tutorial</a>
<a href="{{ url_for('team') }}">Unser Ansatz</a>
<a href="{{ url_for('kontakt') }}">Kontakt</a>
<a href="{{ url_for('inventarsystem') }}">Inventarsystem</a>
</div>
<div class="nav-actions">
{% if 'username' in session %}
<a class="nav-btn" href="{{ url_for('appointments') }}">Beratungstermin</a>
<a class="nav-btn" href="{{ url_for('appointments') }}">Buchungsoption</a>
<details class="nav-dropdown">
<summary class="nav-btn">Nutzerbereich</summary>
@@ -416,16 +417,17 @@
<div class="footer-content">
<div class="footer-section">
<h4>Über uns</h4>
<p>Digitale Verwaltungsablaeufe fuer Schulsekretariate und Schulleitungen in Deutschland.</p>
<p>Digitale Verwaltungsabläufe für Bildungseinrichtungen in Deutschland.</p>
</div>
<div class="footer-section">
<h4>Schnelllinks</h4>
<ul class="footer-links">
<li><a href="{{ url_for('default') }}">Start</a></li>
<li><a href="{{ url_for('dienstleistungen') }}">Leistungsuebersicht</a></li>
<li><a href="{{ url_for('dienstleistungen') }}">Leistungsübersicht</a></li>
<li><a href="{{ url_for('tutorial') }}">Tutorial</a></li>
<li><a href="{{ url_for('blog') }}">Neuigkeiten</a></li>
{% if 'username' in session %}
<li><a href="{{ url_for('appointments') }}">Beratungstermine</a></li>
<li><a href="{{ url_for('appointments') }}">Buchungsoption</a></li>
{% endif %}
</ul>
</div>
@@ -525,7 +527,7 @@
</style>
</footer>
<div class="cookie-banner hidden" id="cookieBanner" role="dialog" aria-live="polite" aria-label="Cookie Hinweis">
<p>Wir verwenden Cookies, um die Website sicher und benutzerfreundlich zu betreiben. Mit "Cookies akzeptieren" stimmen Sie der Nutzung zu. Details in <a href="{{ url_for('datenschutz') }}">Datenschutz</a>.</p>
<p>Wir verwenden Cookies, um die Website sicher und benutzerfreundlich zu betreiben. Mit "Cookies akzeptieren" wird die Nutzung bestätigt. Details in <a href="{{ url_for('datenschutz') }}">Datenschutz</a>.</p>
<div class="cookie-actions">
<button type="button" class="cookie-btn" id="cookieAcceptBtn">Cookies akzeptieren</button>
<button type="button" class="cookie-btn secondary" id="cookieDeclineBtn">Ablehnen und zu Ecosia</button>
+15 -11
View File
@@ -1,43 +1,47 @@
{% extends "base.html" %}
{% block title %}Leistungen fuer Schulen | Invario{% endblock %}
{% block title %}Leistungen für Schulen | Invario{% endblock %}
{% block content %}
<section class="page-hero">
<h1>Leistungen fuer Schulsekretariat und Schulleitung</h1>
<p>Praxisnahe Module fuer Schulen in Deutschland: verstaendlich, sicher und ohne unnoetige Komplexitaet.</p>
<h1>Leistungen für Bildungseinrichtungen</h1>
<p>Praxisnahe Module für Schulen in Deutschland: verständlich, sicher und ohne unnötige Komplexität.</p>
</section>
<section class="cards">
<article class="card">
<h2>Digitale Inventarverwaltung</h2>
<p>Alle Geraete, Raeume und Zustaendigkeiten an einem Ort. So finden Sie Informationen schneller und reduzieren Rueckfragen.</p>
<p>Alle Geräte, Räume und Zuständigkeiten an einem Ort. Das verkürzt Suchzeiten und reduziert Rückfragen.</p>
</article>
<article class="card">
<h2>Lizenz- und Fristenkontrolle</h2>
<p>Lizenzlaufzeiten werden transparent angezeigt, inklusive Hinweise auf bald ablaufende Nutzungen.</p>
</article>
<article class="card">
<h2>Support mit klaren Prioritaeten</h2>
<p>Stoerungen werden strukturiert aufgenommen, priorisiert und mit nachvollziehbarem Status bearbeitet.</p>
<h2>Support mit klaren Prioritäten</h2>
<p>Störungen werden strukturiert aufgenommen, priorisiert und mit nachvollziehbarem Status bearbeitet.</p>
</article>
<article class="card">
<h2>DSGVO-konforme Dokumentation</h2>
<p>Vorgaenge und Aenderungen bleiben nachvollziehbar dokumentiert, damit Pruefungen und Abstimmungen einfacher werden.</p>
<p>Vorgänge und Änderungen bleiben nachvollziehbar dokumentiert, damit Prüfungen und Abstimmungen einfacher werden.</p>
</article>
<article class="card">
<h2>Einrichtung und Schulung</h2>
<p>Wir richten das System gemeinsam mit Ihrem Team ein und schulen in klaren, alltagsnahen Schritten.</p>
<p>Die Einführung erfolgt in klaren, alltagsnahen Schritten, damit der laufende Betrieb stabil bleibt.</p>
</article>
<article class="card">
<h2>Begleitung im laufenden Betrieb</h2>
<p>Feste Ansprechpartner unterstuetzen Ihr Team bei Fragen, Erweiterungen und organisatorischen Anpassungen.</p>
<p>Feste Ansprechpartner unterstützen bei Fragen, Erweiterungen und organisatorischen Anpassungen.</p>
</article>
<article class="card">
<h2>Technische Sicherheitsbasis</h2>
<p>Rollenrechte, sichere Sitzungen, Schutz-Header und protokollierte Änderungen bilden die Grundlage für einen verlässlichen Betrieb.</p>
</article>
</section>
<section class="highlight">
<h2>Besonders geeignet fuer Teams mit wenig Zeit</h2>
<p>Die Oberflaeche ist bewusst reduziert aufgebaut: grosse, klare Bedienelemente, eindeutige Bezeichnungen und kurze Klickwege fuer taegliche Verwaltungsaufgaben.</p>
<h2>Besonders geeignet für Teams mit wenig Zeit</h2>
<p>Die Oberfläche ist bewusst reduziert aufgebaut: große, klare Bedienelemente, eindeutige Bezeichnungen und kurze Klickwege für tägliche Verwaltungsaufgaben.</p>
</section>
<style>
+21 -20
View File
@@ -1,30 +1,30 @@
{% extends "base.html" %}
{% block title %}Inventarsystem fuer Schulen | Uebersicht{% endblock %}
{% block title %}Inventarsystem für Schulen | Übersicht{% endblock %}
{% block content %}
<section class="page-hero">
<h1>Inventarsystem fuer Schulen</h1>
<p>Alle wichtigen Funktionen fuer den Schulalltag in einer klaren Oberflaeche: von Inventar ueber Lizenzen bis zur nachvollziehbaren Historie.</p>
<h1>Inventarsystem für Schulen</h1>
<p>Alle wichtigen Funktionen für den Schulalltag in einer klaren Oberfläche: von Inventar über Lizenzen bis zur nachvollziehbaren Historie.</p>
</section>
<section class="split">
<article class="panel">
<h2>1. Bestand einfach pflegen</h2>
<p>Jedes Geraet erhaelt eine eindeutige Akte mit Standort, Status, Kaufdaten und zustaendiger Person.</p>
<p>Jedes Gerät erhält eine eindeutige Akte mit Standort, Status, Kaufdaten und zuständiger Person.</p>
<ul>
<li>Suche nach Seriennummer, Raum oder Geraetetyp</li>
<li>Einheitliche Datenfelder fuer alle Standorte</li>
<li>Schnelle Erfassung neuer Geraete</li>
<li>Suche nach Seriennummer, Raum oder Gerätetyp</li>
<li>Einheitliche Datenfelder für alle Standorte</li>
<li>Schnelle Erfassung neuer Geräte</li>
</ul>
</article>
<article class="panel">
<h2>2. Standorte nachvollziehbar verwalten</h2>
<p>Raeume, Etagen und Gebaeude werden klar strukturiert, damit jederzeit ersichtlich ist, wo sich ein Geraet befindet.</p>
<p>Räume, Etagen und Gebäude werden klar strukturiert, damit jederzeit ersichtlich ist, wo sich ein Gerät befindet.</p>
<ul>
<li>Uebersicht je Raum oder Fachbereich</li>
<li>Sammelverschiebung mehrerer Geraete</li>
<li>Übersicht je Raum oder Fachbereich</li>
<li>Sammelverschiebung mehrerer Geräte</li>
<li>Einfacher Abgleich bei Inventurterminen</li>
</ul>
</article>
@@ -32,8 +32,8 @@
<section class="split" style="margin-top:0.9rem;">
<article class="panel">
<h2>3. QR-Code Unterstuetzung</h2>
<p>Mit QR-Codes lassen sich Geraete vor Ort direkt identifizieren und aktualisieren.</p>
<h2>3. QR-Code Unterstützung</h2>
<p>Mit QR-Codes lassen sich Geräte vor Ort direkt identifizieren und aktualisieren.</p>
<ul>
<li>Labels direkt aus dem System erzeugen</li>
<li>Scannen und sofort zur richtigen Akte springen</li>
@@ -43,23 +43,24 @@
<article class="panel">
<h2>4. Historie und Verantwortung</h2>
<p>Aenderungen bleiben dokumentiert, damit Entscheidungen und Vorgaenge transparent bleiben.</p>
<p>Änderungen bleiben dokumentiert, damit Entscheidungen und Vorgänge transparent bleiben.</p>
<ul>
<li>Wer hat wann was geaendert</li>
<li>Leihvorgaenge und Rueckgaben nachvollziehen</li>
<li>Klare Nachweise fuer interne Abstimmungen</li>
<li>Wer hat wann was geändert</li>
<li>Leihvorgänge und Rückgaben nachvollziehen</li>
<li>Klare Nachweise für interne Abstimmungen</li>
</ul>
</article>
</section>
<section class="panel" style="margin-top:0.9rem;">
<h2>5. Rollen, Rechte und Exporte</h2>
<p>Das System unterscheidet klar zwischen Verwaltung, Schulleitung und technischen Rollen.</p>
<p>Das System unterscheidet klar zwischen Verwaltungs- und Technikrollen.</p>
<ul class="wide-list">
<li><strong>Rollenbasiert:</strong> Nur relevante Funktionen pro Nutzergruppe sichtbar.</li>
<li><strong>Datenschutzgerecht:</strong> Zugriff und Aenderungen werden protokolliert.</li>
<li><strong>Exportierbar:</strong> Berichte und Bestandslisten koennen fuer Termine und Pruefungen ausgegeben werden.</li>
<li><strong>Erweiterbar:</strong> Das System waechst mit Ihren organisatorischen Anforderungen.</li>
<li><strong>Datenschutzgerecht:</strong> Zugriff und Änderungen werden protokolliert.</li>
<li><strong>Exportierbar:</strong> Berichte und Bestandslisten können für Termine und Prüfungen ausgegeben werden.</li>
<li><strong>Sicher betrieben:</strong> Session-Schutz, sichere Header und Zugriffskontrollen sind standardmäßig aktiv.</li>
<li><strong>Erweiterbar:</strong> Das System wächst mit organisatorischen Anforderungen.</li>
</ul>
</section>
+8 -8
View File
@@ -1,11 +1,11 @@
{% extends "base.html" %}
{% block title %}Kontakt fuer Schulen | Invario{% endblock %}
{% block title %}Kontakt für Schulen | Invario{% endblock %}
{% block content %}
<section class="page-hero">
<h1>Kontakt</h1>
<p>Wir beantworten Anfragen aus Schulsekretariat und Schulleitung schnell und klar. Fuer neue Projekte empfehlen wir einen kurzen Beratungstermin.</p>
<p>Anfragen rund um Einführung, Betrieb und Support werden schnell und klar beantwortet. Für neue Projekte empfiehlt sich eine kurze Buchungsoption.</p>
</section>
<section class="contact-grid">
@@ -13,23 +13,23 @@
<h2>Allgemeine Anfrage</h2>
<p><strong>E-Mail:</strong> info@invario.de</p>
<p><strong>Telefon:</strong> +49 (0) 123 / 456789</p>
<p>Geeignet fuer organisatorische Fragen, Erstkontakt und allgemeine Informationen.</p>
<p>Geeignet für organisatorische Fragen, Erstkontakt und allgemeine Informationen.</p>
</article>
<article class="contact-card">
<h2>Support</h2>
<p><strong>E-Mail:</strong> support@invario.de</p>
<p><strong>Telefon:</strong> +49 (0) 123 / 456790</p>
<p>Bei laufendem Betrieb, stoerenden Fehlern oder dringenden Rueckfragen im Schulalltag.</p>
<p>Bei laufendem Betrieb, störenden Fehlern oder dringenden Rückfragen im Schulalltag.</p>
</article>
<article class="contact-card">
<h2>Beratungstermin</h2>
<p>In 30 Minuten besprechen wir Ihre aktuelle Situation und priorisieren sinnvolle erste Schritte fuer Ihre Schule.</p>
<h2>Buchungsoption</h2>
<p>In 30 Minuten werden aktuelle Rahmenbedingungen bewertet und sinnvolle erste Schritte priorisiert.</p>
{% if 'username' in session %}
<a class="btn" href="{{ url_for('appointments') }}">Beratungstermin buchen</a>
<a class="btn" href="{{ url_for('appointments') }}">Buchungsoption nutzen</a>
{% else %}
<a class="btn" href="{{ url_for('login') }}">Login fuer Terminbuchung</a>
<a class="btn" href="{{ url_for('login') }}">Login für Buchung</a>
{% endif %}
</article>
</section>
+1 -1
View File
@@ -93,7 +93,7 @@
{% block content %}
<section class="auth-wrap">
<h1>Login</h1>
<p>Bitte melden Sie sich mit Ihrem Konto an, um Termine anzufragen.</p>
<p>Bitte melden Sie sich mit Ihrem Konto an, um Buchungen anzufragen.</p>
<form method="POST" action="{{ url_for('login') }}">
<div class="field">
<label for="username">Benutzername</label>
+46 -26
View File
@@ -1,6 +1,6 @@
{% extends "base.html" %}
{% block title %}Digitale Schulverwaltung fuer Sekretariat und Schulleitung{% endblock %}
{% block title %}Digitale Schulverwaltung mit Sicherheitsfokus{% endblock %}
{% block head %}
{{ super() }}
@@ -320,24 +320,25 @@
{% block content %}
<section class="hero" id="top">
<div>
<span class="eyebrow">Fuer Schulsekretariat und Schulleitung</span>
<span class="eyebrow">Für moderne Schulverwaltung</span>
<h1>Mehr Ruhe im Schulalltag durch klare digitale Verwaltung.</h1>
<p>
Invario unterstützt Schulen in Deutschland dabei, Inventar, Lizenzen und Anfragen nachvollziehbar zu organisieren. Die Bedienung ist bewusst einfach gehalten, damit auch Teams ohne IT-Spezialisierung schnell und sicher arbeiten koennen.
Invario unterstützt Bildungseinrichtungen in Deutschland dabei, Inventar, Lizenzen und Anfragen nachvollziehbar zu organisieren. Die Bedienung bleibt bewusst einfach, während zentrale Sicherheitsfunktionen wie Rollenrechte, Protokollierung und geschützte Verbindungen standardmäßig integriert sind.
</p>
<div class="cta-row">
{% if 'username' in session %}
<a class="btn btn-primary" href="{{ url_for('appointments') }}">Beratungstermin buchen</a>
<a class="btn btn-primary" href="{{ url_for('appointments') }}">Buchungsoption nutzen</a>
{% else %}
<a class="btn btn-primary" href="{{ url_for('login') }}">Beratungstermin buchen</a>
<a class="btn btn-primary" href="{{ url_for('login') }}">Buchungsoption nutzen</a>
{% endif %}
<a class="btn btn-secondary" href="{{ url_for('dienstleistungen') }}">Leistungen ansehen</a>
<a class="btn btn-secondary" href="{{ url_for('tutorial') }}">Tutorial ansehen</a>
<a class="btn btn-secondary" href="{{ url_for('kontakt') }}">Direkt kontaktieren</a>
</div>
</div>
<aside class="hero-card" aria-label="Kurzfakten fuer Schulen">
<h3>Was Schulen besonders schaetzen</h3>
<p>Klare Ablaeufe, feste Ansprechpartner und verstaendliche Oberflaechen fuer den taeglichen Einsatz.</p>
<aside class="hero-card" aria-label="Kurzfakten für Schulen">
<h3>Was Schulen besonders schätzen</h3>
<p>Klare Abläufe, feste Ansprechpartner und verständliche Oberflächen für den täglichen Einsatz.</p>
<div class="stats">
<div><strong>5 Min</strong><span>Einstieg pro Aufgabe</span></div>
<div><strong>1 Klick</strong><span>Status und Historie</span></div>
@@ -347,20 +348,20 @@
</section>
<section class="section" id="nutzen" style="animation-delay: 100ms;">
<h2>Was Ihr Sekretariat sofort entlastet</h2>
<p>Alle Informationen sind gebuendelt, Vorgaenge sind standardisiert, und Rueckfragen lassen sich schneller beantworten.</p>
<h2>Vorteile für Ihr Sekretariat</h2>
<p>Alle Informationen sind gebündelt, Vorgänge sind standardisiert, und Rückfragen lassen sich schneller beantworten.</p>
<div class="section-grid">
<article class="card">
<h3>Inventar auf einen Blick</h3>
<p>Geraete, Standorte und Zustaendigkeiten sind zentral erfasst. Das reduziert Suchzeiten und doppelte Rueckfragen.</p>
<p>Geräte, Standorte und Zuständigkeiten sind zentral erfasst. Das reduziert Suchzeiten und doppelte Rückfragen.</p>
</article>
<article class="card">
<h3>Lizenzfristen im Blick</h3>
<p>Auslaufende Lizenzen werden rechtzeitig sichtbar, damit keine Unterrichtsausfaelle durch fehlende Software entstehen.</p>
<p>Auslaufende Lizenzen werden rechtzeitig sichtbar, damit keine Unterrichtsausfälle durch fehlende Software entstehen.</p>
</article>
<article class="card">
<h3>Verstaendliche Prozesse</h3>
<p>Statt technischer Fachsprache sehen Sie klare Schritte und eindeutige Statusmeldungen fuer jede Aufgabe.</p>
<h3>Verständliche Prozesse</h3>
<p>Statt technischer Fachsprache zeigt die Plattform klare Schritte und eindeutige Statusmeldungen für jede Aufgabe.</p>
</article>
</div>
</section>
@@ -371,15 +372,15 @@
<div class="routine-list">
<div class="routine">
<div>
<b>Neues Geraet kommt an</b>
Seriennummer, Raum und Ansprechpartner werden in wenigen Schritten eingetragen und sind sofort nachvollziehbar.
<b>Neues Gerät kommt an</b>
Seriennummer, Raum und Ansprechperson werden in wenigen Schritten eingetragen und sind sofort nachvollziehbar.
</div>
<span>Inventar</span>
</div>
<div class="routine">
<div>
<b>Rueckfrage der Schulleitung</b>
Status zu Bestellung, Nutzung oder Defekt ist direkt sichtbar, ohne mehrere Listen durchsuchen zu muessen.
<b>Rückfrage zur Gerätehistorie</b>
Status zu Bestellung, Nutzung oder Defekt ist direkt sichtbar, ohne mehrere Listen durchsuchen zu müssen.
</div>
<span>Transparenz</span>
</div>
@@ -393,27 +394,46 @@
</div>
</section>
<section class="section" id="sicherheit" style="animation-delay: 220ms;">
<h2>Allgemeine Sicherheit des Programms</h2>
<p>Das Sicherheitskonzept verbindet technische Schutzmaßnahmen mit klaren Arbeitsabläufen, damit Daten im laufenden Betrieb zuverlässig geschützt bleiben.</p>
<div class="section-grid">
<article class="card">
<h3>Rollenbasierte Zugriffe</h3>
<p>Nutzerkonten sehen nur Funktionen, die für die jeweilige Aufgabe benötigt werden. Das reduziert Fehlbedienungen und ungewollte Änderungen.</p>
</article>
<article class="card">
<h3>Dokumentierte Änderungen</h3>
<p>Wichtige Aktionen werden nachvollziehbar protokolliert. Dadurch lassen sich Abläufe prüfen und Sicherheitsereignisse schneller einordnen.</p>
</article>
<article class="card">
<h3>Geschützte Übertragung</h3>
<p>Verbindungen laufen über sichere Protokolle, ergänzt durch Sicherheits-Header und strikte Session-Regeln für den täglichen Webbetrieb.</p>
</article>
</div>
</section>
<section class="section" id="ablauf" style="animation-delay: 260ms;">
<h2>So verlaeuft die Zusammenarbeit</h2>
<p>Ein klarer Prozess sorgt fuer Sicherheit, besonders bei begrenzten Zeitfenstern im Schulbetrieb.</p>
<div class="process" aria-label="Ablauf in fuenf Schritten">
<h2>So verläuft die Zusammenarbeit</h2>
<p>Ein klarer Prozess sorgt für Sicherheit, besonders bei begrenzten Zeitfenstern im Schulbetrieb.</p>
<div class="process" aria-label="Ablauf in fünf Schritten">
<div class="step"><strong>1. Kennenlernen</strong><small>Ziele klären</small></div>
<div class="step"><strong>2. Struktur</strong><small>Bestehende Abläufe erfassen</small></div>
<div class="step"><strong>3. Einrichtung</strong><small>System passgenau einstellen</small></div>
<div class="step"><strong>4. Schulung</strong><small>Praxisnah einführen</small></div>
<div class="step"><strong>5. Betrieb</strong><small>Persoenlich begleiten</small></div>
<div class="step"><strong>5. Betrieb</strong><small>Persönlich begleiten</small></div>
</div>
</section>
<section class="contact" id="kontakt">
<div>
<h2>Sie moechten den Verwaltungsaufwand spuerbar reduzieren?</h2>
<p>In einem kurzen Gespraech klaeren wir gemeinsam, welche Prozesse in Ihrem Sekretariat zuerst vereinfacht werden sollten. Auf Wunsch erhalten Sie danach einen konkreten Einfuehrungsplan fuer Ihre Schule.</p>
<h2>Beratung für den nächsten Digitalisierungsschritt</h2>
<p>Ein kurzes Gespräch schafft Klarheit über Prioritäten, Sicherheitsanforderungen und realistische Einführungsetappen für den Schulbetrieb.</p>
</div>
{% if 'username' in session %}
<a class="btn btn-secondary" href="{{ url_for('appointments') }}">Beratungstermin buchen</a>
<a class="btn btn-secondary" href="{{ url_for('appointments') }}">Buchungsoption nutzen</a>
{% else %}
<a class="btn btn-secondary" href="{{ url_for('login') }}">Beratungstermin buchen</a>
<a class="btn btn-secondary" href="{{ url_for('login') }}">Buchungsoption nutzen</a>
{% endif %}
</section>
{% endblock %}
+16 -15
View File
@@ -5,46 +5,47 @@
{% block content %}
<section class="page-hero">
<h1>Praxisbeispiele aus dem Schulalltag</h1>
<p>So setzen Schulen unsere Loesung ein, um Verwaltungsaufwand zu reduzieren und Ablaeufe transparent zu machen.</p>
<p>So setzen Schulen unsere Lösung ein, um Verwaltungsaufwand zu reduzieren und Abläufe transparent zu machen.</p>
</section>
<section class="split">
<article class="panel">
<h2>Beispiel 1: Gymnasium mit 1.100 Schuelern</h2>
<h2>Beispiel 1: Gymnasium mit 1.100 Schülern</h2>
<ul>
<li><strong>Ausgangslage:</strong> Inventardaten lagen in mehreren Excel-Listen und Papierordnern.</li>
<li><strong>Umsetzung:</strong> Zentralisierung von Geraeten, Raeumen und Verantwortlichkeiten in einer Plattform.</li>
<li><strong>Ergebnis:</strong> Rueckfragen aus Schulleitung und Fachbereichen werden deutlich schneller beantwortet.</li>
<li><strong>Umsetzung:</strong> Zentralisierung von Geräten, Räumen und Verantwortlichkeiten in einer Plattform.</li>
<li><strong>Ergebnis:</strong> Rückfragen aus Fachbereichen werden deutlich schneller beantwortet.</li>
</ul>
</article>
<article class="panel">
<h2>Beispiel 2: Verbundschule mit mehreren Standorten</h2>
<ul>
<li><strong>Ausgangslage:</strong> Unterschiedliche Ablaeufe je Standort, keine gemeinsame Fristenuebersicht.</li>
<li><strong>Umsetzung:</strong> Einheitliche Prozesse fuer Inventar, Lizenzen und Supporttickets.</li>
<li><strong>Ergebnis:</strong> Standortuebergreifende Transparenz und bessere Planbarkeit im Sekretariat.</li>
<li><strong>Ausgangslage:</strong> Unterschiedliche Abläufe je Standort, keine gemeinsame Fristenübersicht.</li>
<li><strong>Umsetzung:</strong> Einheitliche Prozesse für Inventar, Lizenzen und Supporttickets.</li>
<li><strong>Ergebnis:</strong> Standortübergreifende Transparenz und bessere Planbarkeit in der Verwaltung.</li>
</ul>
</article>
</section>
<section class="split" style="margin-top:0.9rem;">
<article class="panel">
<h2>Beispiel 3: Berufskolleg mit Fokus IT-Raeume</h2>
<h2>Beispiel 3: Berufskolleg mit Fokus IT-Räume</h2>
<ul>
<li><strong>Ausgangslage:</strong> Hohe Anzahl technischer Geraete mit haeufigen Aenderungen.</li>
<li><strong>Umsetzung:</strong> QR-gestuetzte Bestandsfuehrung und klare Historie je Geraet.</li>
<li><strong>Ergebnis:</strong> Schnellere Inventur und weniger Fehler bei Standort- oder Statusaenderungen.</li>
<li><strong>Ausgangslage:</strong> Hohe Anzahl technischer Geräte mit häufigen Änderungen.</li>
<li><strong>Umsetzung:</strong> QR-gestützte Bestandsführung und klare Historie je Gerät.</li>
<li><strong>Ergebnis:</strong> Schnellere Inventur und weniger Fehler bei Standort- oder Statusänderungen.</li>
</ul>
</article>
<article class="panel">
<h2>Was diese Projekte gemeinsam haben</h2>
<ul>
<li>Verstaendliche Bedienung ohne IT-Fachwissen</li>
<li>Klare Rollen fuer Sekretariat, Schulleitung und Administration</li>
<li>Nachvollziehbare Dokumentation fuer interne Abstimmungen</li>
<li>Schrittweise Einfuehrung im laufenden Schulbetrieb</li>
<li>Verständliche Bedienung ohne IT-Fachwissen</li>
<li>Klare Rollen für Verwaltung und technische Aufgaben</li>
<li>Nachvollziehbare Dokumentation für interne Abstimmungen</li>
<li>Schrittweise Einführung im laufenden Schulbetrieb</li>
<li>Sicherheitsorientierte Prozesse mit klaren Freigaben</li>
</ul>
</article>
</section>
+25 -4
View File
@@ -51,6 +51,19 @@
box-shadow: 0 0 0 3px rgba(58, 133, 180, 0.2);
}
.checkbox-line {
display: flex;
align-items: flex-start;
gap: 0.6rem;
margin: 0.35rem 0 1rem;
color: #244f66;
}
.checkbox-line input {
width: auto;
margin-top: 0.2rem;
}
.auth-btn {
width: 100%;
border: none;
@@ -77,12 +90,16 @@
{% block content %}
<section class="auth-wrap">
<h1>Registrierung</h1>
<p>Legen Sie ein Konto an, um den Kalender für Terminanfragen zu nutzen.</p>
<h1>Schulregistrierung</h1>
<p>Registrieren Sie Ihre Schule, um Buchungen, Lizenzen und Support zentral zu verwalten.</p>
<form method="POST" action="{{ url_for('register') }}">
<div class="field">
<label for="display_name">Name</label>
<input id="display_name" name="display_name" type="text" autocomplete="name" required>
<label for="school_name">Name der Schule</label>
<input id="school_name" name="school_name" type="text" autocomplete="organization" required>
</div>
<div class="field">
<label for="contact_person">Ansprechpartner der Schule</label>
<input id="contact_person" name="contact_person" type="text" autocomplete="name" required>
</div>
<div class="field">
<label for="username">Benutzername</label>
@@ -96,6 +113,10 @@
<label for="password_repeat">Passwort wiederholen</label>
<input id="password_repeat" name="password_repeat" type="password" autocomplete="new-password" required>
</div>
<label class="checkbox-line" for="activate_test_key">
<input id="activate_test_key" name="activate_test_key" type="checkbox" value="1">
<span>Direkt bei Registrierung einen Test-Key aktivieren</span>
</label>
<button class="auth-btn" type="submit">Konto erstellen</button>
</form>
<p class="auth-meta">Bereits registriert? <a href="{{ url_for('login') }}">Zum Login</a></p>
+13 -13
View File
@@ -4,34 +4,34 @@
{% block content %}
<section class="page-hero">
<h1>Unser Ansatz fuer Schulen</h1>
<p>Wir arbeiten strukturiert, persoenlich und mit Fokus auf den praktischen Nutzen im Sekretariat und in der Schulleitung.</p>
<h1>Unser Ansatz für Schulen</h1>
<p>Die Arbeitsweise ist strukturiert, persönlich und auf den praktischen Nutzen in der täglichen Verwaltung ausgerichtet.</p>
</section>
<section class="grid">
<article class="member">
<h2>Verstaendliche Beratung</h2>
<p>Wir uebersetzen technische Moeglichkeiten in klare Entscheidungen: Was bringt im Schulalltag wirklich Entlastung und was nicht.</p>
<p><strong>Ihr Vorteil:</strong> Keine unnoetigen Funktionen, sondern ein klarer Fahrplan mit nachvollziehbaren Prioritaeten.</p>
<h2>Verständliche Beratung</h2>
<p>Technische Möglichkeiten werden in klare Entscheidungen übersetzt: Was bringt im Schulalltag wirklich Entlastung und was nicht.</p>
<p><strong>Ergebnis:</strong> Keine unnötigen Funktionen, sondern ein klarer Fahrplan mit nachvollziehbaren Prioritäten.</p>
</article>
<article class="member">
<h2>Saubere Einfuehrung</h2>
<p>Das System wird gemeinsam mit Ihrem Team eingerichtet, ohne den laufenden Betrieb zu ueberlasten.</p>
<p><strong>Ihr Vorteil:</strong> Schrittweise Umstellung mit Schulung direkt an Ihren typischen Arbeitsablaeufen.</p>
<h2>Saubere Einführung</h2>
<p>Das System wird gemeinsam mit den verantwortlichen Teams eingerichtet, ohne den laufenden Betrieb zu überlasten.</p>
<p><strong>Ergebnis:</strong> Schrittweise Umstellung mit Schulung direkt an typischen Arbeitsabläufen.</p>
</article>
<article class="member">
<h2>Zuverlaessige Begleitung</h2>
<p>Nach der Einfuehrung bleiben wir erreichbar und unterstuetzen bei Anpassungen, Fragen und neuen Anforderungen.</p>
<p><strong>Ihr Vorteil:</strong> Feste Ansprechpartner und verlässliche Rueckmeldung statt wechselnder Kontaktwege.</p>
<h2>Zuverlässige Begleitung</h2>
<p>Nach der Einführung bleibt das Team erreichbar und unterstützt bei Anpassungen, Fragen und neuen Anforderungen.</p>
<p><strong>Ergebnis:</strong> Feste Ansprechpartner und verlässliche Rückmeldung statt wechselnder Kontaktwege.</p>
</article>
</section>
<section class="references">
<h2>Werte, nach denen wir arbeiten</h2>
<ul>
<li>Klarheit vor Komplexitaet</li>
<li>Klarheit vor Komplexität</li>
<li>Datenschutz als Standard, nicht als Zusatz</li>
<li>Respekt fuer die Arbeitsrealitaet in Schulen</li>
<li>Respekt für die Arbeitsrealität in Schulen</li>
<li>Verbindliche Kommunikation und transparente Schritte</li>
</ul>
</section>
+64
View File
@@ -0,0 +1,64 @@
{% extends "base.html" %}
{% block title %}Tutorial | Invario{% endblock %}
{% block content %}
<section class="page-hero">
<h1>Tutorial: Sicherer Start mit Invario</h1>
<p>Diese Schritt-für-Schritt-Anleitung zeigt den Einstieg in Inventar, Lizenzen und Supportprozesse mit besonderem Fokus auf Sicherheit im Alltag.</p>
</section>
<section class="grid">
<article class="card">
<h2>1. Nutzerkonten und Rollen anlegen</h2>
<p>Zuerst werden Rollen für Verwaltung und Technik eingerichtet. Jede Rolle erhält nur die benötigten Rechte, um Risiken durch Überberechtigungen zu vermeiden.</p>
</article>
<article class="card">
<h2>2. Inventardaten strukturiert übernehmen</h2>
<p>Geräte, Räume und Zuständigkeiten werden einheitlich erfasst. Klare Datenstrukturen verbessern die Nachvollziehbarkeit und unterstützen Prüfungen.</p>
</article>
<article class="card">
<h2>3. Lizenzfristen aktiv überwachen</h2>
<p>Lizenzlaufzeiten und Erinnerungen werden zentral gepflegt. So lassen sich Ausfälle vermeiden und Fristen rechtzeitig bearbeiten.</p>
</article>
<article class="card">
<h2>4. Supportabläufe definieren</h2>
<p>Tickets erhalten klare Prioritäten und feste Statuswerte. Das schafft Transparenz und beschleunigt die Bearbeitung im Tagesbetrieb.</p>
</article>
</section>
<section class="security-box">
<h2>Sicherheitsleitfaden für den Betrieb</h2>
<ul>
<li><strong>Zugriffsschutz:</strong> Rollenbasiertes Arbeiten mit getrennten Zuständigkeiten.</li>
<li><strong>Sitzungssicherheit:</strong> Session-Cookies mit sicheren Standardeinstellungen.</li>
<li><strong>Übertragung:</strong> Einsatz sicherer Protokolle und Schutz-Header für Webanfragen.</li>
<li><strong>Nachvollziehbarkeit:</strong> Protokollierung relevanter Änderungen und Aktionen.</li>
<li><strong>Datenschutz:</strong> Datenminimierung und dokumentierte Verarbeitungsprozesse.</li>
<li><strong>Kontinuität:</strong> Regelmäßige Backups und Wiederanlaufplanung.</li>
</ul>
</section>
<section class="next-step">
<h2>Nächster Schritt</h2>
<p>Für die Einführung empfiehlt sich ein kurzer Pilotbetrieb mit realen Beispieldaten, bevor die vollständige Übernahme in den Produktivbetrieb erfolgt.</p>
{% if 'username' in session %}
<a class="btn" href="{{ url_for('appointments') }}">Pilotstart planen</a>
{% else %}
<a class="btn" href="{{ url_for('login') }}">Login für Buchung</a>
{% endif %}
</section>
<style>
.page-hero { margin-bottom: 1.2rem; }
.grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); gap: 0.9rem; }
.card { background: #fff; border: 1px solid #d8dfd7; border-radius: 14px; padding: 1rem; box-shadow: 0 10px 24px rgba(25, 45, 41, 0.04); }
.card h2 { color: #265057; margin-bottom: 0.45rem; font-size: clamp(1.05rem, 1.8vw, 1.35rem); }
.security-box { margin-top: 0.9rem; background: linear-gradient(135deg, #f8f4eb 0%, #eef3eb 100%); border: 1px solid #d4dbd2; border-radius: 14px; padding: 1.1rem; }
.security-box h2 { color: #2a4d53; margin-bottom: 0.45rem; font-size: clamp(1.1rem, 2.2vw, 1.55rem); }
.security-box ul { margin: 0; padding-left: 1.1rem; color: #4a6267; display: grid; gap: 0.5rem; }
.next-step { margin-top: 0.9rem; background: #fff; border: 1px solid #d8dfd7; border-radius: 14px; padding: 1rem; box-shadow: 0 10px 24px rgba(25, 45, 41, 0.04); }
.next-step h2 { color: #265057; margin-bottom: 0.45rem; font-size: clamp(1.05rem, 1.8vw, 1.35rem); }
.btn { margin-top: 0.5rem; display: inline-flex; align-items: center; justify-content: center; border-radius: 999px; border: 1px solid #1d5a63; background: linear-gradient(120deg, #296f78 0%, #1a5057 100%); color: #fff; padding: 0.54rem 0.92rem; font-weight: 700; }
</style>
{% endblock %}