Add user authentication and registration features
- Implement login and registration HTML templates for user authentication. - Create user management functions in user.py for handling user data, including adding, deleting, and updating users. - Introduce password hashing and strength checking for secure user credentials. - Add terms of service and privacy policy pages to the website. - Enhance main page with dynamic content based on user session status.
This commit is contained in:
@@ -0,0 +1,206 @@
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% block title %}Blog verwalten{% endblock %}
|
||||
|
||||
{% block head %}
|
||||
{{ super() }}
|
||||
<style>
|
||||
.blog-admin-grid {
|
||||
display: grid;
|
||||
grid-template-columns: 0.7fr 1.3fr;
|
||||
gap: 1.2rem;
|
||||
}
|
||||
|
||||
.new-post-form {
|
||||
background: #ffffff;
|
||||
border: 1px solid #d4e0e9;
|
||||
border-radius: 16px;
|
||||
padding: 1.4rem;
|
||||
box-shadow: 0 14px 32px rgba(20, 39, 55, 0.06);
|
||||
height: fit-content;
|
||||
position: sticky;
|
||||
top: 100px;
|
||||
}
|
||||
|
||||
.new-post-form h2 {
|
||||
font-size: 1.2rem;
|
||||
color: #0f354d;
|
||||
margin: 0 0 0.9rem;
|
||||
}
|
||||
|
||||
.field {
|
||||
margin-bottom: 0.9rem;
|
||||
}
|
||||
|
||||
.field label {
|
||||
display: block;
|
||||
margin-bottom: 0.3rem;
|
||||
font-weight: 700;
|
||||
color: #1f4b65;
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
|
||||
.field input,
|
||||
.field textarea {
|
||||
width: 100%;
|
||||
border: 1px solid #c4d4e0;
|
||||
border-radius: 10px;
|
||||
padding: 0.65rem 0.72rem;
|
||||
font: inherit;
|
||||
color: #143f5d;
|
||||
background: #ffffff;
|
||||
}
|
||||
|
||||
.field textarea {
|
||||
min-height: 120px;
|
||||
resize: vertical;
|
||||
}
|
||||
|
||||
.field input:focus,
|
||||
.field textarea:focus {
|
||||
outline: none;
|
||||
border-color: #2f79a7;
|
||||
box-shadow: 0 0 0 3px rgba(58, 133, 180, 0.2);
|
||||
}
|
||||
|
||||
.submit-btn {
|
||||
width: 100%;
|
||||
border: none;
|
||||
border-radius: 999px;
|
||||
padding: 0.72rem;
|
||||
font-size: 0.95rem;
|
||||
font-weight: 700;
|
||||
color: #ffffff;
|
||||
background: linear-gradient(120deg, #0a5f8f 0%, #0b4567 100%);
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.posts-list {
|
||||
display: grid;
|
||||
gap: 0.8rem;
|
||||
}
|
||||
|
||||
.post-card {
|
||||
background: #ffffff;
|
||||
border: 1px solid #d4e0e9;
|
||||
border-radius: 14px;
|
||||
padding: 1.1rem;
|
||||
box-shadow: 0 10px 28px rgba(20, 40, 55, 0.05);
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: flex-start;
|
||||
gap: 1rem;
|
||||
}
|
||||
|
||||
.post-info h3 {
|
||||
font-size: 1.05rem;
|
||||
color: #113d59;
|
||||
margin: 0 0 0.25rem;
|
||||
}
|
||||
|
||||
.post-info p {
|
||||
margin: 0.2rem 0;
|
||||
font-size: 0.9rem;
|
||||
color: #5a7a8f;
|
||||
}
|
||||
|
||||
.post-meta {
|
||||
font-size: 0.8rem;
|
||||
color: #7a8fa2;
|
||||
margin-top: 0.3rem;
|
||||
}
|
||||
|
||||
.delete-form {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.delete-btn {
|
||||
border: none;
|
||||
border-radius: 6px;
|
||||
padding: 0.4rem 0.7rem;
|
||||
font-size: 0.8rem;
|
||||
font-weight: 700;
|
||||
color: #ffffff;
|
||||
background: linear-gradient(120deg, #a74444 0%, #8a3535 100%);
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
@media (max-width: 980px) {
|
||||
.blog-admin-grid {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
.new-post-form {
|
||||
position: static;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<h1 style="font-size: 2rem; color: #0f354d; margin-bottom: 1.2rem;">Blog verwalten</h1>
|
||||
|
||||
<section class="blog-admin-grid">
|
||||
<aside class="new-post-form">
|
||||
<h2>Neuer Beitrag</h2>
|
||||
<form method="POST" action="{{ url_for('admin_blog') }}">
|
||||
<div class="field">
|
||||
<label for="title">Titel</label>
|
||||
<input
|
||||
id="title"
|
||||
name="title"
|
||||
type="text"
|
||||
placeholder="Beitragstitel"
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
<div class="field">
|
||||
<label for="excerpt">Zusammenfassung</label>
|
||||
<textarea
|
||||
id="excerpt"
|
||||
name="excerpt"
|
||||
placeholder="Optionale Kurzbeschreibung"
|
||||
></textarea>
|
||||
</div>
|
||||
<div class="field">
|
||||
<label for="content">Inhalt</label>
|
||||
<textarea
|
||||
id="content"
|
||||
name="content"
|
||||
placeholder="Beitrag schreiben..."
|
||||
required
|
||||
></textarea>
|
||||
</div>
|
||||
<input type="hidden" name="action" value="create" />
|
||||
<button type="submit" class="submit-btn">Veroeffentlichen</button>
|
||||
</form>
|
||||
</aside>
|
||||
|
||||
<article>
|
||||
<h2 style="font-size: 1.2rem; color: #0f354d; margin: 0 0 0.8rem;">Veroeffentlichte Beitraege</h2>
|
||||
<section class="posts-list">
|
||||
{% if posts %}
|
||||
{% for post in posts %}
|
||||
<article class="post-card">
|
||||
<div class="post-info">
|
||||
<h3>{{ post.title }}</h3>
|
||||
<p>{{ post.excerpt }}</p>
|
||||
<div class="post-meta">
|
||||
<strong>Autor:</strong> {{ post.author }}<br />
|
||||
<strong>Veroeffentlicht:</strong> {{ post.created_at[:10] }}
|
||||
</div>
|
||||
</div>
|
||||
<form method="POST" action="{{ url_for('admin_blog') }}" class="delete-form">
|
||||
<input type="hidden" name="action" value="delete" />
|
||||
<input type="hidden" name="post_id" value="{{ post.id }}" />
|
||||
<button type="submit" class="delete-btn" onclick="return confirm('Sicher?')">Loeschen</button>
|
||||
</form>
|
||||
</article>
|
||||
{% endfor %}
|
||||
{% else %}
|
||||
<p>Noch keine Beitraege veroeffentlicht.</p>
|
||||
{% endif %}
|
||||
</section>
|
||||
</article>
|
||||
</section>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,214 @@
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% block title %}Admin Dashboard{% endblock %}
|
||||
|
||||
{% block head %}
|
||||
{{ super() }}
|
||||
<style>
|
||||
.admin-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, minmax(0, 1fr));
|
||||
gap: 1rem;
|
||||
margin-bottom: 1.2rem;
|
||||
}
|
||||
|
||||
.stat-card {
|
||||
background: #ffffff;
|
||||
border: 1px solid #d4e0e9;
|
||||
border-radius: 14px;
|
||||
padding: 1.2rem;
|
||||
box-shadow: 0 10px 28px rgba(20, 40, 55, 0.05);
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.stat-value {
|
||||
font-size: 2.2rem;
|
||||
font-weight: 700;
|
||||
color: #0a5c88;
|
||||
margin-bottom: 0.3rem;
|
||||
}
|
||||
|
||||
.stat-label {
|
||||
font-size: 0.9rem;
|
||||
color: #5a7a8f;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.appointments-section {
|
||||
background: #ffffff;
|
||||
border: 1px solid #d4e0e9;
|
||||
border-radius: 16px;
|
||||
padding: 1.4rem;
|
||||
box-shadow: 0 14px 32px rgba(20, 39, 55, 0.06);
|
||||
}
|
||||
|
||||
.appointments-section h2 {
|
||||
font-size: 1.3rem;
|
||||
color: #0f354d;
|
||||
margin-bottom: 0.8rem;
|
||||
}
|
||||
|
||||
.appointment-card {
|
||||
border: 1px solid #d8e3ec;
|
||||
border-radius: 12px;
|
||||
padding: 1rem;
|
||||
margin-bottom: 0.8rem;
|
||||
background: #f9fbfd;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: flex-start;
|
||||
gap: 1rem;
|
||||
}
|
||||
|
||||
.appointment-info > strong {
|
||||
display: block;
|
||||
color: #113d59;
|
||||
margin-bottom: 0.25rem;
|
||||
}
|
||||
|
||||
.appointment-info p {
|
||||
margin: 0.15rem 0;
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
|
||||
.appointment-status {
|
||||
display: inline-block;
|
||||
border-radius: 999px;
|
||||
padding: 0.25rem 0.6rem;
|
||||
font-size: 0.8rem;
|
||||
font-weight: 700;
|
||||
margin-top: 0.35rem;
|
||||
}
|
||||
|
||||
.status-pending {
|
||||
border: 1px solid #fba316;
|
||||
background: #fffbf0;
|
||||
color: #b8730f;
|
||||
}
|
||||
|
||||
.status-confirmed {
|
||||
border: 1px solid #0e9f6e;
|
||||
background: #f0fdf4;
|
||||
color: #0b5c47;
|
||||
}
|
||||
|
||||
.status-rejected {
|
||||
border: 1px solid #d3413e;
|
||||
background: #fdf5f5;
|
||||
color: #8b2a27;
|
||||
}
|
||||
|
||||
.appointment-actions {
|
||||
display: flex;
|
||||
gap: 0.4rem;
|
||||
}
|
||||
|
||||
.action-form {
|
||||
display: grid;
|
||||
gap: 0.6rem;
|
||||
}
|
||||
|
||||
.response-input {
|
||||
width: 100%;
|
||||
min-height: 60px;
|
||||
border: 1px solid #c4d4e0;
|
||||
border-radius: 8px;
|
||||
padding: 0.5rem;
|
||||
font-family: inherit;
|
||||
font-size: 0.85rem;
|
||||
resize: vertical;
|
||||
}
|
||||
|
||||
.action-btn {
|
||||
border: none;
|
||||
border-radius: 6px;
|
||||
padding: 0.4rem 0.7rem;
|
||||
font-size: 0.85rem;
|
||||
font-weight: 700;
|
||||
cursor: pointer;
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
.confirm-btn {
|
||||
background: linear-gradient(120deg, #0a7c4e 0%, #065f3f 100%);
|
||||
}
|
||||
|
||||
.reject-btn {
|
||||
background: linear-gradient(120deg, #a74444 0%, #8a3535 100%);
|
||||
}
|
||||
|
||||
@media (max-width: 980px) {
|
||||
.admin-grid {
|
||||
grid-template-columns: 1fr 1fr;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 600px) {
|
||||
.admin-grid {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
.appointment-card {
|
||||
flex-direction: column;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<h1 style="font-size: 2rem; color: #0f354d; margin-bottom: 1rem;">Admin Dashboard</h1>
|
||||
|
||||
<section class="admin-grid">
|
||||
<article class="stat-card">
|
||||
<div class="stat-value">{{ status_counts.Angefragt }}</div>
|
||||
<div class="stat-label">Neue Anfragen</div>
|
||||
</article>
|
||||
<article class="stat-card">
|
||||
<div class="stat-value">{{ status_counts.Bestaetigt }}</div>
|
||||
<div class="stat-label">Bestaetigt</div>
|
||||
</article>
|
||||
<article class="stat-card">
|
||||
<div class="stat-value">{{ total_posts }}</div>
|
||||
<div class="stat-label">Blog-Beitraege</div>
|
||||
</article>
|
||||
</section>
|
||||
|
||||
<section class="appointments-section">
|
||||
<h2>Terminanfragen verwalten</h2>
|
||||
{% if appointments %}
|
||||
{% for appointment in appointments %}
|
||||
<article class="appointment-card">
|
||||
<div class="appointment-info">
|
||||
<strong>{{ appointment.display_name }} - {{ appointment.subject }}</strong>
|
||||
<p><strong>Datum:</strong> {{ appointment.date }} um {{ appointment.time }}</p>
|
||||
<p><strong>Angefragt:</strong> {{ appointment.created_at[:10] }}</p>
|
||||
{% if appointment.note %}
|
||||
<p><strong>Notiz:</strong> {{ appointment.note }}</p>
|
||||
{% endif %}
|
||||
{% if appointment.response %}
|
||||
<p><strong>Antwort:</strong> {{ appointment.response }}</p>
|
||||
{% endif %}
|
||||
<span class="appointment-status status-{{ appointment.status|lower|replace('Ä', 'ae')|replace('ö', 'oe')|replace('ü', 'ue') if appointment.status == 'Angefragt' else 'confirmed' if appointment.status == 'Bestaetigt' else 'rejected' }}">{{ appointment.status }}</span>
|
||||
</div>
|
||||
{% if appointment.status == 'Angefragt' %}
|
||||
<div class="appointment-actions">
|
||||
<form method="POST" action="{{ url_for('update_appointment', appointment_id=appointment.id) }}" class="action-form" style="min-width: 280px;">
|
||||
<textarea class="response-input" name="response" placeholder="Antwort (optional)"></textarea>
|
||||
<div style="display: flex; gap: 0.4rem;">
|
||||
<button type="submit" name="action" value="confirm" class="confirm-btn action-btn">Bestaetigen</button>
|
||||
<button type="submit" name="action" value="reject" class="reject-btn action-btn">Ablehnen</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
{% endif %}
|
||||
</article>
|
||||
{% endfor %}
|
||||
{% else %}
|
||||
<p>Keine Terminanfragen vorhanden.</p>
|
||||
{% endif %}
|
||||
</section>
|
||||
|
||||
<section style="margin-top: 1.5rem;">
|
||||
<a href="{{ url_for('admin_blog') }}" style="color: #ffffff; background: linear-gradient(120deg, #0b5b89 0%, #0b4262 100%); padding: 0.68rem 1.15rem; border-radius: 999px; font-weight: 700; display: inline-block; text-decoration: none;">Blog verwalten</a>
|
||||
</section>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,302 @@
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% block title %}Termin anfragen{% endblock %}
|
||||
|
||||
{% block head %}
|
||||
{{ super() }}
|
||||
<style>
|
||||
.appointments-grid {
|
||||
display: grid;
|
||||
grid-template-columns: 1.2fr 0.8fr;
|
||||
gap: 1rem;
|
||||
align-items: start;
|
||||
}
|
||||
|
||||
.panel {
|
||||
background: #ffffff;
|
||||
border: 1px solid #d4e0e9;
|
||||
border-radius: 16px;
|
||||
padding: 1.2rem;
|
||||
box-shadow: 0 14px 32px rgba(20, 39, 55, 0.06);
|
||||
}
|
||||
|
||||
.calendar-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 0.8rem;
|
||||
margin-bottom: 0.9rem;
|
||||
}
|
||||
|
||||
.calendar-header h1 {
|
||||
font-size: 1.5rem;
|
||||
color: #133f5d;
|
||||
}
|
||||
|
||||
.month-nav {
|
||||
display: inline-flex;
|
||||
gap: 0.4rem;
|
||||
}
|
||||
|
||||
.month-nav a {
|
||||
border-radius: 999px;
|
||||
border: 1px solid #bfd1de;
|
||||
padding: 0.38rem 0.7rem;
|
||||
color: #185170;
|
||||
font-weight: 700;
|
||||
background: #ffffff;
|
||||
}
|
||||
|
||||
.weekday-row,
|
||||
.day-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(7, minmax(0, 1fr));
|
||||
gap: 0.3rem;
|
||||
}
|
||||
|
||||
.weekday {
|
||||
text-align: center;
|
||||
font-size: 0.82rem;
|
||||
font-weight: 700;
|
||||
color: #587689;
|
||||
padding-bottom: 0.2rem;
|
||||
}
|
||||
|
||||
.day {
|
||||
min-height: 74px;
|
||||
border: 1px solid #d8e3ec;
|
||||
border-radius: 10px;
|
||||
background: #f9fcff;
|
||||
color: #0f3f5d;
|
||||
cursor: pointer;
|
||||
font-weight: 700;
|
||||
transition: all 0.15s ease;
|
||||
}
|
||||
|
||||
.day:hover {
|
||||
border-color: #9ec0d6;
|
||||
transform: translateY(-1px);
|
||||
}
|
||||
|
||||
.day.empty {
|
||||
background: #f2f6f9;
|
||||
border-style: dashed;
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.day.today {
|
||||
border-color: #2d7fab;
|
||||
}
|
||||
|
||||
.day.selected {
|
||||
background: linear-gradient(140deg, #0d5c88 0%, #0a4464 100%);
|
||||
border-color: #0d5c88;
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
.booking-form h2,
|
||||
.appointment-list h2 {
|
||||
font-size: 1.2rem;
|
||||
color: #143f5e;
|
||||
margin: 0 0 0.8rem;
|
||||
}
|
||||
|
||||
.selected-date-badge {
|
||||
display: inline-block;
|
||||
margin-bottom: 0.8rem;
|
||||
border-radius: 999px;
|
||||
padding: 0.28rem 0.6rem;
|
||||
border: 1px solid #bfd2df;
|
||||
color: #23526c;
|
||||
font-weight: 700;
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
|
||||
.field {
|
||||
margin-bottom: 0.8rem;
|
||||
}
|
||||
|
||||
.field label {
|
||||
display: block;
|
||||
margin-bottom: 0.3rem;
|
||||
font-weight: 700;
|
||||
color: #1f4b65;
|
||||
}
|
||||
|
||||
.field input,
|
||||
.field textarea {
|
||||
width: 100%;
|
||||
border: 1px solid #c4d4e0;
|
||||
border-radius: 10px;
|
||||
padding: 0.65rem 0.72rem;
|
||||
font: inherit;
|
||||
color: #143f5d;
|
||||
background: #ffffff;
|
||||
}
|
||||
|
||||
.field textarea {
|
||||
min-height: 86px;
|
||||
resize: vertical;
|
||||
}
|
||||
|
||||
.submit-btn {
|
||||
width: 100%;
|
||||
border: none;
|
||||
border-radius: 999px;
|
||||
padding: 0.74rem;
|
||||
font-size: 1rem;
|
||||
font-weight: 700;
|
||||
color: #ffffff;
|
||||
background: linear-gradient(120deg, #0a5f8f 0%, #0b4567 100%);
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.entry {
|
||||
border: 1px solid #d7e2ea;
|
||||
border-radius: 12px;
|
||||
padding: 0.72rem;
|
||||
margin-bottom: 0.55rem;
|
||||
background: #f9fbfd;
|
||||
}
|
||||
|
||||
.entry strong {
|
||||
color: #113d59;
|
||||
}
|
||||
|
||||
.entry p {
|
||||
margin-top: 0.18rem;
|
||||
font-size: 0.92rem;
|
||||
}
|
||||
|
||||
.status {
|
||||
display: inline-block;
|
||||
margin-top: 0.45rem;
|
||||
border-radius: 999px;
|
||||
border: 1px solid #c9d7e2;
|
||||
padding: 0.15rem 0.55rem;
|
||||
font-size: 0.8rem;
|
||||
color: #2f5f79;
|
||||
font-weight: 700;
|
||||
background: #eef4f8;
|
||||
}
|
||||
|
||||
@media (max-width: 960px) {
|
||||
.appointments-grid {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<section class="appointments-grid">
|
||||
<article class="panel">
|
||||
<div class="calendar-header">
|
||||
<h1>{{ month_name }} {{ year }}</h1>
|
||||
<div class="month-nav">
|
||||
<a href="{{ url_for('appointments', month=previous_month, year=previous_year) }}">Zurueck</a>
|
||||
<a href="{{ url_for('appointments', month=next_month, year=next_year) }}">Weiter</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="weekday-row" aria-hidden="true">
|
||||
<div class="weekday">Mo</div>
|
||||
<div class="weekday">Di</div>
|
||||
<div class="weekday">Mi</div>
|
||||
<div class="weekday">Do</div>
|
||||
<div class="weekday">Fr</div>
|
||||
<div class="weekday">Sa</div>
|
||||
<div class="weekday">So</div>
|
||||
</div>
|
||||
|
||||
<div class="day-grid" id="dayGrid">
|
||||
{% for week in month_grid %}
|
||||
{% for day in week %}
|
||||
{% if day == 0 %}
|
||||
<button type="button" class="day empty" disabled></button>
|
||||
{% else %}
|
||||
{% set day_iso = "%04d-%02d-%02d"|format(year, month, day) %}
|
||||
<button
|
||||
type="button"
|
||||
class="day {% if day_iso == today_iso %}today{% endif %}"
|
||||
data-date="{{ day_iso }}"
|
||||
>
|
||||
{{ day }}
|
||||
</button>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% endfor %}
|
||||
</div>
|
||||
</article>
|
||||
|
||||
<aside class="panel booking-form">
|
||||
<h2>Termin anfragen</h2>
|
||||
<span class="selected-date-badge" id="selectedDateBadge">Kein Datum gewaehlt</span>
|
||||
<form method="POST" action="{{ url_for('appointments', month=month, year=year) }}">
|
||||
<input type="hidden" id="selectedDateInput" name="selected_date" required>
|
||||
<div class="field">
|
||||
<label for="appointment_time">Uhrzeit</label>
|
||||
<input id="appointment_time" name="appointment_time" type="time" required>
|
||||
</div>
|
||||
<div class="field">
|
||||
<label for="subject">Betreff</label>
|
||||
<input id="subject" name="subject" type="text" placeholder="z. B. Projekt Kickoff" required>
|
||||
</div>
|
||||
<div class="field">
|
||||
<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>
|
||||
</form>
|
||||
</aside>
|
||||
</section>
|
||||
|
||||
<section class="panel appointment-list" style="margin-top: 1rem;">
|
||||
<h2>Meine Terminanfragen</h2>
|
||||
{% if user_appointments %}
|
||||
{% for item in user_appointments %}
|
||||
<article class="entry">
|
||||
<strong>{{ item.date }} um {{ item.time }} - {{ item.subject }}</strong>
|
||||
{% if item.note %}
|
||||
<p>{{ item.note }}</p>
|
||||
{% endif %}
|
||||
{% if item.response %}
|
||||
<p><strong>Admin-Antwort:</strong> {{ item.response }}</p>
|
||||
{% endif %}
|
||||
<span class="status">{{ item.status }}</span>
|
||||
</article>
|
||||
{% endfor %}
|
||||
{% else %}
|
||||
<p>Noch keine Anfragen vorhanden.</p>
|
||||
{% endif %}
|
||||
</section>
|
||||
|
||||
<script>
|
||||
(function () {
|
||||
const dayGrid = document.getElementById("dayGrid");
|
||||
const selectedDateInput = document.getElementById("selectedDateInput");
|
||||
const selectedDateBadge = document.getElementById("selectedDateBadge");
|
||||
|
||||
function setSelection(dateValue, button) {
|
||||
selectedDateInput.value = dateValue;
|
||||
selectedDateBadge.textContent = "Ausgewaehlt: " + dateValue;
|
||||
|
||||
dayGrid.querySelectorAll(".day").forEach(function (node) {
|
||||
node.classList.remove("selected");
|
||||
});
|
||||
|
||||
if (button) {
|
||||
button.classList.add("selected");
|
||||
}
|
||||
}
|
||||
|
||||
dayGrid.addEventListener("click", function (event) {
|
||||
const target = event.target.closest(".day[data-date]");
|
||||
if (!target) {
|
||||
return;
|
||||
}
|
||||
setSelection(target.dataset.date, target);
|
||||
});
|
||||
})();
|
||||
</script>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,325 @@
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=5.0, user-scalable=yes">
|
||||
<meta name="mobile-web-app-capable" content="yes">
|
||||
<meta name="apple-mobile-web-app-capable" content="yes">
|
||||
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
|
||||
<title>{% block title %}IT Loesungen{% endblock %}</title>
|
||||
{% block head %}
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@400;500;600;700&family=Source+Sans+3:wght@400;500;600&display=swap" rel="stylesheet">
|
||||
<style>
|
||||
:root {
|
||||
--bg-main: #f5f8fa;
|
||||
--bg-soft: #e8eef2;
|
||||
--surface: #ffffff;
|
||||
--text-main: #112332;
|
||||
--text-soft: #466176;
|
||||
--line: #d8e1e8;
|
||||
--brand: #0a4c74;
|
||||
--brand-strong: #073754;
|
||||
--accent: #f28c28;
|
||||
--radius-md: 14px;
|
||||
--shadow-sm: 0 10px 30px rgba(17, 35, 50, 0.08);
|
||||
}
|
||||
* { box-sizing: border-box; }
|
||||
|
||||
html,
|
||||
body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
min-height: 100%;
|
||||
font-family: "Source Sans 3", system-ui, sans-serif;
|
||||
color: var(--text-main);
|
||||
background: radial-gradient(circle at 85% -10%, #c5d8e5 0%, transparent 35%),
|
||||
radial-gradient(circle at -10% 50%, #dce8ef 0%, transparent 42%),
|
||||
var(--bg-main);
|
||||
}
|
||||
|
||||
h1, h2, h3, h4 {
|
||||
margin: 0;
|
||||
font-family: "Space Grotesk", system-ui, sans-serif;
|
||||
line-height: 1.08;
|
||||
}
|
||||
|
||||
p {
|
||||
margin: 0;
|
||||
line-height: 1.55;
|
||||
color: var(--text-soft);
|
||||
}
|
||||
|
||||
a {
|
||||
color: inherit;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
img {
|
||||
max-width: 100%;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.site-shell {
|
||||
width: min(1240px, calc(100% - 2rem));
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.site-nav {
|
||||
position: sticky;
|
||||
top: 0;
|
||||
z-index: 30;
|
||||
backdrop-filter: blur(10px);
|
||||
background: rgba(245, 248, 250, 0.86);
|
||||
border-bottom: 1px solid var(--line);
|
||||
}
|
||||
|
||||
.site-nav-inner {
|
||||
min-height: 78px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 1rem;
|
||||
}
|
||||
|
||||
.brand {
|
||||
font-family: "Space Grotesk", system-ui, sans-serif;
|
||||
font-size: 1.1rem;
|
||||
font-weight: 700;
|
||||
letter-spacing: 0.08em;
|
||||
text-transform: uppercase;
|
||||
color: var(--brand-strong);
|
||||
}
|
||||
|
||||
.nav-links {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 1rem;
|
||||
font-weight: 600;
|
||||
color: var(--text-soft);
|
||||
}
|
||||
|
||||
.nav-links a:hover {
|
||||
color: var(--brand);
|
||||
}
|
||||
|
||||
.nav-actions {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.6rem;
|
||||
}
|
||||
|
||||
.nav-btn {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border-radius: 999px;
|
||||
border: 1px solid #bcd0de;
|
||||
padding: 0.48rem 0.95rem;
|
||||
font-weight: 700;
|
||||
color: #0e425f;
|
||||
background: #ffffff;
|
||||
transition: transform 0.15s ease;
|
||||
}
|
||||
|
||||
.nav-btn:hover {
|
||||
transform: translateY(-1px);
|
||||
}
|
||||
|
||||
.nav-btn.primary {
|
||||
color: #ffffff;
|
||||
border-color: #0a4c74;
|
||||
background: linear-gradient(120deg, #0b5b89 0%, #0b4262 100%);
|
||||
}
|
||||
|
||||
.main-wrap {
|
||||
padding: 2rem 0 3.4rem;
|
||||
}
|
||||
|
||||
.flashes {
|
||||
margin-bottom: 1rem;
|
||||
display: grid;
|
||||
gap: 0.75rem;
|
||||
}
|
||||
|
||||
.flash {
|
||||
padding: 0.8rem 1rem;
|
||||
border-radius: 10px;
|
||||
border: 1px solid var(--line);
|
||||
background: var(--surface);
|
||||
box-shadow: var(--shadow-sm);
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.flash.success { border-left: 5px solid #0e9f6e; }
|
||||
.flash.error { border-left: 5px solid #d3413e; }
|
||||
.flash.info { border-left: 5px solid var(--brand); }
|
||||
|
||||
@media (max-width: 820px) {
|
||||
.site-nav-inner {
|
||||
min-height: 64px;
|
||||
}
|
||||
|
||||
.nav-links {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.nav-actions {
|
||||
gap: 0.4rem;
|
||||
}
|
||||
|
||||
.nav-btn {
|
||||
padding: 0.42rem 0.72rem;
|
||||
font-size: 0.85rem;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
{% endblock %}
|
||||
</head>
|
||||
<body>
|
||||
<nav class="site-nav">
|
||||
<div class="site-shell site-nav-inner">
|
||||
<a class="brand" href="{{ url_for('default') }}">Invario</a>
|
||||
<div class="nav-links" aria-label="Main Navigation">
|
||||
<a href="{{ url_for('default') }}#leistungen">Dienstleistungen</a>
|
||||
<a href="{{ url_for('default') }}#projekte">Projekte</a>
|
||||
<a href="{{ url_for('default') }}#team">Team</a>
|
||||
<a href="{{ url_for('default') }}#kontakt">Kontakt</a>
|
||||
</div>
|
||||
<div class="nav-actions">
|
||||
{% if 'username' in session %}
|
||||
<a class="nav-btn" href="{{ url_for('blog') }}">Blog</a>
|
||||
<a class="nav-btn" href="{{ url_for('appointments') }}">Termin anfragen</a>
|
||||
{% if session.get('is_admin') %}
|
||||
<a class="nav-btn" href="{{ url_for('admin_dashboard') }}">Admin</a>
|
||||
{% endif %}
|
||||
<a class="nav-btn" href="{{ url_for('logout') }}">Logout</a>
|
||||
{% else %}
|
||||
<a class="nav-btn" href="{{ url_for('blog') }}">Blog</a>
|
||||
<a class="nav-btn" href="{{ url_for('login') }}">Login</a>
|
||||
<a class="nav-btn primary" href="{{ url_for('register') }}">Registrieren</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
<main class="site-shell main-wrap">
|
||||
{% with messages = get_flashed_messages(with_categories=true) %}
|
||||
{% if messages %}
|
||||
<div class="flashes">
|
||||
{% for category, message in messages %}
|
||||
<div class="flash {{ category }}">{{ message }}</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endwith %}
|
||||
{% block content %}{% endblock %}
|
||||
</main>
|
||||
<footer class="site-footer">
|
||||
<div class="site-shell footer-inner">
|
||||
<div class="footer-content">
|
||||
<div class="footer-section">
|
||||
<h4>Über uns</h4>
|
||||
<p>Wir bieten professionelle IT-Lösungen und Dienstleistungen für Ihr Unternehmen.</p>
|
||||
</div>
|
||||
<div class="footer-section">
|
||||
<h4>Schnelllinks</h4>
|
||||
<ul class="footer-links">
|
||||
<li><a href="{{ url_for('default') }}">Startseite</a></li>
|
||||
<li><a href="{{ url_for('blog') }}">Blog</a></li>
|
||||
{% if 'username' in session %}
|
||||
<li><a href="{{ url_for('appointments') }}">Termine</a></li>
|
||||
{% endif %}
|
||||
</ul>
|
||||
</div>
|
||||
<div class="footer-section">
|
||||
<h4>Rechtliches</h4>
|
||||
<ul class="footer-links">
|
||||
<li><a href="{{ url_for('datenschutz') }}">Datenschutz</a></li>
|
||||
<li><a href="{{ url_for('impressum') }}">Impressum</a></li>
|
||||
<li><a href="{{ url_for('nutzungsbedingungen') }}">Nutzungsbedingungen</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div class="footer-bottom">
|
||||
<p>© 2026 Invario. Alle Rechte vorbehalten.</p>
|
||||
</div>
|
||||
</div>
|
||||
<style>
|
||||
.site-footer {
|
||||
background: linear-gradient(135deg, var(--brand-strong) 0%, #0a4c74 100%);
|
||||
color: #ffffff;
|
||||
margin-top: 4rem;
|
||||
padding: 3rem 0 1.5rem;
|
||||
border-top: 1px solid var(--line);
|
||||
}
|
||||
|
||||
.footer-inner {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
|
||||
gap: 2rem;
|
||||
margin-bottom: 2rem;
|
||||
}
|
||||
|
||||
.footer-section {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.75rem;
|
||||
}
|
||||
|
||||
.footer-section h4 {
|
||||
font-size: 1rem;
|
||||
font-weight: 700;
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
.footer-section p {
|
||||
color: rgba(255, 255, 255, 0.8);
|
||||
font-size: 0.95rem;
|
||||
}
|
||||
|
||||
.footer-links {
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.5rem;
|
||||
}
|
||||
|
||||
.footer-links a {
|
||||
color: rgba(255, 255, 255, 0.8);
|
||||
font-size: 0.95rem;
|
||||
transition: color 0.2s ease;
|
||||
}
|
||||
|
||||
.footer-links a:hover {
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
.footer-bottom {
|
||||
text-align: center;
|
||||
padding-top: 1.5rem;
|
||||
border-top: 1px solid rgba(255, 255, 255, 0.1);
|
||||
}
|
||||
|
||||
.footer-bottom p {
|
||||
color: rgba(255, 255, 255, 0.7);
|
||||
font-size: 0.9rem;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
@media (max-width: 700px) {
|
||||
.footer-inner {
|
||||
grid-template-columns: 1fr;
|
||||
gap: 1.5rem;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</footer>
|
||||
<!-- Mobile compatibility scripts -->
|
||||
<script src="{{ url_for('static', filename='js/mobile_compatibility.js') }}"></script>
|
||||
<script src="{{ url_for('static', filename='js/ios_fixes.js') }}"></script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,117 @@
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% block title %}Blog{% endblock %}
|
||||
|
||||
{% block head %}
|
||||
{{ super() }}
|
||||
<style>
|
||||
.blog-header {
|
||||
text-align: center;
|
||||
margin-bottom: 2rem;
|
||||
}
|
||||
|
||||
.blog-header h1 {
|
||||
font-size: 2.4rem;
|
||||
color: #0f354d;
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
.blog-header p {
|
||||
font-size: 1.05rem;
|
||||
color: #5a7a8f;
|
||||
}
|
||||
|
||||
.posts-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));
|
||||
gap: 1.2rem;
|
||||
margin-bottom: 1.5rem;
|
||||
}
|
||||
|
||||
.post-link {
|
||||
text-decoration: none;
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
.post-item {
|
||||
background: #ffffff;
|
||||
border: 1px solid #d4e0e9;
|
||||
border-radius: 14px;
|
||||
padding: 1.2rem;
|
||||
box-shadow: 0 10px 28px rgba(20, 40, 55, 0.05);
|
||||
transition: transform 0.2s ease, box-shadow 0.2s ease;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.post-link:hover .post-item {
|
||||
transform: translateY(-3px);
|
||||
box-shadow: 0 16px 40px rgba(20, 40, 55, 0.12);
|
||||
}
|
||||
|
||||
.post-item h2 {
|
||||
font-size: 1.2rem;
|
||||
color: #113d59;
|
||||
margin: 0 0 0.5rem;
|
||||
}
|
||||
|
||||
.post-item p {
|
||||
margin: 0;
|
||||
color: #5a7a8f;
|
||||
font-size: 0.95rem;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.post-meta {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-top: 0.8rem;
|
||||
padding-top: 0.8rem;
|
||||
border-top: 1px solid #e8f0f6;
|
||||
font-size: 0.8rem;
|
||||
color: #7a8fa2;
|
||||
}
|
||||
|
||||
.read-more {
|
||||
color: #0a5c88;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.posts-grid {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
.blog-header h1 {
|
||||
font-size: 1.8rem;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<section class="blog-header">
|
||||
<h1>Blog</h1>
|
||||
<p>Neuigkeiten und Insights rund um IT-Loesungen und Projekte</p>
|
||||
</section>
|
||||
|
||||
{% if posts %}
|
||||
<section class="posts-grid">
|
||||
{% for post in posts %}
|
||||
<a href="{{ url_for('blog_post', post_id=post.id) }}" class="post-link">
|
||||
<article class="post-item">
|
||||
<h2>{{ post.title }}</h2>
|
||||
<p>{{ post.excerpt }}</p>
|
||||
<div class="post-meta">
|
||||
<span>{{ post.created_at[:10] }}</span>
|
||||
<span class="read-more">Zum Beitrag →</span>
|
||||
</div>
|
||||
</article>
|
||||
</a>
|
||||
{% endfor %}
|
||||
</section>
|
||||
{% else %}
|
||||
<p style="text-align: center; color: #5a7a8f; padding: 2rem 0;">Noch keine Beitraege veroeffentlicht.</p>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,127 @@
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% block title %}{{ post.title }}{% endblock %}
|
||||
|
||||
{% block head %}
|
||||
{{ super() }}
|
||||
<style>
|
||||
.post-container {
|
||||
max-width: 760px;
|
||||
margin: 0 auto;
|
||||
background: #ffffff;
|
||||
border: 1px solid #d4e0e9;
|
||||
border-radius: 16px;
|
||||
padding: 2rem;
|
||||
box-shadow: 0 14px 32px rgba(20, 39, 55, 0.06);
|
||||
}
|
||||
|
||||
.post-header {
|
||||
margin-bottom: 1.5rem;
|
||||
padding-bottom: 1.2rem;
|
||||
border-bottom: 1px solid #e8f0f6;
|
||||
}
|
||||
|
||||
.post-header h1 {
|
||||
font-size: 2.2rem;
|
||||
color: #0f354d;
|
||||
margin: 0 0 0.6rem;
|
||||
}
|
||||
|
||||
.post-header-meta {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 1rem;
|
||||
color: #7a8fa2;
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
|
||||
.author-badge {
|
||||
display: inline-block;
|
||||
border-radius: 999px;
|
||||
padding: 0.25rem 0.6rem;
|
||||
background: #eef4f8;
|
||||
border: 1px solid #bcd0de;
|
||||
color: #185170;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.post-content {
|
||||
line-height: 1.8;
|
||||
color: #2f4556;
|
||||
font-size: 1.05rem;
|
||||
}
|
||||
|
||||
.post-content h2 {
|
||||
font-size: 1.5rem;
|
||||
color: #113d59;
|
||||
margin: 1.5rem 0 0.8rem;
|
||||
}
|
||||
|
||||
.post-content h3 {
|
||||
font-size: 1.2rem;
|
||||
color: #113d59;
|
||||
margin: 1.2rem 0 0.6rem;
|
||||
}
|
||||
|
||||
.post-content p {
|
||||
margin: 0 0 1rem;
|
||||
}
|
||||
|
||||
.post-content ul,
|
||||
.post-content ol {
|
||||
margin: 0 0 1rem 1.5rem;
|
||||
}
|
||||
|
||||
.post-content li {
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
.back-link {
|
||||
display: inline-block;
|
||||
margin-top: 1rem;
|
||||
padding: 0.6rem 1rem;
|
||||
border-radius: 999px;
|
||||
border: 1px solid #bcd0de;
|
||||
color: #0a5c88;
|
||||
font-weight: 700;
|
||||
text-decoration: none;
|
||||
transition: transform 0.15s ease;
|
||||
}
|
||||
|
||||
.back-link:hover {
|
||||
transform: translateY(-1px);
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.post-container {
|
||||
padding: 1.4rem;
|
||||
}
|
||||
|
||||
.post-header h1 {
|
||||
font-size: 1.6rem;
|
||||
}
|
||||
|
||||
.post-content {
|
||||
font-size: 1rem;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<article class="post-container">
|
||||
<header class="post-header">
|
||||
<h1>{{ post.title }}</h1>
|
||||
<div class="post-header-meta">
|
||||
<span class="author-badge">{{ post.author }}</span>
|
||||
<span>{{ post.created_at[:10] }}</span>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<section class="post-content">
|
||||
{{ post.content }}
|
||||
</section>
|
||||
|
||||
<a href="{{ url_for('blog') }}" class="back-link">← Zurueck zum Blog</a>
|
||||
</article>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,238 @@
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% block title %}Datenschutz | Invario{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="legal-page">
|
||||
<div class="legal-header">
|
||||
<h1>Datenschutzerklärung</h1>
|
||||
<p>Gültig ab: 1. Januar 2026</p>
|
||||
</div>
|
||||
|
||||
<div class="legal-content">
|
||||
<section>
|
||||
<h2>1. Verantwortlicher</h2>
|
||||
<p>Verantwortlich für die Datenverarbeitung ist:</p>
|
||||
<p>
|
||||
Invario GmbH<br>
|
||||
Musterstraße 123<br>
|
||||
12345 Musterstadt<br>
|
||||
Deutschland<br>
|
||||
E-Mail: info@invario.de
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2>2. Datenschutzbeauftragter</h2>
|
||||
<p>Unseren Datenschutzbeauftragten erreichen Sie unter:</p>
|
||||
<p>
|
||||
datenschutz@invario.de
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2>3. Erhobene Daten</h2>
|
||||
<p>Wir erheben und verarbeiten folgende Kategorien von personenbezogenen Daten:</p>
|
||||
<ul>
|
||||
<li><strong>Registrierungsdaten:</strong> Benutzername, Display-Name, E-Mail (falls vorhanden), Passwort-Hash</li>
|
||||
<li><strong>Termin- und Buchungsdaten:</strong> Datum, Uhrzeit, Betreff, Notizen, Status der Termine</li>
|
||||
<li><strong>Blog-Daten:</strong> Veröffentlichte Artikel, Autoreninformationen</li>
|
||||
<li><strong>Technische Daten:</strong> IP-Adresse, Browser-Informationen, Cookie-Daten, Zeitstempel</li>
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2>4. Zweck der Datenverarbeitung</h2>
|
||||
<p>Wir verarbeiten Ihre Daten zu folgenden Zwecken:</p>
|
||||
<ul>
|
||||
<li>Bereitstellung und Verwaltung Ihres Benutzerkontos</li>
|
||||
<li>Abwicklung von Terminbuchungen und Anfragen</li>
|
||||
<li>Kommunikation mit Ihnen zu Ihren Anfragen</li>
|
||||
<li>Bereitstellung personalisierter Inhalte</li>
|
||||
<li>Sicherheit und Schutz vor Missbrauch</li>
|
||||
<li>Verbesserung unserer Dienstleistungen</li>
|
||||
<li>Erfüllung gesetzlicher Verpflichtungen</li>
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2>5. Rechtsgrundlagen</h2>
|
||||
<p>Die Verarbeitung personenbezogener Daten erfolgt auf Grundlage von:</p>
|
||||
<ul>
|
||||
<li><strong>Artikel 6 Abs. 1 lit. b) DSGVO:</strong> Abwicklung von Verträgen und Anfragen</li>
|
||||
<li><strong>Artikel 6 Abs. 1 lit. a) DSGVO:</strong> Ihre ausdrückliche Einwilligung</li>
|
||||
<li><strong>Artikel 6 Abs. 1 lit. c) DSGVO:</strong> Erfüllung rechtlicher Verpflichtungen</li>
|
||||
<li><strong>Artikel 6 Abs. 1 lit. f) DSGVO:</strong> Berechtigte Interessen zur Sicherheit und Verbesserung</li>
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2>6. Speicherdauer</h2>
|
||||
<p>Wir speichern Ihre Daten so lange, wie dies erforderlich ist:</p>
|
||||
<ul>
|
||||
<li>Kontodaten: Solange Ihr Konto aktiv ist, danach 12 Monate</li>
|
||||
<li>Terminbuchungen: Bis 3 Jahre nach Abwicklung</li>
|
||||
<li>Blog-Kommentare und Inhalte: Bis zur Löschung des Inhalts</li>
|
||||
<li>Technische Logs: Maximal 90 Tage</li>
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2>7. Empfänger von Daten</h2>
|
||||
<p>Wir geben Ihre Daten nicht an Dritte weiter, außer:</p>
|
||||
<ul>
|
||||
<li>Unsere technischen Dienstanbieter (Webhoting, Cloud-Services)</li>
|
||||
<li>Behörden und Gerichte bei gesetzlicher Verpflichtung</li>
|
||||
<li>Mit Ihrer ausdrücklichen Einwilligung</li>
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2>8. Ihre Rechte</h2>
|
||||
<p>Sie haben folgende Rechte bezügliche Ihrer personenbezogenen Daten:</p>
|
||||
<ul>
|
||||
<li><strong>Auskunftsrecht:</strong> Recht auf Auskunft über Ihre Daten (Artikel 15 DSGVO)</li>
|
||||
<li><strong>Berichtigungsrecht:</strong> Recht auf Korrektur unrichtiger Daten (Artikel 16 DSGVO)</li>
|
||||
<li><strong>Löschungsrecht:</strong> Recht auf Löschung Ihrer Daten (Artikel 17 DSGVO)</li>
|
||||
<li><strong>Einschränkungsrecht:</strong> Recht auf Einschränkung der Verarbeitung (Artikel 18 DSGVO)</li>
|
||||
<li><strong>Recht auf Datenportabilität:</strong> Recht auf Übertragung Ihrer Daten (Artikel 20 DSGVO)</li>
|
||||
<li><strong>Widerspruchsrecht:</strong> Recht auf Widerspruch gegen Verarbeitung (Artikel 21 DSGVO)</li>
|
||||
<li><strong>Recht auf Beschwerde:</strong> Beschwerde bei einer Aufsichtsbehörde</li>
|
||||
</ul>
|
||||
<p>Um Ihre Rechte auszuüben, kontaktieren Sie uns unter: datenschutz@invario.de</p>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2>9. Cookies</h2>
|
||||
<p>Wir verwenden Cookies zur Verwaltung von Sitzungen und Authentifizierung:</p>
|
||||
<ul>
|
||||
<li><strong>Session-Cookies:</strong> Erforderlich für die Anmeldung und Funktionalität</li>
|
||||
<li><strong>Sicherheits-Cookies:</strong> Schutz vor CSRF und XSS-Angriffen</li>
|
||||
<li><strong>Analytik-Cookies:</strong> Optional, zur Verbesserung unserer Dienste</li>
|
||||
</ul>
|
||||
<p>Sie können Cookies in den Einstellungen Ihres Browsers deaktivieren. Dies kann jedoch die Funktionalität beeinträchtigen.</p>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2>10. Sicherheit</h2>
|
||||
<p>Wir schützen Ihre Daten durch:</p>
|
||||
<ul>
|
||||
<li>Verschlüsselte Übertragung (SSL/TLS)</li>
|
||||
<li>Sichere Passwortspeicherung (Hashing)</li>
|
||||
<li>Firewalls und Zugriffskontrollen</li>
|
||||
<li>Regelmäßige Sicherheitsupdates</li>
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2>11. Externe Links</h2>
|
||||
<p>Diese Website enthält möglicherweise Links zu externen Websites. Wir sind nicht verantwortlich für deren Datenschutzpraktiken. Bitte lesen Sie deren Datenschutzerklärungen.</p>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2>12. Änderungen dieser Datenschutzerklärung</h2>
|
||||
<p>Wir können diese Datenschutzerklärung jederzeit aktualisieren. Die aktuelle Version ist immer auf unserer Website verfügbar. Bei wesentlichen Änderungen werden Sie benachrichtigt.</p>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2>13. Kontakt</h2>
|
||||
<p>Bei Fragen zur Datenschutzerklärung kontaktieren Sie uns unter:</p>
|
||||
<p>
|
||||
E-Mail: datenschutz@invario.de<br>
|
||||
Telefon: +49 (0) 123 456789<br>
|
||||
Adresse: Musterstraße 123, 12345 Musterstadt
|
||||
</p>
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.legal-page {
|
||||
max-width: 900px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.legal-header {
|
||||
margin-bottom: 3rem;
|
||||
padding-bottom: 2rem;
|
||||
border-bottom: 2px solid var(--line);
|
||||
}
|
||||
|
||||
.legal-header h1 {
|
||||
font-size: 2.2rem;
|
||||
margin-bottom: 0.5rem;
|
||||
color: var(--brand);
|
||||
}
|
||||
|
||||
.legal-header p {
|
||||
color: var(--text-soft);
|
||||
font-size: 0.95rem;
|
||||
}
|
||||
|
||||
.legal-content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 2.5rem;
|
||||
}
|
||||
|
||||
section {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 1rem;
|
||||
}
|
||||
|
||||
section h2 {
|
||||
font-size: 1.3rem;
|
||||
color: var(--brand);
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
section p {
|
||||
line-height: 1.7;
|
||||
color: var(--text-soft);
|
||||
}
|
||||
|
||||
section ul {
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.75rem;
|
||||
}
|
||||
|
||||
section ul li {
|
||||
padding-left: 1.5rem;
|
||||
position: relative;
|
||||
color: var(--text-soft);
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
section ul li:before {
|
||||
content: "→";
|
||||
position: absolute;
|
||||
left: 0;
|
||||
color: var(--accent);
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
section strong {
|
||||
color: var(--text-main);
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
@media (max-width: 700px) {
|
||||
.legal-header h1 {
|
||||
font-size: 1.6rem;
|
||||
}
|
||||
|
||||
section h2 {
|
||||
font-size: 1.1rem;
|
||||
}
|
||||
|
||||
.legal-content {
|
||||
gap: 1.8rem;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,279 @@
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% block title %}Impressum | Invario{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="legal-page">
|
||||
<div class="legal-header">
|
||||
<h1>Impressum</h1>
|
||||
<p>Angaben gemäß TMG (Telemediengesetz) und MDStV (Mediendienstestaatsvertrag)</p>
|
||||
</div>
|
||||
|
||||
<div class="legal-content">
|
||||
<section>
|
||||
<h2>1. Betreiber der Website</h2>
|
||||
<p>
|
||||
<strong>Invario GmbH</strong><br>
|
||||
Musterstraße 123<br>
|
||||
12345 Musterstadt<br>
|
||||
Deutschland
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2>2. Registergericht und Registernummer</h2>
|
||||
<p>
|
||||
<strong>Registergericht:</strong> Amtsgericht Musterstadt<br>
|
||||
<strong>Registernummer:</strong> HRB 123456<br>
|
||||
<strong>USt-ID:</strong> DE 123 456 789
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2>3. Geschäftsführung</h2>
|
||||
<p>
|
||||
<strong>Geschäftsführer:</strong> Max Mustermann und Erika Musterfrau
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2>4. Kontaktinformationen</h2>
|
||||
<p>
|
||||
<strong>Telefon:</strong> +49 (0) 123 / 456789<br>
|
||||
<strong>E-Mail:</strong> info@invario.de<br>
|
||||
<strong>Website:</strong> www.invario.de
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2>5. Verantwortliche Redaktion</h2>
|
||||
<p>
|
||||
<strong>Verantwortlich nach § 55 Abs. 2 RStV:</strong><br>
|
||||
Max Mustermann<br>
|
||||
Invario GmbH<br>
|
||||
Musterstraße 123<br>
|
||||
12345 Musterstadt
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2>6. Haftungsausschluss</h2>
|
||||
<p>
|
||||
<strong>Haftung für Inhalte:</strong><br>
|
||||
Trotz sorgfältiger Überprüfung übernehmen wir keine Haftung für die Inhalte externer Links.
|
||||
Die auf dieser Website verlinkten Seiten sind ausschließlich Verantwortung des jeweiligen Betreibers.
|
||||
Zum Zeitpunkt der Link-Erstellung waren keine illegalen Inhalte erkennbar.
|
||||
</p>
|
||||
<p>
|
||||
<strong>Haftung für Links:</strong><br>
|
||||
Sollte eine Seite, auf die wir verlinken, in Zukunft illegale oder sittenwidrige Inhalte enthalten,
|
||||
werden wir den Link entfernen, sobald wir davon Kenntnis erlangen. Die Funktionsfähigkeit der Website
|
||||
wird trotz gründlicher Prüfung nicht garantiert.
|
||||
</p>
|
||||
<p>
|
||||
<strong>Haftung für Dienste und Angebote:</strong><br>
|
||||
Alle unterbreiteten Informationen sind freibleibend und unverbindlich. Wir behalten uns ausdrücklich vor,
|
||||
Teile der Website oder das gesamte Angebot ohne separate Ankündigung zu verändern, zu ergänzen, zu löschen oder
|
||||
die Veröffentlichung zeitweise oder endgültig einzustellen.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2>7. Urheberrecht und Nutzungsrechte</h2>
|
||||
<p>
|
||||
Die auf dieser Website veröffentlichten Inhalte und Werke unterliegen dem deutschen Urheberrecht.
|
||||
Eine Vervielfältigung, Bearbeitung, Verbreitung und jede Art der Verwertung außerhalb der Grenzen des Urheberrechts
|
||||
bedürfen der schriftlichen Zustimmung des Urhebers oder Erstellers. Downloads und Kopien dieser
|
||||
Seite sind nur für den privaten, nicht kommerziellen Gebrauch gestattet.
|
||||
</p>
|
||||
<p>
|
||||
<strong>© 2026 Invario GmbH. Alle Rechte vorbehalten.</strong>
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2>8. Besonderheiten in Bezug auf Inhalte</h2>
|
||||
<p>
|
||||
<strong>Blog und Benutzergenerierte Inhalte:</strong><br>
|
||||
Für Inhalte, die von Benutzern oder Administratoren veröffentlicht werden, trägt der jeweilige Autor/Verfasser
|
||||
die Verantwortung. Wir überprüfen regelmäßig alle Inhalte auf der Website. Sollten Sie der Meinung sein,
|
||||
dass gegen Ihr Urheberrecht verstoßen wird oder illegale Inhalte vorliegen, teilen Sie uns dies bitte
|
||||
umgehend mit.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2>9. Zahlungsarten und Geschäftsbedingungen</h2>
|
||||
<p>
|
||||
Die Nutzung unserer Dienstleistungen unterliegt den auf dieser Website veröffentlichten Nutzungsbedingungen
|
||||
und unseren allgemeinen Geschäftsbedingungen. Diese finden Sie unter
|
||||
<a href="{{ url_for('nutzungsbedingungen') }}">Nutzungsbedingungen</a>.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2>10. Datenschutz</h2>
|
||||
<p>
|
||||
Weitere Informationen zur Verarbeitung Ihrer personenbezogenen Daten finden Sie in unserer
|
||||
<a href="{{ url_for('datenschutz') }}">Datenschutzerklärung</a>.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2>11. Außergerichtliche Streitbeilegung</h2>
|
||||
<p>
|
||||
Der Europäischen Kommission steht ein Online-Portal zur Beilegung von Streitigkeiten
|
||||
(Plattform zur Online-Streitbeilegung - OS) zur Verfügung:
|
||||
<a href="https://ec.europa.eu/consumers/odr/" target="_blank">https://ec.europa.eu/consumers/odr/</a>
|
||||
</p>
|
||||
<p>
|
||||
Wir sind nicht bereit oder verpflichtet, an Streitbeilegungsverfahren vor einer Verbraucherschlichtungsstelle teilzunehmen.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2>12. Geltendes Recht</h2>
|
||||
<p>
|
||||
Für alle Rechtsbeziehungen zwischen dem Nutzer und uns gilt ausschließlich deutsches Recht.
|
||||
Es gilt das TMG und das MDStV in ihrer jeweils aktuellen Fassung. Erfüllungsort ist Musterstadt.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2>13. Kontakt zum Datenschutzbeauftragten</h2>
|
||||
<p>
|
||||
<strong>Datenschutzbeauftragter:</strong><br>
|
||||
E-Mail: datenschutz@invario.de<br>
|
||||
Telefon: +49 (0) 123 / 456789
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2>14. Zu beachtende Gebote in Bezug auf Konten</h2>
|
||||
<ul>
|
||||
<li>Die Anmeldung erfordert einen gültigen Benutzernamen und ein Passwort</li>
|
||||
<li>Sie sind verantwortlich für die Geheimhaltung des Passworts</li>
|
||||
<li>Sie haften für alle Aktivitäten in Ihrem Konto</li>
|
||||
<li>Missbrauch und Sicherheitslücken müssen uns sofort mitgeteilt werden</li>
|
||||
<li>Eine Konto-Weitergabe ist nicht gestattet</li>
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
<div class="last-updated">
|
||||
<p><strong>Zuletzt aktualisiert:</strong> 1. Januar 2026</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.legal-page {
|
||||
max-width: 900px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.legal-header {
|
||||
margin-bottom: 3rem;
|
||||
padding-bottom: 2rem;
|
||||
border-bottom: 2px solid var(--line);
|
||||
}
|
||||
|
||||
.legal-header h1 {
|
||||
font-size: 2.2rem;
|
||||
margin-bottom: 0.5rem;
|
||||
color: var(--brand);
|
||||
}
|
||||
|
||||
.legal-header p {
|
||||
color: var(--text-soft);
|
||||
font-size: 0.95rem;
|
||||
}
|
||||
|
||||
.legal-content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 2.5rem;
|
||||
}
|
||||
|
||||
section {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 1rem;
|
||||
}
|
||||
|
||||
section h2 {
|
||||
font-size: 1.3rem;
|
||||
color: var(--brand);
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
section p {
|
||||
line-height: 1.7;
|
||||
color: var(--text-soft);
|
||||
}
|
||||
|
||||
section p a {
|
||||
color: var(--brand);
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
section p a:hover {
|
||||
color: var(--accent);
|
||||
}
|
||||
|
||||
section ul {
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.75rem;
|
||||
}
|
||||
|
||||
section ul li {
|
||||
padding-left: 1.5rem;
|
||||
position: relative;
|
||||
color: var(--text-soft);
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
section ul li:before {
|
||||
content: "→";
|
||||
position: absolute;
|
||||
left: 0;
|
||||
color: var(--accent);
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
section strong {
|
||||
color: var(--text-main);
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.last-updated {
|
||||
background: var(--bg-soft);
|
||||
padding: 1.5rem;
|
||||
border-radius: var(--radius-md);
|
||||
margin-top: 2rem;
|
||||
}
|
||||
|
||||
.last-updated p {
|
||||
margin: 0;
|
||||
text-align: center;
|
||||
color: var(--text-soft);
|
||||
}
|
||||
|
||||
@media (max-width: 700px) {
|
||||
.legal-header h1 {
|
||||
font-size: 1.6rem;
|
||||
}
|
||||
|
||||
section h2 {
|
||||
font-size: 1.1rem;
|
||||
}
|
||||
|
||||
.legal-content {
|
||||
gap: 1.8rem;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,110 @@
|
||||
<!--
|
||||
Copyright 2025 Maximilian Gründinger
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% block title %}Login{% endblock %}
|
||||
|
||||
{% block head %}
|
||||
{{ super() }}
|
||||
<style>
|
||||
.auth-wrap {
|
||||
max-width: 520px;
|
||||
margin: 2rem auto;
|
||||
padding: 2rem;
|
||||
border-radius: 18px;
|
||||
border: 1px solid #d4e0e9;
|
||||
background: #ffffff;
|
||||
box-shadow: 0 20px 44px rgba(14, 32, 48, 0.08);
|
||||
}
|
||||
|
||||
.auth-wrap h1 {
|
||||
font-size: 2rem;
|
||||
color: #0f344d;
|
||||
margin-bottom: 0.4rem;
|
||||
}
|
||||
|
||||
.auth-wrap p {
|
||||
margin-bottom: 1.3rem;
|
||||
}
|
||||
|
||||
.field {
|
||||
margin-bottom: 0.9rem;
|
||||
}
|
||||
|
||||
.field label {
|
||||
display: block;
|
||||
margin-bottom: 0.35rem;
|
||||
font-weight: 700;
|
||||
color: #19445f;
|
||||
}
|
||||
|
||||
.field input {
|
||||
width: 100%;
|
||||
padding: 0.68rem 0.78rem;
|
||||
border-radius: 10px;
|
||||
border: 1px solid #c4d5e2;
|
||||
font-size: 1rem;
|
||||
color: #12384f;
|
||||
}
|
||||
|
||||
.field input:focus {
|
||||
outline: none;
|
||||
border-color: #2f79a7;
|
||||
box-shadow: 0 0 0 3px rgba(58, 133, 180, 0.2);
|
||||
}
|
||||
|
||||
.auth-btn {
|
||||
width: 100%;
|
||||
border: none;
|
||||
border-radius: 999px;
|
||||
padding: 0.72rem;
|
||||
font-size: 1rem;
|
||||
font-weight: 700;
|
||||
color: #ffffff;
|
||||
background: linear-gradient(120deg, #0a5f8f 0%, #0b4567 100%);
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.auth-meta {
|
||||
margin-top: 1rem;
|
||||
color: #547184;
|
||||
}
|
||||
|
||||
.auth-meta a {
|
||||
color: #0a5f8f;
|
||||
font-weight: 700;
|
||||
}
|
||||
</style>
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<section class="auth-wrap">
|
||||
<h1>Login</h1>
|
||||
<p>Bitte melden Sie sich mit Ihrem Konto an, um Termine anzufragen.</p>
|
||||
<form method="POST" action="{{ url_for('login') }}">
|
||||
<div class="field">
|
||||
<label for="username">Benutzername</label>
|
||||
<input id="username" name="username" type="text" autocomplete="username" required>
|
||||
</div>
|
||||
<div class="field">
|
||||
<label for="password">Passwort</label>
|
||||
<input id="password" name="password" type="password" autocomplete="current-password" required>
|
||||
</div>
|
||||
<button class="auth-btn" type="submit">Login</button>
|
||||
</form>
|
||||
<p class="auth-meta">Noch kein Konto? <a href="{{ url_for('register') }}">Jetzt registrieren</a></p>
|
||||
</section>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,450 @@
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% block title %}IT Loesungen | Modern{% endblock %}
|
||||
|
||||
{% block head %}
|
||||
{{ super() }}
|
||||
<style>
|
||||
.hero {
|
||||
margin-top: 1.2rem;
|
||||
padding: 3.8rem;
|
||||
border-radius: 24px;
|
||||
background: linear-gradient(135deg, #f8fcff 0%, #e1ecf3 70%, #d4e3ed 100%);
|
||||
border: 1px solid #cfdbe4;
|
||||
display: grid;
|
||||
grid-template-columns: 1.2fr 1fr;
|
||||
gap: 2rem;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
box-shadow: 0 25px 55px rgba(17, 35, 50, 0.1);
|
||||
}
|
||||
|
||||
.hero::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
right: -80px;
|
||||
bottom: -90px;
|
||||
width: 280px;
|
||||
height: 280px;
|
||||
border-radius: 999px;
|
||||
background: radial-gradient(circle at center, #0b5b89 0%, #0b5b89 40%, transparent 70%);
|
||||
opacity: 0.12;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.eyebrow {
|
||||
display: inline-block;
|
||||
margin-bottom: 0.85rem;
|
||||
padding: 0.3rem 0.65rem;
|
||||
border-radius: 999px;
|
||||
font-size: 0.75rem;
|
||||
font-weight: 700;
|
||||
letter-spacing: 0.08em;
|
||||
text-transform: uppercase;
|
||||
color: #0c4f78;
|
||||
background: #d9ebf6;
|
||||
}
|
||||
|
||||
.hero h1 {
|
||||
font-size: clamp(2rem, 5.1vw, 3.4rem);
|
||||
color: #06293e;
|
||||
text-wrap: balance;
|
||||
}
|
||||
|
||||
.hero p {
|
||||
max-width: 56ch;
|
||||
margin-top: 1.1rem;
|
||||
font-size: 1.06rem;
|
||||
}
|
||||
|
||||
.cta-row {
|
||||
margin-top: 1.8rem;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 0.75rem;
|
||||
}
|
||||
|
||||
.btn {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border-radius: 999px;
|
||||
border: 1px solid transparent;
|
||||
padding: 0.68rem 1.15rem;
|
||||
font-weight: 700;
|
||||
transition: transform 0.2s ease, box-shadow 0.2s ease;
|
||||
}
|
||||
|
||||
.btn:hover {
|
||||
transform: translateY(-1px);
|
||||
}
|
||||
|
||||
.btn-primary {
|
||||
color: #ffffff;
|
||||
background: linear-gradient(120deg, #0c5a86 0%, #08486c 100%);
|
||||
box-shadow: 0 8px 20px rgba(11, 87, 128, 0.26);
|
||||
}
|
||||
|
||||
.btn-secondary {
|
||||
color: #0d4567;
|
||||
background: #ffffff;
|
||||
border-color: #b8cddc;
|
||||
}
|
||||
|
||||
.hero-card {
|
||||
align-self: end;
|
||||
background: #0e2f44;
|
||||
color: #dcf0ff;
|
||||
border-radius: 18px;
|
||||
padding: 1.2rem;
|
||||
border: 1px solid #194b68;
|
||||
}
|
||||
|
||||
.hero-card h3 {
|
||||
font-size: 1.15rem;
|
||||
margin-bottom: 0.6rem;
|
||||
}
|
||||
|
||||
.hero-card p {
|
||||
color: #b6d6ea;
|
||||
font-size: 0.96rem;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.stats {
|
||||
margin-top: 1rem;
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, minmax(0, 1fr));
|
||||
gap: 0.55rem;
|
||||
}
|
||||
|
||||
.stats div {
|
||||
padding: 0.55rem 0.65rem;
|
||||
border-radius: 12px;
|
||||
background: #153a52;
|
||||
border: 1px solid #2a5673;
|
||||
}
|
||||
|
||||
.stats strong {
|
||||
display: block;
|
||||
font-family: "Space Grotesk", system-ui, sans-serif;
|
||||
color: #ffffff;
|
||||
font-size: 1.08rem;
|
||||
}
|
||||
|
||||
.stats span {
|
||||
color: #9ec5dc;
|
||||
font-size: 0.8rem;
|
||||
}
|
||||
|
||||
.section {
|
||||
margin-top: 2.2rem;
|
||||
padding: 2rem;
|
||||
border-radius: 18px;
|
||||
border: 1px solid #d4dde5;
|
||||
background: #ffffff;
|
||||
box-shadow: 0 15px 35px rgba(20, 40, 55, 0.05);
|
||||
animation: rise 700ms ease both;
|
||||
}
|
||||
|
||||
.section h2 {
|
||||
font-size: clamp(1.4rem, 2.5vw, 2rem);
|
||||
margin-bottom: 0.5rem;
|
||||
color: #0f334b;
|
||||
}
|
||||
|
||||
.section-grid {
|
||||
margin-top: 1.1rem;
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, minmax(0, 1fr));
|
||||
gap: 0.9rem;
|
||||
}
|
||||
|
||||
.card {
|
||||
padding: 1rem;
|
||||
border-radius: 14px;
|
||||
border: 1px solid #d9e2ea;
|
||||
background: linear-gradient(160deg, #fbfdff 0%, #f4f8fb 100%);
|
||||
}
|
||||
|
||||
.card h3 {
|
||||
font-size: 1.07rem;
|
||||
color: #113c58;
|
||||
margin-bottom: 0.45rem;
|
||||
}
|
||||
|
||||
.card p {
|
||||
font-size: 0.96rem;
|
||||
}
|
||||
|
||||
.project-list {
|
||||
margin-top: 1.1rem;
|
||||
display: grid;
|
||||
gap: 0.8rem;
|
||||
}
|
||||
|
||||
.project {
|
||||
padding: 0.95rem 1rem;
|
||||
border-radius: 14px;
|
||||
border: 1px solid #cfdae4;
|
||||
background: #f8fbfd;
|
||||
display: flex;
|
||||
gap: 1rem;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.project b {
|
||||
display: block;
|
||||
color: #0b3753;
|
||||
margin-bottom: 0.2rem;
|
||||
}
|
||||
|
||||
.project span {
|
||||
font-size: 0.88rem;
|
||||
color: #4a6579;
|
||||
border: 1px solid #bfd0dd;
|
||||
padding: 0.2rem 0.55rem;
|
||||
border-radius: 999px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.process {
|
||||
margin-top: 1.2rem;
|
||||
display: grid;
|
||||
grid-template-columns: repeat(6, minmax(0, 1fr));
|
||||
gap: 0.6rem;
|
||||
}
|
||||
|
||||
.step {
|
||||
padding: 0.8rem 0.65rem;
|
||||
text-align: center;
|
||||
border-radius: 12px;
|
||||
border: 1px solid #ccdae5;
|
||||
background: #f7fafc;
|
||||
}
|
||||
|
||||
.step strong {
|
||||
display: block;
|
||||
margin-bottom: 0.2rem;
|
||||
font-size: 0.98rem;
|
||||
color: #0f3650;
|
||||
}
|
||||
|
||||
.step small {
|
||||
color: #5f7b8f;
|
||||
}
|
||||
|
||||
.team-note {
|
||||
margin-top: 0.85rem;
|
||||
padding: 0.9rem 1rem;
|
||||
border-radius: 12px;
|
||||
border: 1px solid #f0c18b;
|
||||
background: linear-gradient(120deg, #fffaf3 0%, #ffeed8 100%);
|
||||
color: #7d4f14;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.contact {
|
||||
margin-top: 2rem;
|
||||
border-radius: 20px;
|
||||
padding: 2.3rem;
|
||||
border: 1px solid #0f496f;
|
||||
background: linear-gradient(120deg, #114e75 0%, #0a3d5c 100%);
|
||||
color: #d2ebfa;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 1rem;
|
||||
}
|
||||
|
||||
.contact h2 {
|
||||
color: #ffffff;
|
||||
font-size: clamp(1.25rem, 2.7vw, 2rem);
|
||||
margin-bottom: 0.4rem;
|
||||
}
|
||||
|
||||
.contact p {
|
||||
color: #b9d8ec;
|
||||
}
|
||||
|
||||
.contact .btn-secondary {
|
||||
border-color: rgba(255, 255, 255, 0.35);
|
||||
background: rgba(255, 255, 255, 0.14);
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
.site-footer {
|
||||
margin-top: 2rem;
|
||||
padding: 1rem 0 0.3rem;
|
||||
color: #6a8192;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
gap: 1rem;
|
||||
font-size: 0.95rem;
|
||||
}
|
||||
|
||||
@keyframes rise {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateY(16px);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 980px) {
|
||||
.hero {
|
||||
grid-template-columns: 1fr;
|
||||
padding: 2rem;
|
||||
}
|
||||
|
||||
.section-grid {
|
||||
grid-template-columns: 1fr 1fr;
|
||||
}
|
||||
|
||||
.process {
|
||||
grid-template-columns: repeat(3, minmax(0, 1fr));
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 700px) {
|
||||
.section-grid {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
.project {
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
}
|
||||
|
||||
.process {
|
||||
grid-template-columns: 1fr 1fr;
|
||||
}
|
||||
|
||||
.contact {
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
padding: 1.55rem;
|
||||
}
|
||||
|
||||
.site-footer {
|
||||
flex-direction: column;
|
||||
padding-bottom: 1.2rem;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<section class="hero" id="top">
|
||||
<div>
|
||||
<span class="eyebrow">IT Loesungen mit Haltung</span>
|
||||
<h1>Zuhören. Verstehen. Planen. Realisieren.</h1>
|
||||
<p>
|
||||
Wir unterstuetzen Unternehmen ganzheitlich bei Enterprise-Architektur,
|
||||
Projektmanagement und IT-Betrieb. Die Anforderung bleibt im Mittelpunkt,
|
||||
die Umsetzung wird klar, messbar und belastbar.
|
||||
</p>
|
||||
<div class="cta-row">
|
||||
{% if 'username' in session %}
|
||||
<a class="btn btn-primary" href="{{ url_for('appointments') }}">Termin anfragen</a>
|
||||
{% else %}
|
||||
<a class="btn btn-primary" href="{{ url_for('login') }}">Termin anfragen</a>
|
||||
{% endif %}
|
||||
<a class="btn btn-primary" href="#kontakt">Kontakt aufnehmen</a>
|
||||
<a class="btn btn-secondary" href="#leistungen">Dienstleistungen ansehen</a>
|
||||
</div>
|
||||
</div>
|
||||
<aside class="hero-card" aria-label="Kurzfakten">
|
||||
<h3>IT Projekte mit Substanz</h3>
|
||||
<p>
|
||||
Von Infrastruktur bis Governance: Wir verbinden konzeptionelle Tiefe mit
|
||||
pragmatischer Umsetzung im Tagesgeschaeft.
|
||||
</p>
|
||||
<div class="stats">
|
||||
<div><strong>25+</strong><span>aktive Mandate</span></div>
|
||||
<div><strong>98%</strong><span>Zieltermine erreicht</span></div>
|
||||
<div><strong>24/7</strong><span>Servicebereit</span></div>
|
||||
</div>
|
||||
</aside>
|
||||
</section>
|
||||
|
||||
<section class="section" id="leistungen" style="animation-delay: 100ms;">
|
||||
<h2>Dienstleistungen</h2>
|
||||
<p>Modulare Leistungen, individuell kombiniert fuer Ihre IT-Roadmap.</p>
|
||||
<div class="section-grid">
|
||||
<article class="card">
|
||||
<h3>Support und Service</h3>
|
||||
<p>Betriebskritische Systeme stabil halten, proaktiv ueberwachen und schnell reagieren.</p>
|
||||
</article>
|
||||
<article class="card">
|
||||
<h3>Optimierung und Tuning</h3>
|
||||
<p>Strukturen, Kosten und Performance datenbasiert verbessern statt nur Symptome behandeln.</p>
|
||||
</article>
|
||||
<article class="card">
|
||||
<h3>Health Check und Verify</h3>
|
||||
<p>Technische Due-Diligence, klare Handlungsplaene und belastbare Priorisierung.</p>
|
||||
</article>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="section" id="projekte" style="animation-delay: 180ms;">
|
||||
<h2>Projektfelder</h2>
|
||||
<p>Ausgewählte Schwerpunkte aus laufenden und abgeschlossenen Kundenprojekten.</p>
|
||||
<div class="project-list">
|
||||
<div class="project">
|
||||
<div>
|
||||
<b>Virtualisierung und Hybrid-Cloud</b>
|
||||
Migration in wartbare Plattformen mit planbaren Betriebskosten.
|
||||
</div>
|
||||
<span>Cloud Computing</span>
|
||||
</div>
|
||||
<div class="project">
|
||||
<div>
|
||||
<b>Netzwerk und Sicherheit</b>
|
||||
Segmentierung, Monitoring und Security-Standards auf Enterprise-Niveau.
|
||||
</div>
|
||||
<span>Security</span>
|
||||
</div>
|
||||
<div class="project">
|
||||
<div>
|
||||
<b>Projektmanagement und EAM</b>
|
||||
Governance, Architekturprinzipien und Umsetzung in einer Linie.
|
||||
</div>
|
||||
<span>Transformation</span>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="section" id="team" style="animation-delay: 260ms;">
|
||||
<h2>Unsere Arbeitsweise</h2>
|
||||
<p>Klassische Beratungsdisziplin trifft auf moderne Delivery-Kultur.</p>
|
||||
<div class="process" aria-label="Prozessschritte">
|
||||
<div class="step"><strong>Zuhoeren</strong><small>Anforderungen erfassen</small></div>
|
||||
<div class="step"><strong>Verstehen</strong><small>Kontext analysieren</small></div>
|
||||
<div class="step"><strong>Besprechen</strong><small>Optionen priorisieren</small></div>
|
||||
<div class="step"><strong>Planen</strong><small>Roadmap festlegen</small></div>
|
||||
<div class="step"><strong>Realisieren</strong><small>Loesung liefern</small></div>
|
||||
<div class="step"><strong>Unterstuetzen</strong><small>Betrieb absichern</small></div>
|
||||
</div>
|
||||
<p class="team-note">
|
||||
Aktuell verfuegbar: Ein IT-Infrastruktur-Architekt und ein IT-Governance-Experte
|
||||
mit technischem Hintergrund fuer neue Aufgaben.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section class="contact" id="kontakt">
|
||||
<div>
|
||||
<h2>Bereit fuer das naechste IT-Projekt?</h2>
|
||||
<p>In einem kurzen Erstgespraech klaeren wir Zielbild, Risiken und realistische Umsetzungsschritte.</p>
|
||||
</div>
|
||||
{% if 'username' in session %}
|
||||
<a class="btn btn-secondary" href="{{ url_for('appointments') }}">Termin anfragen</a>
|
||||
{% else %}
|
||||
<a class="btn btn-secondary" href="{{ url_for('login') }}">Termin anfragen</a>
|
||||
{% endif %}
|
||||
</section>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,354 @@
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% block title %}Nutzungsbedingungen | Invario{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="legal-page">
|
||||
<div class="legal-header">
|
||||
<h1>Nutzungsbedingungen</h1>
|
||||
<p>Allgemeine Geschäftsbedingungen (AGB) für die Nutzung von Invario</p>
|
||||
</div>
|
||||
|
||||
<div class="legal-content">
|
||||
<section>
|
||||
<h2>1. Geltungsbereich und Vertragsparteien</h2>
|
||||
<p>
|
||||
Diese Nutzungsbedingungen regeln die Beziehung zwischen Ihnen als Nutzer und der Invario GmbH
|
||||
bei der Nutzung unserer Website und Dienstleistungen. Mit der Nutzung unserer Website und Dienste
|
||||
akzeptieren Sie diese Bedingungen vollständig und verbindlich.
|
||||
</p>
|
||||
<p>
|
||||
<strong>Vertragsparteien sind:</strong>
|
||||
</p>
|
||||
<ul>
|
||||
<li>Invario GmbH (Anbieter)</li>
|
||||
<li>Der Nutzer (Sie)</li>
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2>2. Registrierung und Konto</h2>
|
||||
<p>
|
||||
<strong>Anforderungen zur Registrierung:</strong><br>
|
||||
Für die Nutzung bestimmter Funktionen müssen Sie sich registrieren. Sie verpflichten sich,
|
||||
wahrheitsgemäß und vollständig folgende Informationen bereitzustellen:
|
||||
</p>
|
||||
<ul>
|
||||
<li>Einen eindeutigen Benutzernamen</li>
|
||||
<li>Einen Anzeigenamen (Display Name)</li>
|
||||
<li>Ein sicheres Passwort (mindestens 8 Zeichen)</li>
|
||||
</ul>
|
||||
<p>
|
||||
<strong>Ihre Verantwortung:</strong><br>
|
||||
Sie sind verantwortlich für den Schutz Ihres Passworts und für alle Aktivitäten in Ihrem Konto.
|
||||
Sie müssen uns sofort benachrichtigen, wenn Sie unbefugten Zugriff vermuten.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2>3. Zulässige Nutzung</h2>
|
||||
<p>
|
||||
<strong>Ihre Nutzung unserer Dienste ist auf folgende Weise begrenzt:</strong>
|
||||
</p>
|
||||
<ul>
|
||||
<li>Sie werden die Website nicht für illegale oder schädliche Zwecke nutzen</li>
|
||||
<li>Sie werden keine Malware, Viren oder zerstörerischen Code hochladen</li>
|
||||
<li>Sie werden nicht versuchen, unbefugten Zugang zu erhalten</li>
|
||||
<li>Sie werden die Website oder deren Dienste nicht missbrauchen</li>
|
||||
<li>Sie werden keine personenbezogenen Daten anderer Nutzer sammeln</li>
|
||||
<li>Sie werden die Rechte anderer Nutzer respektieren</li>
|
||||
<li>Sie werden keine rassistischen, rassistischen oder fremdenfeindlichen Inhalte teilen</li>
|
||||
<li>Sie werden keine Belästigung oder Bedrohung durchführen</li>
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2>4. Terminbuchungen und Anfragen</h2>
|
||||
<p>
|
||||
<strong>Buchungsprozess:</strong><br>
|
||||
Sie können über unsere Plattform Termine anfordern. Ein Termin ist nicht automatisch bestätigt,
|
||||
sondern muss von unserem Team überprüft und genehmigt werden.
|
||||
</p>
|
||||
<p>
|
||||
<strong>Termine inkl. Folgende Rechte und Pflichten:</strong>
|
||||
</p>
|
||||
<ul>
|
||||
<li>Sie können einen Termin anfordern, wir sind jedoch nicht verpflichtet, diesen zu bestätigen</li>
|
||||
<li>Ein Termin wird erst vermittelt durch eine Bestätigung durch unser Team</li>
|
||||
<li>Bei Ablehnung erhalten Sie eine Begründung</li>
|
||||
<li>Sie sind verantwortlich für die Richtigkeit Ihrer Angaben</li>
|
||||
<li>Im Falle von Stornierungen beachten Sie bitte unsere Stornierungsrichtlinien</li>
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2>5. Blog und benutzergenerierte Inhalte</h2>
|
||||
<p>
|
||||
<strong>Veröffentlichung von Inhalten:</strong><br>
|
||||
Admins können Blog-Beiträge veröffentlichen. Diese Beiträge müssen folgende Anforderungen erfüllen:
|
||||
</p>
|
||||
<ul>
|
||||
<li>Keine illegalen oder extremistischen Inhalte</li>
|
||||
<li>Keine rassistischen oder rassistischen Aussagen</li>
|
||||
<li>Keine Verletzung von Urheberrechten dritter Parteien</li>
|
||||
<li>Keine persönlichen Daten von anderen Personen ohne ihre Zustimmung</li>
|
||||
<li>Keine Spam oder kommerzielle Werbung (außer für autorisierte Partner)</li>
|
||||
</ul>
|
||||
<p>
|
||||
<strong>Recht zur Modernis und Lösch:</strong><br>
|
||||
Wir behalten uns das Recht vor, Inhalte zu moderieren, zu bearbeiten oder zu löschen,
|
||||
die gegen diese Bedingungen verstoßen. Dies geschieht ohne Ankündigung und ohne Haftung.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2>6. Geistige Eigentum</h2>
|
||||
<p>
|
||||
<strong>Alle Inhalte und Materialien auf dieser Website, einschließlich, aber nicht begrenzt auf:</strong>
|
||||
</p>
|
||||
<ul>
|
||||
<li>Texte, Grafiken, Logos, Bilder, Audio- und Video-Dateien</li>
|
||||
<li>Software, Quellcode und Datenbanken</li>
|
||||
<li>Die Auswahl, Koordination und Anordnung solcher Materialien</li>
|
||||
</ul>
|
||||
<p>
|
||||
...sind Eigentum der Invario GmbH oder der lizenzierten Parteien und durch Urheberrechts-
|
||||
und sonstige intellektuelle Eigentumsgesetze geschützt.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2>7. Haftungsbeschränkung</h2>
|
||||
<p>
|
||||
<strong>Haftungsausschluss:</strong><br>
|
||||
Soweit von Gesetzes wegen zulässig, erklären wir uns nicht verantwortlich für:
|
||||
</p>
|
||||
<ul>
|
||||
<li>Indirekte, zufällige oder Folgeschäden</li>
|
||||
<li>Entgangene Gewinne oder Geschäftsmöglichkeiten</li>
|
||||
<li>Verlust von Daten oder Informationen</li>
|
||||
<li>Unterbrechungen oder Ausfallzeiten</li>
|
||||
<li>Schäden durch unbefugten Zugriff</li>
|
||||
<li>Schäden durch Dritte oder externe Faktoren</li>
|
||||
</ul>
|
||||
<p>
|
||||
<strong>Haftungsbegrenzung:</strong><br>
|
||||
Falls wir haftbar sind, ist unsere Haftung auf den Betrag begrenzt, den Sie an uns bezahlt haben
|
||||
oder den geringeren Betrag von 100 EUR.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2>8. Sicherheit und Datenschutz</h2>
|
||||
<p>
|
||||
Wir nehmen die Sicherheit Ihrer Daten ernst. Weitere Details finden Sie in unserer
|
||||
<a href="{{ url_for('datenschutz') }}">Datenschutzerklärung</a>.
|
||||
</p>
|
||||
<p>
|
||||
<strong>Sie verpflichten sich:</strong>
|
||||
</p>
|
||||
<ul>
|
||||
<li>Ihr Passwort geheim zu halten</li>
|
||||
<li>Sich abzumelden, wenn Sie andere das System nutzen</li>
|
||||
<li>Uns über Sicherheitsverletzungen zu benachrichtigen</li>
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2>9. Änderungen der Bedingungen und Dienste</h2>
|
||||
<p>
|
||||
<strong>Recht zur Änderung:</strong><br>
|
||||
Wir behalten uns das Recht vor, diese Nutzungsbedingungen jederzeit zu ändern.
|
||||
Sie werden benachrichtigt, wenn wesentliche Änderungen vorgenommen werden.
|
||||
Die weitere Nutzung der Website bedeutet Ihre Annahme der neuen Bedingungen.
|
||||
</p>
|
||||
<p>
|
||||
<strong>Änderungen an Diensten:</strong><br>
|
||||
Wir behalten uns das Recht vor, Dienste jederzeit zu ändern, zu erweitern oder zu entfernen,
|
||||
ohne davor verpflichtet zu sein, Sie zu informieren.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2>10. Beendigung des Kontos</h2>
|
||||
<p>
|
||||
<strong>Beendigung durch den Nutzer:</strong><br>
|
||||
Sie können Ihr Konto jederzeit beenden, indem Sie uns eine E-Mail senden.
|
||||
</p>
|
||||
<p>
|
||||
<strong>Beendigung durch uns:</strong><br>
|
||||
Wir können Ihr Konto sofort beenden, wenn Sie diese Nutzungsbedingungen verletzen oder
|
||||
verdächtige Aktivitäten aufweisen. Dies geschieht ohne Vorankündigung.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2>11. Webhooks und automatische Integration</h2>
|
||||
<p>
|
||||
<strong>Funktionalität:</strong><br>
|
||||
Unsere Plattform ermöglicht die Verwaltung von Terminen und Inhalten.
|
||||
Diese Daten sind nur für Sie und bei Berechtigungen für unseren Admin-Team zugänglich.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2>12. Benachrichtigungen und Kommunikation</h2>
|
||||
<p>
|
||||
<strong>Kommunikationsmittel:</strong><br>
|
||||
Wir können Sie per E-Mail, Website-Benachrichtigungen oder anderen Mitteln benachrichtigen.
|
||||
Sie erklären sich damit einverstanden, solche Benachrichtigungen zu erhalten.
|
||||
</p>
|
||||
<p>
|
||||
<strong>Häufigkeit:</strong><br>
|
||||
Wir verpflichten uns, Sie nicht übermäßig zu bombardieren, aber wir können Ihnen relevante Aktualisierungen zusenden.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2>13. Verfügbarkeit und Support</h2>
|
||||
<p>
|
||||
Wir bieten Support während normaler Geschäftszeiten. Während Wartungsarbeiten oder ungeplanten Ausfallzeiten
|
||||
ist die Website möglicherweise nicht verfügbar. Wir entschuldigen uns für jegliche Unannehmlichkeiten.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2>14. Anwendbares Recht und Gerichtsstand</h2>
|
||||
<p>
|
||||
Diese Nutzungsbedingungen unterliegen deutschem Recht. Die Gerichtsstände für alle Streitigkeiten
|
||||
sind in Musterstadt. Sie erklären sich damit einverstanden, dass alle Ansprüche in den deutschen Gerichten
|
||||
eingereicht werden müssen.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2>15. Kontakt</h2>
|
||||
<p>
|
||||
Bei Fragen zu diesen Nutzungsbedingungen kontaktieren Sie uns unter:
|
||||
</p>
|
||||
<p>
|
||||
Invario GmbH<br>
|
||||
E-Mail: info@invario.de<br>
|
||||
Telefon: +49 (0) 123 / 456789<br>
|
||||
Adresse: Musterstraße 123, 12345 Musterstadt
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<div class="last-updated">
|
||||
<p><strong>Zuletzt aktualisiert:</strong> 1. Januar 2026</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.legal-page {
|
||||
max-width: 900px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.legal-header {
|
||||
margin-bottom: 3rem;
|
||||
padding-bottom: 2rem;
|
||||
border-bottom: 2px solid var(--line);
|
||||
}
|
||||
|
||||
.legal-header h1 {
|
||||
font-size: 2.2rem;
|
||||
margin-bottom: 0.5rem;
|
||||
color: var(--brand);
|
||||
}
|
||||
|
||||
.legal-header p {
|
||||
color: var(--text-soft);
|
||||
font-size: 0.95rem;
|
||||
}
|
||||
|
||||
.legal-content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 2.5rem;
|
||||
}
|
||||
|
||||
section {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 1rem;
|
||||
}
|
||||
|
||||
section h2 {
|
||||
font-size: 1.3rem;
|
||||
color: var(--brand);
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
section p {
|
||||
line-height: 1.7;
|
||||
color: var(--text-soft);
|
||||
}
|
||||
|
||||
section p a {
|
||||
color: var(--brand);
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
section p a:hover {
|
||||
color: var(--accent);
|
||||
}
|
||||
|
||||
section ul {
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.75rem;
|
||||
}
|
||||
|
||||
section ul li {
|
||||
padding-left: 1.5rem;
|
||||
position: relative;
|
||||
color: var(--text-soft);
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
section ul li:before {
|
||||
content: "→";
|
||||
position: absolute;
|
||||
left: 0;
|
||||
color: var(--accent);
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
section strong {
|
||||
color: var(--text-main);
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.last-updated {
|
||||
background: var(--bg-soft);
|
||||
padding: 1.5rem;
|
||||
border-radius: var(--radius-md);
|
||||
margin-top: 2rem;
|
||||
}
|
||||
|
||||
.last-updated p {
|
||||
margin: 0;
|
||||
text-align: center;
|
||||
color: var(--text-soft);
|
||||
}
|
||||
|
||||
@media (max-width: 700px) {
|
||||
.legal-header h1 {
|
||||
font-size: 1.6rem;
|
||||
}
|
||||
|
||||
section h2 {
|
||||
font-size: 1.1rem;
|
||||
}
|
||||
|
||||
.legal-content {
|
||||
gap: 1.8rem;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,103 @@
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% block title %}Registrieren{% endblock %}
|
||||
|
||||
{% block head %}
|
||||
{{ super() }}
|
||||
<style>
|
||||
.auth-wrap {
|
||||
max-width: 560px;
|
||||
margin: 2rem auto;
|
||||
padding: 2rem;
|
||||
border-radius: 18px;
|
||||
border: 1px solid #d4e0e9;
|
||||
background: #ffffff;
|
||||
box-shadow: 0 20px 44px rgba(14, 32, 48, 0.08);
|
||||
}
|
||||
|
||||
.auth-wrap h1 {
|
||||
font-size: 2rem;
|
||||
color: #0f344d;
|
||||
margin-bottom: 0.4rem;
|
||||
}
|
||||
|
||||
.auth-wrap p {
|
||||
margin-bottom: 1.3rem;
|
||||
}
|
||||
|
||||
.field {
|
||||
margin-bottom: 0.9rem;
|
||||
}
|
||||
|
||||
.field label {
|
||||
display: block;
|
||||
margin-bottom: 0.35rem;
|
||||
font-weight: 700;
|
||||
color: #19445f;
|
||||
}
|
||||
|
||||
.field input {
|
||||
width: 100%;
|
||||
padding: 0.68rem 0.78rem;
|
||||
border-radius: 10px;
|
||||
border: 1px solid #c4d5e2;
|
||||
font-size: 1rem;
|
||||
color: #12384f;
|
||||
}
|
||||
|
||||
.field input:focus {
|
||||
outline: none;
|
||||
border-color: #2f79a7;
|
||||
box-shadow: 0 0 0 3px rgba(58, 133, 180, 0.2);
|
||||
}
|
||||
|
||||
.auth-btn {
|
||||
width: 100%;
|
||||
border: none;
|
||||
border-radius: 999px;
|
||||
padding: 0.72rem;
|
||||
font-size: 1rem;
|
||||
font-weight: 700;
|
||||
color: #ffffff;
|
||||
background: linear-gradient(120deg, #0a5f8f 0%, #0b4567 100%);
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.auth-meta {
|
||||
margin-top: 1rem;
|
||||
color: #547184;
|
||||
}
|
||||
|
||||
.auth-meta a {
|
||||
color: #0a5f8f;
|
||||
font-weight: 700;
|
||||
}
|
||||
</style>
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<section class="auth-wrap">
|
||||
<h1>Registrierung</h1>
|
||||
<p>Legen Sie ein Konto an, um den Kalender fuer Terminanfragen zu nutzen.</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>
|
||||
</div>
|
||||
<div class="field">
|
||||
<label for="username">Benutzername</label>
|
||||
<input id="username" name="username" type="text" autocomplete="username" required>
|
||||
</div>
|
||||
<div class="field">
|
||||
<label for="password">Passwort (mind. 8 Zeichen)</label>
|
||||
<input id="password" name="password" type="password" autocomplete="new-password" required>
|
||||
</div>
|
||||
<div class="field">
|
||||
<label for="password_repeat">Passwort wiederholen</label>
|
||||
<input id="password_repeat" name="password_repeat" type="password" autocomplete="new-password" required>
|
||||
</div>
|
||||
<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>
|
||||
</section>
|
||||
{% endblock %}
|
||||
Reference in New Issue
Block a user