Ansprechpartner-Sektion: person-card/person-grid-Komponenten, Daten in ansprechpartner.json, Vereins-Platzhalter statt AdobeStock, tel:/mailto korrekt
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
41
app/components/person-card.php
Normal file
41
app/components/person-card.php
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Visitenkarte für eine Person. Props:
|
||||||
|
* $person array{department, name, phone?, email?, image?}
|
||||||
|
* Ohne image greift der Vereins-Platzhalter (Silhouette im TSV-Trikot).
|
||||||
|
* Kontakt-Link: phone → tel:, sonst email → mailto:.
|
||||||
|
*/
|
||||||
|
$image = $person['image'] ?? null;
|
||||||
|
$src = $image ?: 'img/persons/platzhalter.jpg';
|
||||||
|
|
||||||
|
if (!empty($person['phone'])) {
|
||||||
|
$contactHref = 'tel:' . preg_replace('/[^+\d]/', '', $person['phone']);
|
||||||
|
$contactLabel = $person['phone'];
|
||||||
|
$contactIcon = 'telephone';
|
||||||
|
} elseif (!empty($person['email'])) {
|
||||||
|
$contactHref = 'mailto:' . $person['email'];
|
||||||
|
$contactLabel = $person['email'];
|
||||||
|
$contactIcon = 'envelope';
|
||||||
|
} else {
|
||||||
|
$contactHref = null;
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
<article class="person-card">
|
||||||
|
<div class="person-card__media">
|
||||||
|
<img src="<?= e(asset($src)) ?>"
|
||||||
|
alt="<?= $image ? e($person['name']) : '' ?>"
|
||||||
|
width="480" height="600" loading="lazy" decoding="async">
|
||||||
|
</div>
|
||||||
|
<div class="person-card__body">
|
||||||
|
<h3 class="person-card__department"><?= e($person['department']) ?></h3>
|
||||||
|
<p class="person-card__name"><?= e($person['name']) ?></p>
|
||||||
|
<?php if ($contactHref !== null): ?>
|
||||||
|
<a class="person-card__contact" href="<?= e($contactHref) ?>">
|
||||||
|
<?= icon($contactIcon) ?><span><?= e($contactLabel) ?></span>
|
||||||
|
</a>
|
||||||
|
<?php endif; ?>
|
||||||
|
</div>
|
||||||
|
</article>
|
||||||
26
app/components/person-grid.php
Normal file
26
app/components/person-grid.php
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ansprechpartner-Grid aus data/ansprechpartner.json.
|
||||||
|
* Optionaler Prop: $anchor (Sektions-ID, Default 'ansprechpartner').
|
||||||
|
*/
|
||||||
|
$data = json_load('ansprechpartner');
|
||||||
|
$anchor = $anchor ?? 'ansprechpartner';
|
||||||
|
?>
|
||||||
|
<section class="section persons" id="<?= e($anchor) ?>">
|
||||||
|
<div class="container">
|
||||||
|
<h2><?= e($data['title']) ?></h2>
|
||||||
|
<?php if (!empty($data['intro'])): ?>
|
||||||
|
<p class="persons__intro"><?= e($data['intro']) ?></p>
|
||||||
|
<?php endif; ?>
|
||||||
|
<ul class="persons__grid">
|
||||||
|
<?php foreach ($data['persons'] as $person): ?>
|
||||||
|
<li>
|
||||||
|
<?php component('person-card', ['person' => $person]); ?>
|
||||||
|
</li>
|
||||||
|
<?php endforeach; ?>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
36
data/ansprechpartner.json
Normal file
36
data/ansprechpartner.json
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
{
|
||||||
|
"title": "Ansprechpartner",
|
||||||
|
"intro": "Du hast Fragen zu einer Abteilung? Unsere Ansprechpartner helfen dir direkt weiter.",
|
||||||
|
"persons": [
|
||||||
|
{
|
||||||
|
"department": "Herrenfußball",
|
||||||
|
"name": "Benedikt Höfner",
|
||||||
|
"phone": "+49 160 97516404",
|
||||||
|
"image": "img/persons/benedikt-hoefner.jpg"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"department": "Damenfußball",
|
||||||
|
"name": "Sam Kern",
|
||||||
|
"phone": "+49 176 91371064",
|
||||||
|
"image": "img/persons/sam-kern.jpg"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"department": "Jugendfußball",
|
||||||
|
"name": "Fabian Früh",
|
||||||
|
"phone": "+49 160 97516797",
|
||||||
|
"image": "img/persons/fabian-frueh.jpg"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"department": "Jugendfußball",
|
||||||
|
"name": "Kerstin Tauber",
|
||||||
|
"phone": "+49 176 38957526",
|
||||||
|
"image": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"department": "Turnen",
|
||||||
|
"name": "Maxi Roßberg",
|
||||||
|
"email": "turnabteilung.tsv08kulmbach@gmail.com",
|
||||||
|
"image": null
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -277,6 +277,90 @@
|
|||||||
object-fit: contain;
|
object-fit: contain;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* === persons (Ansprechpartner-Visitenkarten) === */
|
||||||
|
.persons > .container {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.persons__intro {
|
||||||
|
margin-inline: auto;
|
||||||
|
margin-top: 1rem;
|
||||||
|
max-width: 60ch;
|
||||||
|
color: var(--clr-text-muted);
|
||||||
|
}
|
||||||
|
|
||||||
|
.persons__grid {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
|
||||||
|
gap: 1.5rem;
|
||||||
|
margin-top: 2.5rem;
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.person-card {
|
||||||
|
display: grid;
|
||||||
|
height: 100%;
|
||||||
|
background: var(--clr-glass-bg);
|
||||||
|
border: 1px solid var(--clr-glass-border);
|
||||||
|
border-radius: var(--radius-card);
|
||||||
|
overflow: hidden;
|
||||||
|
transition: transform var(--transition), box-shadow var(--transition);
|
||||||
|
}
|
||||||
|
|
||||||
|
.person-card:hover {
|
||||||
|
transform: translateY(-4px);
|
||||||
|
box-shadow: var(--shadow-card);
|
||||||
|
}
|
||||||
|
|
||||||
|
.person-card__media img {
|
||||||
|
width: 100%;
|
||||||
|
height: auto;
|
||||||
|
aspect-ratio: 4 / 5;
|
||||||
|
object-fit: cover;
|
||||||
|
}
|
||||||
|
|
||||||
|
.person-card__body {
|
||||||
|
display: grid;
|
||||||
|
gap: 0.2rem;
|
||||||
|
padding: 1.1rem 1.2rem 1.2rem;
|
||||||
|
/* Verlauf knüpft an die dunklen Studiofotos an */
|
||||||
|
background: linear-gradient(180deg, rgb(20 20 20 / 0) 0%, rgb(20 20 20 / 0.35) 100%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.person-card__department {
|
||||||
|
font-size: var(--fs-650);
|
||||||
|
letter-spacing: 0.04em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.person-card__name {
|
||||||
|
color: var(--clr-text-muted);
|
||||||
|
}
|
||||||
|
|
||||||
|
.person-card__contact {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.5rem;
|
||||||
|
margin-top: 0.5rem;
|
||||||
|
padding-block: 0.3rem;
|
||||||
|
color: var(--clr-text);
|
||||||
|
text-decoration: none;
|
||||||
|
font-size: var(--fs-500);
|
||||||
|
}
|
||||||
|
|
||||||
|
.person-card__contact .icon {
|
||||||
|
color: var(--clr-accent);
|
||||||
|
flex: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.person-card__contact span {
|
||||||
|
overflow-wrap: anywhere;
|
||||||
|
}
|
||||||
|
|
||||||
|
.person-card__contact:hover {
|
||||||
|
text-decoration: underline;
|
||||||
|
text-underline-offset: 0.25em;
|
||||||
|
}
|
||||||
|
|
||||||
/* === contact form === */
|
/* === contact form === */
|
||||||
.contact__inner {
|
.contact__inner {
|
||||||
display: grid;
|
display: grid;
|
||||||
@@ -462,7 +546,9 @@
|
|||||||
|
|
||||||
.ad-banner__subline {
|
.ad-banner__subline {
|
||||||
margin-top: 0.75rem;
|
margin-top: 0.75rem;
|
||||||
max-width: 70ch;
|
/* Volle Breite, damit der Dank in einer Zeile steht; auf Mobil bricht er natürlich um. */
|
||||||
|
max-width: none;
|
||||||
|
text-wrap: balance;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ad-banner__track {
|
.ad-banner__track {
|
||||||
|
|||||||
1
public/assets/icons/telephone.svg
Normal file
1
public/assets/icons/telephone.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><path d="M3.654 1.328a.678.678 0 0 0-1.015-.063L1.605 2.3c-.483.484-.661 1.169-.45 1.77a17.6 17.6 0 0 0 4.168 6.608 17.6 17.6 0 0 0 6.608 4.168c.601.211 1.286.033 1.77-.45l1.034-1.034a.678.678 0 0 0-.063-1.015l-2.307-1.794a.68.68 0 0 0-.58-.122l-2.19.547a1.75 1.75 0 0 1-1.657-.459L5.482 8.062a1.75 1.75 0 0 1-.46-1.657l.548-2.19a.68.68 0 0 0-.122-.58zM1.884.511a1.745 1.745 0 0 1 2.612.163L6.29 2.98c.329.423.445.974.315 1.494l-.547 2.19a.68.68 0 0 0 .178.643l2.457 2.457a.68.68 0 0 0 .644.178l2.189-.547a1.75 1.75 0 0 1 1.494.315l2.306 1.794c.829.645.905 1.87.163 2.611l-1.034 1.034c-.74.74-1.846 1.065-2.877.702a18.6 18.6 0 0 1-7.01-4.42 18.6 18.6 0 0 1-4.42-7.009c-.362-1.03-.037-2.137.703-2.877z"/></svg>
|
||||||
|
After Width: | Height: | Size: 770 B |
BIN
public/assets/img/persons/benedikt-hoefner.jpg
Normal file
BIN
public/assets/img/persons/benedikt-hoefner.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 29 KiB |
BIN
public/assets/img/persons/fabian-frueh.jpg
Normal file
BIN
public/assets/img/persons/fabian-frueh.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 32 KiB |
BIN
public/assets/img/persons/platzhalter.jpg
Normal file
BIN
public/assets/img/persons/platzhalter.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 28 KiB |
BIN
public/assets/img/persons/sam-kern.jpg
Normal file
BIN
public/assets/img/persons/sam-kern.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 37 KiB |
Reference in New Issue
Block a user