From 3346d16c3f9f906600575615248ac28c8193272e Mon Sep 17 00:00:00 2001 From: Tobias Feigel Date: Sat, 28 Jun 2025 18:37:13 +0200 Subject: [PATCH] feat: add termine.php template and integration with ICS calendar feed for event fetching, parsing, and display --- assets/css/styles.css | 26 ++++++++ content/5_termine/termine.txt | 6 +- site/snippets/termine.php | 112 ++++++++++++++++++++++++++++++++++ site/templates/termine.php | 34 +++++++++++ 4 files changed, 177 insertions(+), 1 deletion(-) create mode 100644 site/snippets/termine.php create mode 100644 site/templates/termine.php diff --git a/assets/css/styles.css b/assets/css/styles.css index 29f2632..b721574 100644 --- a/assets/css/styles.css +++ b/assets/css/styles.css @@ -8,6 +8,7 @@ monospace; --color-red-50: oklch(97.1% 0.013 17.38); --color-red-500: oklch(63.7% 0.237 25.331); + --color-red-600: oklch(57.7% 0.245 27.325); --color-blue-500: oklch(62.3% 0.214 259.815); --color-blue-600: oklch(54.6% 0.245 262.881); --color-pink-500: oklch(65.6% 0.241 354.308); @@ -21,6 +22,7 @@ --color-white: #fff; --spacing: 0.25rem; --container-lg: 32rem; + --container-3xl: 48rem; --container-7xl: 80rem; --text-sm: 0.875rem; --text-sm--line-height: calc(1.25 / 0.875); @@ -362,6 +364,9 @@ .w-full { width: 100%; } + .max-w-3xl { + max-width: var(--container-3xl); + } .max-w-7xl { max-width: var(--container-7xl); } @@ -473,6 +478,10 @@ border-top-style: var(--tw-border-style); border-top-width: 1px; } + .border-b { + border-bottom-style: var(--tw-border-style); + border-bottom-width: 1px; + } .border-gray-200 { border-color: var(--color-gray-200); } @@ -512,6 +521,9 @@ .object-cover { object-fit: cover; } + .p-4 { + padding: calc(var(--spacing) * 4); + } .px-2 { padding-inline: calc(var(--spacing) * 2); } @@ -640,6 +652,9 @@ .text-red-500 { color: var(--color-red-500); } + .text-red-600 { + color: var(--color-red-600); + } .text-sf_blau-500 { color: var(--color-sf_blau-500); } @@ -674,6 +689,10 @@ .opacity-50 { opacity: 50%; } + .shadow { + --tw-shadow: 0 1px 3px 0 var(--tw-shadow-color, rgb(0 0 0 / 0.1)), 0 1px 2px -1px var(--tw-shadow-color, rgb(0 0 0 / 0.1)); + box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow); + } .shadow-lg { --tw-shadow: 0 10px 15px -3px var(--tw-shadow-color, rgb(0 0 0 / 0.1)), 0 4px 6px -4px var(--tw-shadow-color, rgb(0 0 0 / 0.1)); box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow); @@ -766,6 +785,13 @@ } } } + .hover\:bg-gray-50 { + &:hover { + @media (hover: hover) { + background-color: var(--color-gray-50); + } + } + } .hover\:bg-gray-100 { &:hover { @media (hover: hover) { diff --git a/content/5_termine/termine.txt b/content/5_termine/termine.txt index 482e81c..0492c02 100644 --- a/content/5_termine/termine.txt +++ b/content/5_termine/termine.txt @@ -1,3 +1,7 @@ Title: Termine ----- \ No newline at end of file +---- + +HeroText: Wir möchten Sie gerne über die bevorstehenden Termine in unserem Verein informieren. Halten Sie sich bereit für spannende Ereignisse und Veranstaltungen, die bald anstehen. Details zu den Terminen und Veranstaltungen finden Sie auf unserer Homepage. + +---- diff --git a/site/snippets/termine.php b/site/snippets/termine.php new file mode 100644 index 0000000..6204b38 --- /dev/null +++ b/site/snippets/termine.php @@ -0,0 +1,112 @@ +Kalender konnte nicht geladen werden.'; + return; + } + + // Termine parsen + function parse_ics($ics) { + $lines = explode("\n", $ics); + $events = []; + $event = []; + $inEvent = false; + foreach ($lines as $line) { + $line = trim($line); + if ($line === 'BEGIN:VEVENT') { + $inEvent = true; + $event = []; + } elseif ($line === 'END:VEVENT') { + $inEvent = false; + $events[] = $event; + } elseif ($inEvent) { + // Property kann Parameter enthalten, z.B. DTSTART;TZID=Europe/Berlin:20240701T19000000 + $parts = explode(':', $line, 2); + if (count($parts) === 2) { + $key = $parts[0]; + $val = $parts[1]; + // Nur den eigentlichen Property-Namen extrahieren + $key = strtoupper(preg_replace('/;.+$/', '', $key)); + $event[$key] = $val; + } + } + } + return $events; + } + + function format_ics_date($date) { + // Unterstützt sowohl ganztägige als auch Zeitangaben + if (strpos($date, 'T') !== false) { + $dt = DateTime::createFromFormat('Ymd\THis', substr($date, 0, 15)); + return $dt ? $dt->format('d.m.Y H:i') : $date; + } else { + $dt = DateTime::createFromFormat('Ymd', $date); + return $dt ? $dt->format('d.m.Y') : $date; + } + } + + $events = parse_ics($ics); + // Nur Events mit DTSTART berücksichtigen + $events = array_filter($events, function($event) { + return isset($event['DTSTART']) && !empty($event['DTSTART']); + }); + // Nach Datum sortieren + usort($events, function($a, $b) { + return strcmp($a['DTSTART'], $b['DTSTART']); + }); + + // Aktuelles Datum + $today = (new DateTime())->format('Ymd'); + + // Nur zukünftige Termine anzeigen + $future_events = array_filter($events, function($event) use ($today) { + return isset($event['DTSTART']) && $event['DTSTART'] >= $today; + }); + +?> +
+
+ +
Keine bevorstehenden Termine gefunden.
+ +
+ + + + + + + + + + + + + + + + + + + + + + +
DatumUhrzeitTitelOrtBeschreibung
+
+ +
+
\ No newline at end of file diff --git a/site/templates/termine.php b/site/templates/termine.php new file mode 100644 index 0000000..e256c0d --- /dev/null +++ b/site/templates/termine.php @@ -0,0 +1,34 @@ +title()`. + + This default template must not be removed. It is used whenever Kirby + cannot find a template with the name of the content file. + + Snippets like the header and footer contain markup used in + multiple templates. They also help to keep templates clean. + + More about templates: https://getkirby.com/docs/guide/templates/basics + */ + +?> + + + + + + + + + + + + +