Files
it-hilf-sofort/app.py
T

552 lines
22 KiB
Python

#!/usr/bin/env python3
"""IT-Hilfe-Sofort.de — Flask-Webapp für IT-Dienstleistungen im Gesundheitswesen."""
import os
import re
from pathlib import Path
from flask import Flask
BASE_DIR = Path(__file__).parent
ARTIKEL_DIR = BASE_DIR
PORT = int(os.environ.get("PORT", "5003"))
app = Flask(__name__)
def _base_template(title: str, content: str, active: str = "") -> str:
"""Wrapper fuer einheitliches Seitenlayout.
Args:
title: Seitentitel als String.
content: HTML-Inhalt der Seite.
active: Aktiver Navigationspunkt.
Returns:
Vollstaendiges HTML-Dokument als String.
"""
return f"""<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{title} | IT-Hilfe-Sofort.de</title>
<style>
*,*::before,*::after{{box-sizing:border-box;margin:0;padding:0}}
body{{font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,sans-serif;background:#F9FAFB;color:#1F2937;line-height:1.6}}
.site-header{{background:#1F2937;padding:1rem 1.5rem;display:flex;align-items:center;justify-content:space-between}}
.site-header .logo{{color:#F9FAFB;font-weight:700;font-size:1.05rem;letter-spacing:-0.01em;text-decoration:none}}
.nav-link{{color:#9CA3AF;text-decoration:none;font-size:0.9rem;padding:0.5rem}}
.nav-link:hover,.nav-link.active{{color:#F9FAFB}}
.menu-toggle{{background:none;border:none;color:#9CA3AF;font-size:0.9rem;font-weight:600;cursor:pointer;padding:0.5rem;display:none}}
.hero{{background:linear-gradient(135deg,#20228a,#161e6e);color:#fff;padding:5rem 1.5rem;text-align:center}}
.hero h1{{font-size:2.2rem;font-weight:800;letter-spacing:-0.02em;line-height:1.2;margin-bottom:1rem}}
.hero p{{color:rgba(255,255,255,0.85);font-size:1.1rem;max-width:600px;margin:0 auto}}
.card{{background:#fff;border:1px solid #E5E7EB;border-radius:8px;padding:2rem}}
.card-grid{{display:grid;grid-template-columns:1fr;gap:1.5rem;max-width:1100px;margin:0 auto;padding:0 1.5rem}}
@media(min-width:768px){{.card-grid{{grid-template-columns:repeat(3,1fr)}}}}
.btn-primary{{display:inline-block;background:#20228a;color:#fff;border:none;border-radius:6px;padding:0.8rem 2rem;font-size:0.95rem;font-weight:600;text-decoration:none;cursor:pointer;transition:background 0.2s}}
.btn-primary:hover{{background:#161e6e}}
.content{{max-width:720px;margin:2rem auto;padding:0 1.5rem}}
.content h1{{font-size:2rem;font-weight:800;margin-bottom:1rem}}
.content h2{{font-size:1.5rem;font-weight:700;margin:2rem 0 1rem}}
.content p{{margin-bottom:1rem;line-height:1.7}}
.site-footer{{background:#1F2937;color:#9CA3AF;padding:3rem 1.5rem;font-size:0.85rem;text-align:center}}
.site-footer a{{color:#D1D5DB;text-decoration:none;margin:0 0.5rem}}
.site-footer a:hover{{color:#F9FAFB}}
.section{{padding:4rem 1.5rem}}
.section h2{{font-size:1.8rem;font-weight:700;text-align:center;margin-bottom:2rem}}
@media(max-width:767px){{.menu-toggle{{display:block}}nav#mainNav{{display:none}}nav#mainNav.open{{display:flex;flex-direction:column;position:fixed;top:56px;left:0;right:0;background:#1F2937;padding:1rem;gap:0;z-index:1000}}}}
</style>
</head>
<body>
<header class="site-header">
<a href="/" class="logo">IT-Hilfe-Sofort.de</a>
<nav id="mainNav" style="align-items:center;gap:0.5rem">
<a href="/" class="nav-link{" active" if active == "home" else ""}">Startseite</a>
<a href="/blog/telematik-vorschriften" class="nav-link{" active" if active == "blog" else ""}">Blog</a>
<a href="/leistungen/pflegedienste" class="nav-link{" active" if active == "leistungen" else ""}">Leistungen</a>
<a href="/it-service/hardware" class="nav-link{" active" if active == "it-service" else ""}">IT-Service</a>
<a href="/ueber-uns" class="nav-link{" active" if active == "ueber-uns" else ""}">Über uns</a>
<a href="/kontakt" class="btn-primary" style="padding:0.5rem 1.2rem;font-size:0.85rem">Kontakt</a>
</nav>
<button class="menu-toggle" onclick="document.getElementById('mainNav').classList.toggle('open')">Menü</button>
</header>
<main>{content}</main>
<footer class="site-footer">
<p>IT-Hilfe-Sofort.de — Spezialisiert auf Pflegeeinrichtungen</p>
<p style="margin-top:0.5rem"><a href="/impressum">Impressum</a> <a href="/datenschutz">Datenschutz</a></p>
</footer>
</body>
</html>"""
@app.route("/")
def index() -> str:
"""Startseite."""
content = """
<section class="hero">
<h1>IT-Hilfefür das Gesundheitswesen</h1>
<p>Sicher, schnell, spezialisiert auf Pflegeinrichtungen.</p>
<p style="margin-top:2rem"><a href="/kontakt" class="btn-primary">Beratungsgespräch vereinbaren</a></p>
</section>
<section class="section">
<h2>Unsere Werte</h2>
<div class="card-grid">
<div class="card"><h2>DSGVO-konform</h2><p>Ihre Patientendaten in sicheren Händen — mit lückenloser Dokumentation und zertifizierten Prozessen.</p></div>
<div class="card"><h2>24/7 Support</h2><p>Wir sind da, wenn Sie uns brauchen — mit garantierter Reaktionszeit und persönlichem Ansprechpartner.</p></div>
<div class="card"><h2>Förderfähig</h2><p>KfW-Anträge stellen wir gemeinsam — digitale Infrastruktur ohne finanzielle Hürden.</p></div>
</div>
</section>
<section class="section" style="background:#fff">
<h2>Unsere Leistungen</h2>
<div class="card-grid">
<div class="card"><h2>Pflegedienste</h2><p>Tourenplanung, mobile Datenerfassung, Abrechnung.</p></div>
<div class="card"><h2>Pflegeheime</h2><p>Heimverwaltung, Biometrie, Dokumentation.</p></div>
<div class="card"><h2>Tagespflegen</h2><p>Terminbuchung, Fahrdienst, Aktivierungsangebote.</p></div>
<div class="card"><h2>Hardware</h2><p>Server, Thin Clients, Drucker — Beschaftung & Einrichtung.</p></div>
<div class="card"><h2>Netzwerk</h2><p>WLAN-Ausleuchtung, VPN, Firewall, Netzwerksegmentierung.</p></div>
<div class="card"><h2>Support</h2><p>SLA-Stufen, Fernwartung, Monitoring — maßgeschneidert.</p></div>
</div>
</section>
"""
return _base_template("Startseite", content)
@app.route("/impressum")
def impressum() -> str:
"""Impressum."""
content = '<div class="content"><h1>Impressum</h1><p>Daniel Krause<br>Musterstraße 1<br>12345 Musterstadt</p><p>E-Mail: info@it-hilfe-sofort.de</p></div>'
return _base_template("Impressum", content)
@app.route("/datenschutz")
def datenschutz() -> str:
"""Datenschutzerklärung."""
content = '<div class="content"><h1>Datenschutzerklärung</h1><p>Platzhalter — vollständige Datenschutzerklärung folgt.</p></div>'
return _base_template("Datenschutz", content)
# ── Blog-Artikel-Datenbank ───────────────────────────────
_ARTIKEL = [
(
"/blog/telematik-vorschriften",
"TI-Anschlusspflicht 2025",
"artikel-01-ti-anschlusspflicht.html",
),
(
"/blog/telematik-vorschriften",
"Elektronische Abrechnung ab 12/2026",
"artikel-02-elektronische-abrechnung.html",
),
(
"/blog/telematik-vorschriften",
"SMC-B-Karte — 33% Abdeckung",
"artikel-03-smc-b-karte.html",
),
(
"/blog/dsgvo-it-sicherheit",
"46,9 Mio. EUR DSGVO-Bugelder",
"artikel-04-dsgvo-bussgelder.html",
),
(
"/blog/dsgvo-it-sicherheit",
"BSI: 16 Schwachstellen Pflegesoftware",
"artikel-05-bsi-schwachstellen.html",
),
(
"/blog/dsgvo-it-sicherheit",
"138 Sicherheitsvorfaelle Gesundheitswesen",
"artikel-06-sicherheitsvorfaelle.html",
),
(
"/blog/telematik-vorschriften",
"NIS-2 Registrierungsfrist",
"artikel-07-nis2.html",
),
(
"/blog/fachkraeftemangel",
"200.000 unbesetzte Pflegestellen",
"artikel-08-fachkraeftemangel.html",
),
(
"/blog/fachkraeftemangel",
"62% Altenpflege — Personalplanung",
"artikel-09-personalplanung.html",
),
(
"/blog/fachkraeftemangel",
"KI-Sprachassistent spart 27% Zeit",
"artikel-10-ki-sprachassistent.html",
),
(
"/blog/foerderung-finanzierung",
"Bis 12.000 EUR Digitalisierungszuschuss",
"artikel-11-digitalisierungszuschuss.html",
),
(
"/blog/foerderung-finanzierung",
"DiPA — 70 EUR monatlich ab 2026",
"artikel-12-dipa.html",
),
(
"/blog/foerderung-finanzierung",
"Pflegeversicherung 1 Mrd. Defizit",
"artikel-13-pflegeversicherung.html",
),
(
"/blog/qualitaet-pruefung",
"QPR ambulant ab Juli 2026",
"artikel-14-qpr-ambulant.html",
),
(
"/blog/qualitaet-pruefung",
"PeBeM verpflichtend ab 2026",
"artikel-15-pebem.html",
),
(
"/blog/qualitaet-pruefung",
"MDK-Pruefung digital bestehen",
"artikel-16-mdk-pruefung.html",
),
("/blog/telematik-vorschriften", "ePA fuer alle — Opt-out", "artikel-17-epa.html"),
(
"/blog/dsgvo-it-sicherheit",
"Cloud-Hosting Deutschland",
"artikel-18-cloud-hosting.html",
),
(
"/blog/praxis-tipps",
"Tablets fuer die Pflege — Top 5",
"artikel-19-tablets.html",
),
("/blog/praxis-tipps", "WLAN im Pflegeheim", "artikel-20-wlan.html"),
("/blog/praxis-tipps", "Offline-Dokumentation", "artikel-21-offline.html"),
(
"/blog/dsgvo-it-sicherheit",
"E-Mail-Verschluesselung",
"artikel-22-email-verschluesselung.html",
),
(
"/blog/praxis-tipps",
"Medikationsplan digital",
"artikel-23-medikationsplan.html",
),
(
"/blog/praxis-tipps",
"IT-Notfallplan 10-Punkte",
"artikel-24-it-notfallplan.html",
),
]
# ── Leistungen-Daten ─────────────────────────────────────
_LEISTUNGEN = {
"pflegedienste": {
"titel": "IT-Loesungen fuer ambulante Pflegedienste",
"cards": [
(
"Tourenplanung",
"Digitale Tourenplanung und mobile Datenerfassung vor Ort. Effizientere Routen und Dokumentation auf dem Tablet.",
),
(
"Mobile Dokumentation",
"Echtzeit-Dokumentation von Pflegemaßnahmen direkt im Einsatz. Synchronisiert mit der zentralen Verwaltung.",
),
(
"Abrechnung und Reporting",
"Automatisierte Abrechnung und Auswertungen. Weniger Verwaltungszeit, mehr Zeit fuer Patienten.",
),
],
},
"pflegeheime": {
"titel": "IT-Loesungen fuer stationaere Pflegeheime",
"cards": [
(
"Heimverwaltung",
"Digitale Heimpleitung: Dienstplanung, Raummanagement, Budget-Controller. Alles in einer Plattform.",
),
(
"Biometrie und Zutrittssysteme",
"Fingerabdruck- und Gesichtserkennung fuer sicheren Zutritt. DSGVO-konform und benutzerfreundlich.",
),
(
"Dokumentationssysteme",
"Komplette digitale Dokumentation von Pflegeplanung bis Medikationsueberwachung. Vollstaendig auditfahig.",
),
],
},
"tagespflegen": {
"titel": "IT-Loesungen fuer Tagespflegen",
"cards": [
(
"Terminbuchung",
"Online-Terminbuchung mit Kalendersynchronisation. Patienten koennen Termine direkt vereinbaren.",
),
(
"Fahrdienstverwaltung",
"Organisation von Fahrdiensten und Kurieren. Automatische Zuweisung und Echtzeit-Tracking.",
),
(
"Aktivierungsangebote",
"Digitales Planungs- und Monitoring-System fuer Aktivitaeten und Therapie-Programme im Tagesverlauf.",
),
],
},
}
# ── IT-Service-Daten ─────────────────────────────────────
_IT_SERVICE = {
"hardware": {
"titel": "IT-Hardware fuer das Gesundheitswesen",
"cards": [
(
"Server und Workstations",
"Auswahl, Installation und Wartung von Servern und Workstations. DSGVO-konform und skalierbar.",
),
(
"Thin Clients und Endgeraete",
"Kosteneffiziente Thin Clients mit zentralem Management. Einfache Administration, hohe Sicherheit.",
),
(
"Drucker und Peripherie",
"Medizinische Geraete und Drucker mit Spezialtreibern. Integration in bestehende Netzwerke.",
),
(
"Beschaffung und Consulting",
"Unabhaengige Beratung zur Hardware-Auswahl. Gutes Preis-Leistungs-Verhaeltnis garantiert.",
),
],
},
"netzwerk": {
"titel": "IT-Netzwerk fuer Pflegeeinrichtungen",
"cards": [
(
"WLAN-Ausleuchtung",
"Professionelle WLAN-Planung und -Implementierung fuer komplette Einrichtungen. Lueckenlose Abdeckung.",
),
(
"VPN und Remote-Zugang",
"Verschluesselte Verbindung fuer mobiles Arbeiten. Sichere Fernwartung und Fernadministration.",
),
(
"Firewall und Segmentierung",
"Zwei-Wege-Firewall mit medizinischen Geraete-Portabilitaet. Trennung von Betriebs- und Pflegedaten.",
),
(
"Netzwerkmonitoring",
"24/7 Ueberwachung aller Netzwerk-Komponenten. Proaktive Stoerungserkennung und automatische Eskalation.",
),
],
},
"email-kommunikation": {
"titel": "E-Mail und Kommunikation",
"cards": [
(
"Microsoft 365",
"Vollstaendige Implementierung und Verwaltung von Microsoft 365. Cloud-Hosting in Deutschland verfuegbar.",
),
(
"Exchange und VoIP",
"E-Mail-Server mit Exchange-Integration und VoIP-Telefonie. Nahtlose Kommunikation aller Abteilungen.",
),
(
"Spam-Schutz und Archivierung",
"Mehrschichtiger Spam-Schutz und automatische Archivierung fuer Compliance und Aufbewahrungspflichten.",
),
],
},
"support-wartung": {
"titel": "IT-Support und Wartung",
"cards": [
(
"SLA-Stufen",
"Flexible Service-Level-Agreements: von Standard bis Mission-Critical. Garantierte Reaktionszeiten fuer alle Stoerungen.",
),
(
"Reaktionszeiten",
"Erste Antwort innerhalb von 30 Minuten. Vollstaendige Loesung innerhalb von 4 Stunden bei schwerwiegenden Problemen.",
),
(
"Fernwartung und Hosting",
"Sichere Fernwartung mit Echtzeit-Desktop-Zugriff. DSGVO-konforme Hostung aller Systeme.",
),
(
"Monitoring und Wartung",
"Automatisiertes Monitoring aller IT-Komponenten. Regelmassige Sicherheitsupdates und Wartung in Einweisungszeiten.",
),
],
},
}
# ── Helper: Seitenleiste ──────────────────────────────────
def _sidebar(routes: list[tuple[str, str, str]]) -> str:
"""Erstelle Seitenleiste mit Artikel-Links.
Args:
routes: Liste von (Route, Titel, Datei)-Tupeln.
"""
links = []
for route, titel, _datei in routes:
links.append('<a href="' + route + '" class="sidebar-link">' + titel + "</a>")
return (
"<div class='article-sidebar'><h4 class='sidebar-title'>Weitere Artikel</h4>"
+ "".join(links)
+ "</div>"
)
# ── Helper: Karten bauen ─────────────────────────────────
def _cards(titel: str, beschreibung: str) -> str:
"""Erstelle eine Service-Karte.
Args:
titel: Titel der Karte.
beschreibung: Beschreibungstext.
"""
return '<div class="card"><h3>' + titel + "</h3><p>" + beschreibung + "</p></div>"
# ── Weitere Routen ───────────────────────────────────────
@app.route("/ueber-uns")
def ueber_uns() -> str:
"""Ueber uns."""
content = '<div class="content"><h1>Ueber uns</h1><p>Daniel Krause ist IT-Berater im Gesundheitswesen. Werte: Transparenz, Schnelligkeit, DSGVO-Compliance.</p></div>'
return _base_template("Ueber uns", content)
@app.route("/kontakt")
def kontakt() -> str:
"""Kontakt mit CRM-Formular."""
content = (
'<div class="content" style="max-width:900px">'
"<h1>Kontakt</h1>"
'<div style="display:grid;gap:2rem">'
'<div class="contact-info">'
"<p>Wir beraten Sie gerne persoenlich. Sprechen Sie uns an!</p>"
"<p><strong>E-Mail:</strong> info@it-hilfe-sofort.de</p>"
"</div>"
'<div style="border:1px solid #E5E7EB;border-radius:8px;overflow:hidden">'
'<iframe src="https://crm.companyhub.io/widget/form/iEDHWbU9iII32UkhXj2b" style="width:100%;height:946px;border:none" title="Kontaktformular"></iframe>'
"</div>"
"</div></div>"
)
return _base_template("Kontakt", content)
@app.route("/faq")
def faq() -> str:
"""FAQ."""
fragen: list[tuple[str, str]] = [
("Wie schnell sind Sie vor Ort?", "Innerhalb von 24—48 Stunden."),
("Was kostet der IT-Support?", "Ab 29 EUR/Monat pro Geraet."),
(
"Uebernehmen Sie die komplette IT?",
"Ja, von der Installation bis zum Monitoring.",
),
(
"Wie stellen Sie DSGVO-Compliance sicher?",
"Hosting in Deutschland, Verschlusselung, Zugangskontrollen.",
),
(
"Bieten Sie auch Schulungen an?",
"Ja, fuer alle Mitarbeiter Ihrer Einrichtung.",
),
(
"Wie laeuft der Onboarding ab?",
"Kostenlose Erstberatung, dann Umsetzung in 2—4 Wochen.",
),
(
"Koennen Sie auf bestehende Systeme aufsetzen?",
"Ja, wir arbeiten mit allen gaeingen Pflegesoftwaren.",
),
(
"Gibt es einen Notfallservice?",
"Ja, 24/7 Notfallservice fuer kritische Stoerungen.",
),
]
fragen_html_parts: list[str] = []
for f, t in fragen:
fragen_html_parts.append(
"<div class='faq-item'><summary>"
+ f
+ "</summary><div class='answer'>"
+ t
+ "</div></div>"
)
fragen_html = "".join(fragen_html_parts)
content = "<div class='content'><h1>Haeufige Fragen</h1>" + fragen_html + "</div>"
return _base_template("FAQ", content)
@app.route("/blog/<path:slug>")
def blog(slug: str) -> str:
"""Blog-Artikel."""
datei = "artikel-" + slug + ".html"
pfad = ARTIKEL_DIR / datei
if pfad.exists():
inhalt = pfad.read_text(encoding="utf-8")
# Extrahiere Body-Inhalt aus dem Artikel-HTML
match = re.search(r"<body[^>]*>(.*?)</body>", inhalt, re.DOTALL | re.IGNORECASE)
inhalt = match.group(1) if match else inhalt
else:
inhalt = "<p>Artikel nicht gefunden.</p>"
titel = slug.replace("-", " ").title()
content = (
"<div class='article-layout'><div class='article-content'>" + inhalt + "</div>"
)
# Seitenleiste: alle anderen Artikel derselben Sektion
sektion_routen = [
(r, t, d) for r, t, d in _ARTIKEL if r == "/blog/" + slug.replace("-", "")
]
if not sektion_routen:
sektion_routen = _ARTIKEL
sidebar = _sidebar(sektion_routen)
content += sidebar + "</div>"
return _base_template("Blog: " + titel, content, active="blog")
@app.route("/leistungen/<path:slug>")
def leistungen(slug: str) -> str:
"""Leistungs-Seite."""
data = _LEISTUNGEN.get(slug)
if not data:
content = "<div class='content'><h1>Leistung nicht gefunden</h1></div>"
return _base_template("Leistungen", content)
cards_items = [_cards(titel, beschreibung) for titel, beschreibung in data["cards"]]
cards_all = (
'<div class="card-grid" style="margin-top:2rem">'
+ "".join(cards_items)
+ "</div>"
)
content = (
"<div class='content'><h1>" + data["titel"] + "</h1>" + cards_all + "</div>"
)
return _base_template(data["titel"], content, active="leistungen")
@app.route("/it-service/<path:slug>")
def it_service(slug: str) -> str:
"""IT-Service-Seite."""
data = _IT_SERVICE.get(slug)
if not data:
content = "<div class='content'><h1>Service nicht gefunden</h1></div>"
return _base_template("IT-Service", content)
cards_items = [_cards(titel, beschreibung) for titel, beschreibung in data["cards"]]
cards_all = (
'<div class="card-grid" style="margin-top:2rem">'
+ "".join(cards_items)
+ "</div>"
)
content = (
"<div class='content'><h1>" + data["titel"] + "</h1>" + cards_all + "</div>"
)
return _base_template(data["titel"], content, active="it-service")
# ── Main ──────────────────────────────────────────────────────────────
if __name__ == "__main__":
print(f"IT-Hilfe-Sofort.de startet auf http://127.0.0.1:{PORT}")
app.run(host="127.0.0.1", port=PORT, debug=False)