Kreis Herford und Bielefeld
.tnd-praxenliste {
--ink: #3d434c;
--ink-deep: #2f363f;
--paper: #ffffff;
--mint: #3ec492;
--mint-deep: #2f9e78;
--red: #e3000f;
--line: #e0dede;
--muted: #8b8e94;
font-family: "Cabin", -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
color: var(--ink);
box-sizing: border-box;
padding: 0 clamp(20px, 5vw, 64px);
}
.tnd-praxenliste *,
.tnd-praxenliste *::before,
.tnd-praxenliste *::after {
box-sizing: inherit;
}
.tnd-praxenliste__meta {
display: flex;
align-items: baseline;
justify-content: space-between;
gap: 16px;
flex-wrap: wrap;
padding-bottom: 14px;
margin-bottom: 24px;
border-bottom: 2px solid var(--line);
font-size: 0.92rem;
color: var(--muted);
}
.tnd-praxenliste__zaehler {
font-weight: 700;
font-variant-numeric: tabular-nums;
color: var(--ink);
}
.tnd-praxenliste__liste {
list-style: none;
margin: 0;
padding: 0;
display: grid;
grid-template-columns: 1fr;
gap: 18px;
}
/* Feste Stufen statt auto-fill -- bei voller Bildschirmbreite wuerde
auto-fill sonst 5+ Spalten in eine Reihe quetschen. Deckelt bei 4. */
@media (min-width: 560px) {
.tnd-praxenliste__liste { grid-template-columns: repeat(2, 1fr); }
}
@media (min-width: 860px) {
.tnd-praxenliste__liste { grid-template-columns: repeat(3, 1fr); }
}
@media (min-width: 1180px) {
.tnd-praxenliste__liste { grid-template-columns: repeat(4, 1fr); }
}
.tnd-praxenliste__item {
background: var(--paper);
border: 1px solid var(--line);
border-radius: 6px;
padding: 20px 22px;
display: flex;
flex-direction: column;
gap: 12px;
position: relative;
overflow: hidden;
transition: border-color 0.15s ease, box-shadow 0.15s ease;
}
.tnd-praxenliste__item::before {
content: "";
position: absolute;
top: 0; left: 0; right: 0;
height: 3px;
background: var(--red);
transform: scaleX(0);
transform-origin: left;
transition: transform 0.25s ease;
}
.tnd-praxenliste__item:hover {
border-color: #d3d3d3;
box-shadow: 0 6px 16px rgba(47, 54, 63, 0.08);
}
.tnd-praxenliste__item:hover::before {
transform: scaleX(1);
}
.tnd-praxenliste__name {
font-family: "Patua One", Arial, Helvetica, sans-serif;
font-weight: 400;
font-size: 1.12rem;
line-height: 1.25;
margin: 0;
}
.tnd-praxenliste__tel {
display: inline-flex;
align-items: center;
gap: 8px;
align-self: flex-start;
font-family: "Cabin", sans-serif;
font-weight: 700;
font-size: 1.08rem;
font-variant-numeric: tabular-nums;
color: var(--mint-deep);
text-decoration: none;
padding: 2px 0;
border-bottom: 1.5px solid transparent;
}
.tnd-praxenliste__tel:hover {
color: var(--mint);
border-color: var(--mint);
}
.tnd-praxenliste__tel svg {
flex: none;
color: var(--mint-deep);
}
.tnd-praxenliste__zeile {
display: flex;
align-items: flex-start;
gap: 9px;
font-size: 0.86rem;
line-height: 1.48;
color: var(--muted);
}
.tnd-praxenliste__zeile svg {
flex: none;
margin-top: 2px;
color: var(--muted);
opacity: 0.8;
}
.tnd-praxenliste__zeile a {
color: var(--muted);
text-decoration: underline;
text-decoration-color: var(--line);
text-underline-offset: 2px;
}
.tnd-praxenliste__zeile a:hover {
color: var(--ink);
text-decoration-color: var(--mint);
}
.tnd-praxenliste__zeile--zeiten {
padding-top: 8px;
margin-top: 2px;
border-top: 1px solid var(--line);
}
.tnd-praxenliste__leer {
grid-column: 1 / -1;
text-align: center;
padding: 40px 20px;
color: var(--muted);
}
.tnd-praxenliste__oz-hinweis {
display: block;
margin-top: 3px;
font-style: italic;
color: var(--muted);
}
.tnd-praxenliste strong {
color: inherit;
font-weight: 700;
}
(function () {
var API_BASIS = "https://managed.hotline.thorwesten.io";
var ICONS = {
telefon: '',
adresse: '',
email: '',
uhr: ''
};
function escHtml(str) {
if (!str) return "";
// Entity-Namen bewusst per Verkettung gebaut, nicht als Text-Literal im
// Quelltext -- WordPress' wptexturize() dekodiert benannte
// HTML-Entities global im gespeicherten Content, auch innerhalb von
// -Bloecken, und zerstoert damit sonst diese Strings.
var amp = String.fromCharCode(38);
return String(str)
.replace(/&/g, amp + "amp;")
.replace(//g, amp + "gt;")
.replace(/"/g, amp + "quot;");
}
function telHref(telefon) {
return "tel:+" + String(telefon).replace(/[^0-9]/g, "");
}
var TAGE = ["Mo", "Di", "Mi", "Do", "Fr", "Sa", "So", "Feiertags"];
function formatOeffnungszeiten(struktur, hinweis) {
var byTag = {};
struktur.forEach(function (e) {
var t = e.wochentag;
if (!byTag[t]) byTag[t] = [];
byTag[t].push(e.zeit_von + "\u2013" + e.zeit_bis);
});
var order = [0, 1, 2, 3, 4, 5, 6];
var zeilen = [];
var i = 0;
while (i < order.length) {
var tag = order[i];
if (!byTag[tag]) { i++; continue; }
var sig = byTag[tag].join(",");
var start = tag, end = tag, j = i + 1;
while (j < order.length && byTag[order[j]] && byTag[order[j]].join(",") === sig) {
end = order[j];
j++;
}
var label = (start === end) ? TAGE[start] : TAGE[start] + "\u2013" + TAGE[end];
zeilen.push("
" + escHtml(label) + " " + escHtml(byTag[tag].join(" und ")));
i = j;
}
if (byTag[7]) {
zeilen.push("
" + escHtml(TAGE[7]) + " " + escHtml(byTag[7].join(" und ")));
}
var html = zeilen.join("
");
if (hinweis) {
html += '
(' + escHtml(hinweis) + ")";
}
return html;
}
function karte(p, opts) {
var html = '
';
html += '' + escHtml(p.name) + "
";
if (opts.telefon && p.telefon) {
html += '' +
ICONS.telefon + escHtml(p.telefon) + "";
}
if (opts.adresse && p.adresse) {
html += '' + ICONS.adresse +
"" + escHtml(p.adresse) + "
";
}
if (opts.email && p.email) {
html += '";
}
if (opts.oeffnungszeiten && p.oeffnungszeiten_struktur && p.oeffnungszeiten_struktur.length) {
html += '' + ICONS.uhr +
"" + formatOeffnungszeiten(p.oeffnungszeiten_struktur, p.oeffnungszeiten_hinweis) + "
";
} else if (opts.oeffnungszeiten && p.oeffnungszeiten) {
html += '' + ICONS.uhr +
"" + escHtml(p.oeffnungszeiten).replace(/\n/g, "
") + "
";
}
html += "";
return html;
}
function render(container, praxen, opts) {
if (!praxen.length) {
container.innerHTML = '
Keine Praxen gefunden.
';
return;
}
var meta = '
' +
"Mitgliedspraxen des tierärztlichen Notdienstrings" +
'' + praxen.length + " Praxen
";
var liste = '
' +
praxen.map(function (p) { return karte(p, opts); }).join("") +
"
";
container.innerHTML = meta + liste;
}
document.querySelectorAll(".tnd-praxenliste").forEach(function (container) {
var mandantId = container.getAttribute("data-mandant-id");
if (!mandantId) {
console.warn("[TND Praxenliste] data-mandant-id fehlt.");
return;
}
var opts = {
adresse: container.getAttribute("data-zeige-adresse") !== "0",
telefon: container.getAttribute("data-zeige-telefon") !== "0",
email: container.getAttribute("data-zeige-email") !== "0",
oeffnungszeiten: container.getAttribute("data-zeige-oeffnungszeiten") !== "0",
};
fetch(API_BASIS + "/api/v1/oeffentlich/praxen?mandant_id=" + encodeURIComponent(mandantId))
.then(function (res) {
if (!res.ok) throw new Error("HTTP " + res.status);
return res.json();
})
.then(function (praxen) {
render(container, praxen, opts);
})
.catch(function (err) {
console.warn("[TND Praxenliste] Fehler beim Laden:", err);
container.innerHTML = '
Praxenliste konnte nicht geladen werden.
';
});
});
})();