Compare commits
11 Commits
2aff4a4a5b
...
30a1c4ad8e
| Author | SHA1 | Date | |
|---|---|---|---|
| 30a1c4ad8e | |||
| bbe05bd765 | |||
| afadbbc835 | |||
| 6c73455013 | |||
| 76d072bd44 | |||
| 5d15f4bbc8 | |||
| b829f0e479 | |||
| 20c1721f8e | |||
| 2f782a4f6e | |||
| 95dce6b534 | |||
| 405908f48d |
@@ -20,7 +20,7 @@ RewriteEngine on
|
|||||||
# In some environments it's necessary to
|
# In some environments it's necessary to
|
||||||
# set the RewriteBase to:
|
# set the RewriteBase to:
|
||||||
#
|
#
|
||||||
# RewriteBase /
|
RewriteBase /
|
||||||
|
|
||||||
# block files and folders beginning with a dot, such as .git
|
# block files and folders beginning with a dot, such as .git
|
||||||
# except for the .well-known folder, which is used for Let's Encrypt and security.txt
|
# except for the .well-known folder, which is used for Let's Encrypt and security.txt
|
||||||
@@ -34,6 +34,7 @@ RewriteRule ^site/(.*) index.php [L]
|
|||||||
|
|
||||||
# block direct access to Kirby and the Panel sources
|
# block direct access to Kirby and the Panel sources
|
||||||
RewriteRule ^kirby/(.*) index.php [L]
|
RewriteRule ^kirby/(.*) index.php [L]
|
||||||
|
RewriteRule ^vendor/getkirby/(.*) index.php [L]
|
||||||
|
|
||||||
# make site links work
|
# make site links work
|
||||||
RewriteCond %{REQUEST_FILENAME} !-f
|
RewriteCond %{REQUEST_FILENAME} !-f
|
||||||
|
|||||||
@@ -67,16 +67,16 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "claviska/simpleimage",
|
"name": "claviska/simpleimage",
|
||||||
"version": "4.2.1",
|
"version": "4.4.0",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/claviska/SimpleImage.git",
|
"url": "https://github.com/claviska/SimpleImage.git",
|
||||||
"reference": "ec6d5021e5a7153a2520d64c59b86b6f3c4157c5"
|
"reference": "6d928c779e343100cef40f75bac3e301c32c3741"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/claviska/SimpleImage/zipball/ec6d5021e5a7153a2520d64c59b86b6f3c4157c5",
|
"url": "https://api.github.com/repos/claviska/SimpleImage/zipball/6d928c779e343100cef40f75bac3e301c32c3741",
|
||||||
"reference": "ec6d5021e5a7153a2520d64c59b86b6f3c4157c5",
|
"reference": "6d928c779e343100cef40f75bac3e301c32c3741",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
@@ -108,7 +108,7 @@
|
|||||||
"description": "A PHP class that makes working with images as simple as possible.",
|
"description": "A PHP class that makes working with images as simple as possible.",
|
||||||
"support": {
|
"support": {
|
||||||
"issues": "https://github.com/claviska/SimpleImage/issues",
|
"issues": "https://github.com/claviska/SimpleImage/issues",
|
||||||
"source": "https://github.com/claviska/SimpleImage/tree/4.2.1"
|
"source": "https://github.com/claviska/SimpleImage/tree/4.4.0"
|
||||||
},
|
},
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
@@ -116,7 +116,7 @@
|
|||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"time": "2024-11-22T13:25:03+00:00"
|
"time": "2025-11-20T16:58:37+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "composer/semver",
|
"name": "composer/semver",
|
||||||
@@ -268,21 +268,21 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "getkirby/cms",
|
"name": "getkirby/cms",
|
||||||
"version": "5.1.1",
|
"version": "5.2.1",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/getkirby/kirby.git",
|
"url": "https://github.com/getkirby/kirby.git",
|
||||||
"reference": "fb11f5e3ec422e948fb1a52f16988335bb3489b4"
|
"reference": "42cd286dab62d87a331e53abfe103e4fba118dd6"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/getkirby/kirby/zipball/fb11f5e3ec422e948fb1a52f16988335bb3489b4",
|
"url": "https://api.github.com/repos/getkirby/kirby/zipball/42cd286dab62d87a331e53abfe103e4fba118dd6",
|
||||||
"reference": "fb11f5e3ec422e948fb1a52f16988335bb3489b4",
|
"reference": "42cd286dab62d87a331e53abfe103e4fba118dd6",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
"christian-riesen/base32": "1.6.0",
|
"christian-riesen/base32": "1.6.0",
|
||||||
"claviska/simpleimage": "4.2.1",
|
"claviska/simpleimage": "4.4.0",
|
||||||
"composer/semver": "3.4.4",
|
"composer/semver": "3.4.4",
|
||||||
"ext-ctype": "*",
|
"ext-ctype": "*",
|
||||||
"ext-curl": "*",
|
"ext-curl": "*",
|
||||||
@@ -297,36 +297,31 @@
|
|||||||
"ext-simplexml": "*",
|
"ext-simplexml": "*",
|
||||||
"filp/whoops": "2.18.4",
|
"filp/whoops": "2.18.4",
|
||||||
"getkirby/composer-installer": "^1.2.1",
|
"getkirby/composer-installer": "^1.2.1",
|
||||||
"laminas/laminas-escaper": "2.17.0",
|
"laminas/laminas-escaper": "2.18.0",
|
||||||
"michelf/php-smartypants": "1.8.1",
|
"michelf/php-smartypants": "1.8.1",
|
||||||
"php": "~8.2.0 || ~8.3.0 || ~8.4.0",
|
"php": "~8.2.0 || ~8.3.0 || ~8.4.0 || ~8.5.0",
|
||||||
"phpmailer/phpmailer": "6.10.0",
|
"phpmailer/phpmailer": "7.0.1",
|
||||||
"symfony/polyfill-intl-idn": "1.33.0",
|
"symfony/polyfill-intl-idn": "1.33.0",
|
||||||
"symfony/polyfill-mbstring": "1.33.0",
|
"symfony/polyfill-mbstring": "1.33.0",
|
||||||
"symfony/yaml": "7.3.3"
|
"symfony/yaml": "7.4.1"
|
||||||
},
|
},
|
||||||
"replace": {
|
"replace": {
|
||||||
"symfony/polyfill-php72": "*"
|
"symfony/polyfill-php72": "*"
|
||||||
},
|
},
|
||||||
"suggest": {
|
"suggest": {
|
||||||
"ext-PDO": "Support for using databases",
|
|
||||||
"ext-apcu": "Support for the Apcu cache driver",
|
"ext-apcu": "Support for the Apcu cache driver",
|
||||||
"ext-exif": "Support for exif information from images",
|
"ext-exif": "Support for exif information from images",
|
||||||
"ext-fileinfo": "Improved mime type detection for files",
|
"ext-fileinfo": "Improved mime type detection for files",
|
||||||
"ext-imagick": "Improved thumbnail generation",
|
"ext-imagick": "Improved thumbnail generation",
|
||||||
"ext-intl": "Improved i18n number formatting",
|
"ext-intl": "Improved i18n number formatting",
|
||||||
"ext-memcached": "Support for the Memcached cache driver",
|
"ext-memcached": "Support for the Memcached cache driver",
|
||||||
|
"ext-pdo": "Support for using databases",
|
||||||
"ext-redis": "Support for the Redis cache driver",
|
"ext-redis": "Support for the Redis cache driver",
|
||||||
"ext-sodium": "Support for the crypto class and more robust session handling",
|
"ext-sodium": "Support for the crypto class and more robust session handling",
|
||||||
"ext-zip": "Support for ZIP archive file functions",
|
"ext-zip": "Support for ZIP archive file functions",
|
||||||
"ext-zlib": "Sanitization and validation for svgz files"
|
"ext-zlib": "Sanitization and validation for svgz files"
|
||||||
},
|
},
|
||||||
"type": "kirby-cms",
|
"type": "kirby-cms",
|
||||||
"extra": {
|
|
||||||
"unused": [
|
|
||||||
"symfony/polyfill-intl-idn"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"autoload": {
|
"autoload": {
|
||||||
"files": [
|
"files": [
|
||||||
"config/setup.php",
|
"config/setup.php",
|
||||||
@@ -369,7 +364,7 @@
|
|||||||
"type": "custom"
|
"type": "custom"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"time": "2025-09-16T13:06:53+00:00"
|
"time": "2025-12-16T09:23:12+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "getkirby/composer-installer",
|
"name": "getkirby/composer-installer",
|
||||||
@@ -420,32 +415,32 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "laminas/laminas-escaper",
|
"name": "laminas/laminas-escaper",
|
||||||
"version": "2.17.0",
|
"version": "2.18.0",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/laminas/laminas-escaper.git",
|
"url": "https://github.com/laminas/laminas-escaper.git",
|
||||||
"reference": "df1ef9503299a8e3920079a16263b578eaf7c3ba"
|
"reference": "06f211dfffff18d91844c1f55250d5d13c007e18"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/laminas/laminas-escaper/zipball/df1ef9503299a8e3920079a16263b578eaf7c3ba",
|
"url": "https://api.github.com/repos/laminas/laminas-escaper/zipball/06f211dfffff18d91844c1f55250d5d13c007e18",
|
||||||
"reference": "df1ef9503299a8e3920079a16263b578eaf7c3ba",
|
"reference": "06f211dfffff18d91844c1f55250d5d13c007e18",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
"ext-ctype": "*",
|
"ext-ctype": "*",
|
||||||
"ext-mbstring": "*",
|
"ext-mbstring": "*",
|
||||||
"php": "~8.1.0 || ~8.2.0 || ~8.3.0 || ~8.4.0"
|
"php": "~8.2.0 || ~8.3.0 || ~8.4.0 || ~8.5.0"
|
||||||
},
|
},
|
||||||
"conflict": {
|
"conflict": {
|
||||||
"zendframework/zend-escaper": "*"
|
"zendframework/zend-escaper": "*"
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"infection/infection": "^0.29.8",
|
"infection/infection": "^0.31.0",
|
||||||
"laminas/laminas-coding-standard": "~3.0.1",
|
"laminas/laminas-coding-standard": "~3.1.0",
|
||||||
"phpunit/phpunit": "^10.5.45",
|
"phpunit/phpunit": "^11.5.42",
|
||||||
"psalm/plugin-phpunit": "^0.19.2",
|
"psalm/plugin-phpunit": "^0.19.5",
|
||||||
"vimeo/psalm": "^6.6.2"
|
"vimeo/psalm": "^6.13.1"
|
||||||
},
|
},
|
||||||
"type": "library",
|
"type": "library",
|
||||||
"autoload": {
|
"autoload": {
|
||||||
@@ -477,7 +472,7 @@
|
|||||||
"type": "community_bridge"
|
"type": "community_bridge"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"time": "2025-05-06T19:29:36+00:00"
|
"time": "2025-10-14T18:31:13+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "league/color-extractor",
|
"name": "league/color-extractor",
|
||||||
@@ -596,16 +591,16 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "phpmailer/phpmailer",
|
"name": "phpmailer/phpmailer",
|
||||||
"version": "v6.10.0",
|
"version": "v7.0.1",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/PHPMailer/PHPMailer.git",
|
"url": "https://github.com/PHPMailer/PHPMailer.git",
|
||||||
"reference": "bf74d75a1fde6beaa34a0ddae2ec5fce0f72a144"
|
"reference": "360ae911ce62e25e11249f6140fa58939f556ebe"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/PHPMailer/PHPMailer/zipball/bf74d75a1fde6beaa34a0ddae2ec5fce0f72a144",
|
"url": "https://api.github.com/repos/PHPMailer/PHPMailer/zipball/360ae911ce62e25e11249f6140fa58939f556ebe",
|
||||||
"reference": "bf74d75a1fde6beaa34a0ddae2ec5fce0f72a144",
|
"reference": "360ae911ce62e25e11249f6140fa58939f556ebe",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
@@ -619,13 +614,14 @@
|
|||||||
"doctrine/annotations": "^1.2.6 || ^1.13.3",
|
"doctrine/annotations": "^1.2.6 || ^1.13.3",
|
||||||
"php-parallel-lint/php-console-highlighter": "^1.0.0",
|
"php-parallel-lint/php-console-highlighter": "^1.0.0",
|
||||||
"php-parallel-lint/php-parallel-lint": "^1.3.2",
|
"php-parallel-lint/php-parallel-lint": "^1.3.2",
|
||||||
"phpcompatibility/php-compatibility": "^9.3.5",
|
"phpcompatibility/php-compatibility": "^10.0.0@dev",
|
||||||
"roave/security-advisories": "dev-latest",
|
"squizlabs/php_codesniffer": "^3.13.5",
|
||||||
"squizlabs/php_codesniffer": "^3.7.2",
|
|
||||||
"yoast/phpunit-polyfills": "^1.0.4"
|
"yoast/phpunit-polyfills": "^1.0.4"
|
||||||
},
|
},
|
||||||
"suggest": {
|
"suggest": {
|
||||||
"decomplexity/SendOauth2": "Adapter for using XOAUTH2 authentication",
|
"decomplexity/SendOauth2": "Adapter for using XOAUTH2 authentication",
|
||||||
|
"directorytree/imapengine": "For uploading sent messages via IMAP, see gmail example",
|
||||||
|
"ext-imap": "Needed to support advanced email address parsing according to RFC822",
|
||||||
"ext-mbstring": "Needed to send email in multibyte encoding charset or decode encoded addresses",
|
"ext-mbstring": "Needed to send email in multibyte encoding charset or decode encoded addresses",
|
||||||
"ext-openssl": "Needed for secure SMTP sending and DKIM signing",
|
"ext-openssl": "Needed for secure SMTP sending and DKIM signing",
|
||||||
"greew/oauth2-azure-provider": "Needed for Microsoft Azure XOAUTH2 authentication",
|
"greew/oauth2-azure-provider": "Needed for Microsoft Azure XOAUTH2 authentication",
|
||||||
@@ -665,7 +661,7 @@
|
|||||||
"description": "PHPMailer is a full-featured email creation and transfer class for PHP",
|
"description": "PHPMailer is a full-featured email creation and transfer class for PHP",
|
||||||
"support": {
|
"support": {
|
||||||
"issues": "https://github.com/PHPMailer/PHPMailer/issues",
|
"issues": "https://github.com/PHPMailer/PHPMailer/issues",
|
||||||
"source": "https://github.com/PHPMailer/PHPMailer/tree/v6.10.0"
|
"source": "https://github.com/PHPMailer/PHPMailer/tree/v7.0.1"
|
||||||
},
|
},
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
@@ -673,7 +669,7 @@
|
|||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"time": "2025-04-24T15:19:31+00:00"
|
"time": "2025-11-25T07:18:09+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "psr/log",
|
"name": "psr/log",
|
||||||
@@ -1134,28 +1130,28 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/yaml",
|
"name": "symfony/yaml",
|
||||||
"version": "v7.3.3",
|
"version": "v7.4.1",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/symfony/yaml.git",
|
"url": "https://github.com/symfony/yaml.git",
|
||||||
"reference": "d4f4a66866fe2451f61296924767280ab5732d9d"
|
"reference": "24dd4de28d2e3988b311751ac49e684d783e2345"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/symfony/yaml/zipball/d4f4a66866fe2451f61296924767280ab5732d9d",
|
"url": "https://api.github.com/repos/symfony/yaml/zipball/24dd4de28d2e3988b311751ac49e684d783e2345",
|
||||||
"reference": "d4f4a66866fe2451f61296924767280ab5732d9d",
|
"reference": "24dd4de28d2e3988b311751ac49e684d783e2345",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
"php": ">=8.2",
|
"php": ">=8.2",
|
||||||
"symfony/deprecation-contracts": "^2.5|^3.0",
|
"symfony/deprecation-contracts": "^2.5|^3",
|
||||||
"symfony/polyfill-ctype": "^1.8"
|
"symfony/polyfill-ctype": "^1.8"
|
||||||
},
|
},
|
||||||
"conflict": {
|
"conflict": {
|
||||||
"symfony/console": "<6.4"
|
"symfony/console": "<6.4"
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"symfony/console": "^6.4|^7.0"
|
"symfony/console": "^6.4|^7.0|^8.0"
|
||||||
},
|
},
|
||||||
"bin": [
|
"bin": [
|
||||||
"Resources/bin/yaml-lint"
|
"Resources/bin/yaml-lint"
|
||||||
@@ -1186,7 +1182,7 @@
|
|||||||
"description": "Loads and dumps YAML files",
|
"description": "Loads and dumps YAML files",
|
||||||
"homepage": "https://symfony.com",
|
"homepage": "https://symfony.com",
|
||||||
"support": {
|
"support": {
|
||||||
"source": "https://github.com/symfony/yaml/tree/v7.3.3"
|
"source": "https://github.com/symfony/yaml/tree/v7.4.1"
|
||||||
},
|
},
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
@@ -1206,7 +1202,7 @@
|
|||||||
"type": "tidelift"
|
"type": "tidelift"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"time": "2025-08-27T11:34:33+00:00"
|
"time": "2025-12-04T18:11:45+00:00"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"packages-dev": [],
|
"packages-dev": [],
|
||||||
@@ -1219,5 +1215,5 @@
|
|||||||
"php": "~8.1.0 || ~8.2.0 || ~8.3.0 || ~8.4.0"
|
"php": "~8.1.0 || ~8.2.0 || ~8.3.0 || ~8.4.0"
|
||||||
},
|
},
|
||||||
"platform-dev": {},
|
"platform-dev": {},
|
||||||
"plugin-api-version": "2.6.0"
|
"plugin-api-version": "2.9.0"
|
||||||
}
|
}
|
||||||
|
|||||||
|
After Width: | Height: | Size: 830 KiB |
@@ -0,0 +1,5 @@
|
|||||||
|
Uuid: bwjwjg6rtabbwkrt
|
||||||
|
|
||||||
|
----
|
||||||
|
|
||||||
|
Template: blocks/image
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
[Event "A-Klasse 2025/2026 - TSV Bindlach Aktionär 3"]
|
||||||
|
[Site "Bindlach"]
|
||||||
|
[Date "2025.11.30"]
|
||||||
|
[Round "4"]
|
||||||
|
[White "Feigel, Tobias"]
|
||||||
|
[Black "Dederer, Alexej"]
|
||||||
|
[Result "1-0"]
|
||||||
|
[WhiteElo "1358"]
|
||||||
|
[BlackElo "1487"]
|
||||||
|
[EventDate "2025.11.30"]
|
||||||
|
[ECO "B01"]
|
||||||
|
[PlyCount "57"]
|
||||||
|
|
||||||
|
1.e4 d5 2.exd5 Qxd5 3.Nc3 Qe6+ $146 4.Be2 Qg6 5.g3 $2 c6 6.d4 Bf5 7.Bd3 $2 Bxd3 8.cxd3 e6 9.Nf3 Qh5 $1 10.Qe2 Nf6 11.a3 Nbd7 12.Bf4 Nd5 13.Nxd5 Qxd5 14.O-O Nf6 15.Rfe1 Rd8 16.Qd1 Be7 17.Rc1 Qh5 $2 18.Re5 Qh3 19.Ng5 $1 Qg4 $4 20.f3 Qh5 21.Nxe6 $1 Qh3 22.Nxd8 Kxd8 23.Qb3 Qd7 24.Rce1 Qxd4+ $2 25.Kg2 Bc5 26.Rxc5 $1 Qxc5 27.Qxb7 Qa5 28.Re7 Qb6 29.Bc7+ 1-0
|
||||||
|
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
Uuid: zrylk3mmhvof3dy3
|
||||||
@@ -0,0 +1,80 @@
|
|||||||
|
Title: 20251201-Erfolg-in-Bindlach
|
||||||
|
|
||||||
|
----
|
||||||
|
|
||||||
|
Blocks:
|
||||||
|
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"content": {
|
||||||
|
"text": "<p>Nach drei Niederlagen in Folge fuhren wir am 30.11.2025 mit geringen Erwartungen zur 3.Mannschaft des TSV Bindlach.</p><p>An den Brettern 2 <strong>(Alexander Döge</strong>), 6 (<strong>Rainald Müller</strong>) und 8 (<strong>Reinhardt Schmalz</strong>) waren schnell Remisen vereinbart. Aber am Spitzenbrett konnte <strong>Dominik Döge</strong> in einem Springerendspiel mit Minusbauern das Unentschieden nicht realisieren und <strong>Fred Zimmerbauer</strong> am vierten Brett verlor nach einem missglückten Springerzug Material und schließlich die Partie. Die Bindlacher wähnten sich bei diesem Zwischenstand mit 3,5 zu 1,5 schon auf der Siegerstraße. Alles deutete schon auf eine erneute Niederlage der Spielgemeinschaft SF Bad Steben/TV Reinersreuth hin. </p><p>Aber die drei letzten Partien verliefen hochspannend mit einem glücklichen Finale für die Kurstädter. <strong>Tobias Feigel</strong> konnte mit einem Figurenopfer die schwache Königsstellung seines Gegners aufreißen und auf der 7. Reihe mit konzentriertem Schwerfigurenangriff dann mattsetzen. <strong>Klaus Frommelt</strong> übte mit den weißen Steinen einen großen Druck auf die gegnerische Stellung aus, opferte seine Qualität gegen eine Fünfbauernphalanx am Damenflügel, welche beim Vorrücken trotz großen Widerstandes seines Gegenübers nicht mehr aufzuhalten war. Jetzt lag es an <strong>Dominik Kadlic</strong> den nötigen Gewinnpunkt zum Mannschaftssieg einzufahren. In einer turbulenten Auseinandersetzung mit beiderseitigen Gewinnchancen konnte er nach Abtausch aller Schwerfiguren solide in ein gewonnenes Bauernendspiel abwickeln.</p><p>Ein überraschender Sieg gegen die favorisierten Bindlacher, welchen man eigentlich nicht erwarten konnte. Dies gibt Hoffnung für das neue Jahr, wenn man zum Heimspiel am 11.01.2026 die sehr stark besetzte 2.Vertretung des SC Bayreuth empfängt.</p>"
|
||||||
|
},
|
||||||
|
"id": "dea24cf8-2397-4bf7-83da-f1baab4a3ca8",
|
||||||
|
"isHidden": false,
|
||||||
|
"type": "text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"content": {
|
||||||
|
"fen": "3k3r/pp3ppp/2p2n2/2b1R3/3q1B2/PQ1P1PP1/1P4KP/4R3 w - - 2 26"
|
||||||
|
},
|
||||||
|
"id": "f09ceaf2-6442-4b7f-8846-2df40fe0f6d0",
|
||||||
|
"isHidden": false,
|
||||||
|
"type": "fen"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"content": {
|
||||||
|
"text": "<p>Die Stellung stammt aus der Partie an Brett 7 von <strong>Tobias Feige</strong>l gegen <strong>Alexej Dederer</strong>, vor dem 26. Zug von Weiß. Tobias opferte mit 26. Txc5! seine Qualität zurück um dann nach 26. ... Dxc5 mit 27. Dxb7 gefolgt von Te7 und schließlich Lc7 einen gewinnbringenden Mattangriff zu starten, der nur durch Damenverlust aufgehalten werden konnte:</p>"
|
||||||
|
},
|
||||||
|
"id": "36746cbf-384a-4f6c-be7c-ed0233464d22",
|
||||||
|
"isHidden": false,
|
||||||
|
"type": "text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"content": {
|
||||||
|
"fen": "3k3r/pQB1Rppp/1qp2n2/8/8/P2P1PP1/1P4KP/8 b - - 4 29"
|
||||||
|
},
|
||||||
|
"id": "f7e62a19-884e-472f-8f11-bb0e9fdaf9a4",
|
||||||
|
"isHidden": false,
|
||||||
|
"type": "fen"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"content": {
|
||||||
|
"text": "<p>Ein schönes Ende der Partie, die Alexej an der Stelle sofort aufgab!</p>"
|
||||||
|
},
|
||||||
|
"id": "7601756e-536a-4ed6-b299-8506ec9d1ae9",
|
||||||
|
"isHidden": false,
|
||||||
|
"type": "text"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
----
|
||||||
|
|
||||||
|
Image: - file://bwjwjg6rtabbwkrt
|
||||||
|
|
||||||
|
----
|
||||||
|
|
||||||
|
Headline: Erfolg gegen Bindlach!
|
||||||
|
|
||||||
|
----
|
||||||
|
|
||||||
|
Subheadline: Der erste Sieg der Saison ist eingefahren!
|
||||||
|
|
||||||
|
----
|
||||||
|
|
||||||
|
Summary: Nach drei Niederlagen in Folge fuhren wir am 30.11.2025 mit geringen Erwartungen zur 3.Mannschaft des TSV Bindlach - zu Unrecht, wie sich herausstellen sollte!
|
||||||
|
|
||||||
|
----
|
||||||
|
|
||||||
|
Tags: Spielbericht
|
||||||
|
|
||||||
|
----
|
||||||
|
|
||||||
|
Author: - user://P4aiY3HI
|
||||||
|
|
||||||
|
----
|
||||||
|
|
||||||
|
Date: 2025-12-01
|
||||||
|
|
||||||
|
----
|
||||||
|
|
||||||
|
Uuid: gqvlabgfoko535r9
|
||||||
|
After Width: | Height: | Size: 495 KiB |
@@ -0,0 +1 @@
|
|||||||
|
Uuid: dgspiwstnipmybks
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
Title: 20251020-Saisonauftakt
|
||||||
|
|
||||||
|
----
|
||||||
|
|
||||||
|
Blocks:
|
||||||
|
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"content": {
|
||||||
|
"text": "<p>Der Start in die neue Saison verläuft für die SG SF Bad Steben/TV Reinersreuth äußerst unglücklich.</p><p>Im ersten Heimspiel setzte es gegen die SG Helmbrechts/Presseck eine 3,5 : 4,5 Niederlage. Dabei gelang es uns nicht, ein vollständiges Team mit acht Spielern zu gewährleisten. Nur sieben Akteure zum Saisonauftakt bedeuteten schon ein Handikap.</p><p>Am 19.10.2025 mussten wir zur ersten Auswärtsbegegnung beim vorläufigen Spitzenreiter SC Pegnitz antreten und es gab ein deutliches 2 : 6. Trotz großer Bemühungen unseres Spielleiters konnte er nur sechs Schachfreunde gegen die Heimmannschaft gewinnen. Mit einem anfänglichen 0 : 2-Rückstand ist es dann fast aussichtslos, auf einen Mannschafts-punktgewinn zu schielen. Nur Dominik Kadlic konnte seine Partie gewinnen, während Jürgen Franz und Rainald Müller ihre Spiele remisierten. Besonders hervorzuheben ist dabei die Punkteteilung unseres Spielleiters (DWZ: 1668), welcher am Spitzenbrett Markus Müller (DWZ: 1988) erfolgreich Paroli bieten konnte.</p><p>Nach den zwei Spieltagen stecken wir schon mitten im Abstiegskampf. Am 09.11.25 gilt es dann in der Heimbegegnung gegen den Aufsteiger ATSV Oberkotzau 2 nicht den Anschluss an das untere Mittelfeld in der Tabelle zu verlieren und endlich mal mit „voller Kapelle“ anzutreten.</p>"
|
||||||
|
},
|
||||||
|
"id": "e9def111-1209-4d1f-be78-985818f8c593",
|
||||||
|
"isHidden": false,
|
||||||
|
"type": "text"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
----
|
||||||
|
|
||||||
|
Image: - file://dgspiwstnipmybks
|
||||||
|
|
||||||
|
----
|
||||||
|
|
||||||
|
Headline: Holpriger Saisonauftakt
|
||||||
|
|
||||||
|
----
|
||||||
|
|
||||||
|
Subheadline: Es läuft nicht rund!
|
||||||
|
|
||||||
|
----
|
||||||
|
|
||||||
|
Summary: Der Start in die neue Saison verläuft für die SG SF Bad Steben/TV Reinersreuth äußerst unglücklich.
|
||||||
|
|
||||||
|
----
|
||||||
|
|
||||||
|
Tags: Spielbericht
|
||||||
|
|
||||||
|
----
|
||||||
|
|
||||||
|
Author: - user://P4aiY3HI
|
||||||
|
|
||||||
|
----
|
||||||
|
|
||||||
|
Date: 2025-10-19
|
||||||
|
|
||||||
|
----
|
||||||
|
|
||||||
|
Uuid: 8qlli8wrp1tbkgap
|
||||||
@@ -0,0 +1,56 @@
|
|||||||
|
Title: 20250922-Engagement
|
||||||
|
|
||||||
|
----
|
||||||
|
|
||||||
|
Blocks:
|
||||||
|
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"content": {
|
||||||
|
"text": "<p>Neben dem Engagement im eigenen Verein wurden bei der Versammlung des Schachkreis Hof-Bayreuth-Kulmbach am vergangenen Freitag zwei SF in die Ämter des Kreisjugendleiter und seines Stellvertreters gewählt.</p>"
|
||||||
|
},
|
||||||
|
"id": "c9741947-2e75-49e6-a4c5-47e35f183528",
|
||||||
|
"isHidden": false,
|
||||||
|
"type": "text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"content": {
|
||||||
|
"text": "**Tobias Feigel** (2. von links im Bild) amtierender Jugendleiter der SF und seit 2017 auch Kreisjugendleiter räumte seinen Posten auf Kreisebene und trat in die zweite Reihe zurück, um Platz zu machen für **Alexander Döge** (2. von rechts im Bild), der Kassenprüfer der SF ist und nun neuer Kreisjugendleiter. Tobias wird Alexander als sein Stellvertreter die nächsten zwei Jahre unterstützen und sich dann ganz aus der Vorstandschaft des Kreises verabschieden. Bei der nächsten Wahl soll dann Alexanders Bruder **Dominik Döge** in den Vorstand des Kreises an die Stelle von Tobias treten.\n\nEs seien mir dazu ein paar persönliche Worte erlaubt: In wenigen Jahren werde ich schachlich gesehen als Senior gewertet und da wird es höchste Zeit, den Posten in jüngere Hände abzugeben! Ich bin mir sicher, dass mit Alexander und Dominik zwei hervorragende Kandidaten für den Posten gefunden wurden und ich werde beide während der Übergangszeit unterstützen!"
|
||||||
|
},
|
||||||
|
"id": "6a2ee75a-db20-4861-80ee-db49f191c16e",
|
||||||
|
"isHidden": false,
|
||||||
|
"type": "markdown"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
----
|
||||||
|
|
||||||
|
Image: - file://ioxhz3ujwtl6un8k
|
||||||
|
|
||||||
|
----
|
||||||
|
|
||||||
|
Headline: SF engagieren sich auf Kreisebene
|
||||||
|
|
||||||
|
----
|
||||||
|
|
||||||
|
Subheadline: Zwei SF im Vorstand des Schachkreises
|
||||||
|
|
||||||
|
----
|
||||||
|
|
||||||
|
Summary: Neben dem Engagement im eigenen Verein wurden bei der Versammlung des Schachkreis Hof-Bayreuth-Kulmbach am vergangenen Freitag zwei SF in die Ämter des Kreisjugendleiter und seines Stellvertreters gewählt.
|
||||||
|
|
||||||
|
----
|
||||||
|
|
||||||
|
Tags: Vereinsleben
|
||||||
|
|
||||||
|
----
|
||||||
|
|
||||||
|
Author: - user://KOY9VcGi
|
||||||
|
|
||||||
|
----
|
||||||
|
|
||||||
|
Date: 2025-09-22
|
||||||
|
|
||||||
|
----
|
||||||
|
|
||||||
|
Uuid: kbtd9a8so9mbkvti
|
||||||
|
After Width: | Height: | Size: 509 KiB |
@@ -0,0 +1 @@
|
|||||||
|
Uuid: ioxhz3ujwtl6un8k
|
||||||
@@ -37,7 +37,7 @@ Tags: Spielbericht, Turnierbericht
|
|||||||
|
|
||||||
----
|
----
|
||||||
|
|
||||||
Author: - user://myU6sssZ
|
Author: - user://KOY9VcGi
|
||||||
|
|
||||||
----
|
----
|
||||||
|
|
||||||
|
Before Width: | Height: | Size: 69 KiB After Width: | Height: | Size: 69 KiB |
|
Before Width: | Height: | Size: 546 KiB After Width: | Height: | Size: 546 KiB |
@@ -1,23 +1,26 @@
|
|||||||
User-agent: *
|
User-agent: *
|
||||||
Allow: /
|
Allow: /
|
||||||
|
Crawl-delay: 1
|
||||||
|
|
||||||
# Spezielle Erlaubnis für DSGVO/Legal Scanner
|
# Spezielle Erlaubnis für DSGVO/Legal Scanner
|
||||||
User-agent: LegalCockpitBot
|
User-agent: LegalCockpitBot
|
||||||
Allow: /
|
Allow: /
|
||||||
|
Crawl-delay: 0
|
||||||
|
|
||||||
User-agent: CookieBot
|
User-agent: cockpit.legal
|
||||||
|
Allow: /
|
||||||
|
Crawl-delay: 0
|
||||||
|
|
||||||
|
User-agent: Mozilla*
|
||||||
Allow: /
|
Allow: /
|
||||||
|
|
||||||
User-agent: DataProtectionBot
|
# Sitemap
|
||||||
Allow: /
|
Sitemap: https://www.schachfreunde-badsteben.de/sitemap.xml
|
||||||
|
|
||||||
User-agent: GDPRBot
|
|
||||||
Allow: /
|
|
||||||
|
|
||||||
# Sitemap (falls vorhanden)
|
|
||||||
# Sitemap: https://www.schachfreunde-badsteben.de/sitemap.xml
|
|
||||||
|
|
||||||
# Wichtige Seiten explizit erlauben
|
# Wichtige Seiten explizit erlauben
|
||||||
|
Allow: /
|
||||||
Allow: /datenschutz
|
Allow: /datenschutz
|
||||||
Allow: /impressum
|
Allow: /impressum
|
||||||
Allow: /kontakt
|
Allow: /kontakt
|
||||||
|
Allow: /home
|
||||||
|
Allow: /news
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
<?php
|
<?php
|
||||||
// URL der öffentlichen ICS-Datei
|
// URL der öffentlichen ICS-Datei
|
||||||
define(
|
define(
|
||||||
@@ -83,13 +82,10 @@ function format_ics_date_with_timezone($date, $timezone = null)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ICS-Datei laden
|
// Cache für 24 Stunden (in Minuten)
|
||||||
$ics = @file_get_contents(CAL_URL);
|
$cacheDuration = 24 * 60;
|
||||||
if (!$ics) {
|
$cacheId = 'google_calendar_events';
|
||||||
echo '<div class="text-red-600">Kalender konnte nicht geladen werden.</div>';
|
$cache = kirby()->cache('pages');
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Termine parsen
|
// Termine parsen
|
||||||
function parse_ics($ics)
|
function parse_ics($ics)
|
||||||
@@ -134,9 +130,26 @@ function parse_ics($ics)
|
|||||||
return $events;
|
return $events;
|
||||||
}
|
}
|
||||||
|
|
||||||
$events = parse_ics($ics);
|
return function () use ($cache, $cacheId, $cacheDuration) {
|
||||||
|
// Versuche Daten aus dem Cache zu laden
|
||||||
|
$events = $cache->get($cacheId);
|
||||||
|
|
||||||
|
if ($events === null) {
|
||||||
|
// Wenn nicht im Cache, neu laden
|
||||||
|
$ics = @file_get_contents(CAL_URL);
|
||||||
|
|
||||||
|
if (!$ics) {
|
||||||
|
// Fehler beim Laden (z.B. 429 Error)
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Termine parsen
|
||||||
|
$events = parse_ics($ics);
|
||||||
|
|
||||||
|
// In Cache speichern
|
||||||
|
$cache->set($cacheId, $events, $cacheDuration);
|
||||||
|
}
|
||||||
|
|
||||||
return function () use ($events) {
|
|
||||||
return $events;
|
return $events;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1,13 +1,23 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
return [
|
return [
|
||||||
'debug' => true,
|
'debug' => false,
|
||||||
|
|
||||||
|
// Home-Seite explizit definieren
|
||||||
|
'home' => 'home',
|
||||||
|
|
||||||
'panel' => [
|
'panel' => [
|
||||||
'vue' => [
|
'vue' => [
|
||||||
'compiler' => false
|
'compiler' => false
|
||||||
]
|
]
|
||||||
],
|
],
|
||||||
'routes' => [
|
'routes' => [
|
||||||
|
[
|
||||||
|
'pattern' => '/',
|
||||||
|
'action' => function() {
|
||||||
|
return site()->homePage();
|
||||||
|
}
|
||||||
|
],
|
||||||
[
|
[
|
||||||
'pattern' => 'sitemap.xml',
|
'pattern' => 'sitemap.xml',
|
||||||
'action' => function() {
|
'action' => function() {
|
||||||
@@ -29,5 +39,5 @@ return [
|
|||||||
return go('sitemap.xml', 301);
|
return go('sitemap.xml', 301);
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
],
|
],
|
||||||
];
|
];
|
||||||
|
|||||||
@@ -1,33 +1,40 @@
|
|||||||
<?php
|
<?php
|
||||||
$events = collection('termine');
|
$events = collection('termine');
|
||||||
|
|
||||||
|
if ($events === null): ?>
|
||||||
|
<div class="container mx-auto py-8">
|
||||||
|
<h2>Bevorstehende Termine</h2>
|
||||||
|
<div class="text-red-600">Die Termine können gerade nicht geladen werden.</div>
|
||||||
|
</div>
|
||||||
|
<?php return; endif;
|
||||||
|
|
||||||
// Aktuelles Datum - PHP 8.3 kompatibel
|
// Aktuelles Datum - PHP 8.3 kompatibel
|
||||||
$today = (new DateTime('now'))->format('Ymd');
|
$today = (new DateTime('now'))->format('Ymd');
|
||||||
|
|
||||||
// Nur zukünftige Termine anzeigen
|
// Nur zukünftige Termine anzeigen
|
||||||
$future_events = array_filter($events, function ($event) use ($today) {
|
$future_events = array_filter($events, function ($event) use ($today) {
|
||||||
return isset($event['DTSTART']) && $event['DTSTART'] >= $today;
|
return isset($event['DTSTART']) && $event['DTSTART'] >= $today;
|
||||||
});
|
});
|
||||||
|
|
||||||
// Termine nach DTSTART in aufsteigender Reihenfolge sortieren
|
// Termine nach DTSTART in aufsteigender Reihenfolge sortieren
|
||||||
usort($future_events, function ($a, $b) {
|
usort($future_events, function ($a, $b) {
|
||||||
return $a['DTSTART'] <=> $b['DTSTART'];
|
return $a['DTSTART'] <=> $b['DTSTART'];
|
||||||
});
|
});
|
||||||
|
|
||||||
// --- Deutsche Monatsnamen ---
|
// --- Deutsche Monatsnamen ---
|
||||||
$de_months = [
|
$de_months = [
|
||||||
'01' => 'Jan',
|
'01' => 'Jan',
|
||||||
'02' => 'Feb',
|
'02' => 'Feb',
|
||||||
'03' => 'Mrz',
|
'03' => 'Mrz',
|
||||||
'04' => 'Apr',
|
'04' => 'Apr',
|
||||||
'05' => 'Mai',
|
'05' => 'Mai',
|
||||||
'06' => 'Jun',
|
'06' => 'Jun',
|
||||||
'07' => 'Jul',
|
'07' => 'Jul',
|
||||||
'08' => 'Aug',
|
'08' => 'Aug',
|
||||||
'09' => 'Sep',
|
'09' => 'Sep',
|
||||||
'10' => 'Okt',
|
'10' => 'Okt',
|
||||||
'11' => 'Nov',
|
'11' => 'Nov',
|
||||||
'12' => 'Dez',
|
'12' => 'Dez',
|
||||||
];
|
];
|
||||||
?>
|
?>
|
||||||
|
|
||||||
@@ -35,8 +42,12 @@ $de_months = [
|
|||||||
<h2>Bevorstehende Termine</h2>
|
<h2>Bevorstehende Termine</h2>
|
||||||
|
|
||||||
<div class="relative flex items-center justify-center">
|
<div class="relative flex items-center justify-center">
|
||||||
<button id="scroll-left" class="flex-shrink-0 bg-white p-3 rounded-full shadow-lg hover:bg-gray-100 focus:outline-none focus:ring-2 focus:ring-blue-500 z-10 hidden md:block mr-4">
|
<button id="scroll-left"
|
||||||
<svg class="w-6 h-6 text-gray-700" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 19l-7-7 7-7"></path></svg>
|
class="flex-shrink-0 bg-white p-3 rounded-full shadow-lg hover:bg-gray-100 focus:outline-none focus:ring-2 focus:ring-blue-500 z-10 hidden md:block mr-4">
|
||||||
|
<svg class="w-6 h-6 text-gray-700" fill="none" stroke="currentColor" viewBox="0 0 24 24"
|
||||||
|
xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 19l-7-7 7-7"></path>
|
||||||
|
</svg>
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<div id="termine-wrapper" class="relative w-full max-w-7xl overflow-hidden">
|
<div id="termine-wrapper" class="relative w-full max-w-7xl overflow-hidden">
|
||||||
@@ -49,18 +60,18 @@ $de_months = [
|
|||||||
$location = $event['LOCATION'] ?? '';
|
$location = $event['LOCATION'] ?? '';
|
||||||
$desc = $event['DESCRIPTION'] ?? '';
|
$desc = $event['DESCRIPTION'] ?? '';
|
||||||
$timezone = $event['DTSTART_TZID'] ?? null;
|
$timezone = $event['DTSTART_TZID'] ?? null;
|
||||||
|
|
||||||
// Sichere Funktionsaufrufe mit Null-Checks
|
// Sichere Funktionsaufrufe mit Null-Checks
|
||||||
$date_info = function_exists('format_ics_date_with_timezone')
|
$date_info = function_exists('format_ics_date_with_timezone')
|
||||||
? format_ics_date_with_timezone($start, $timezone)
|
? format_ics_date_with_timezone($start, $timezone)
|
||||||
: ['display' => '', 'has_time' => false, 'iso' => ''];
|
: ['display' => '', 'has_time' => false, 'iso' => ''];
|
||||||
|
|
||||||
$date = $date_info['display'] ?? '';
|
$date = $date_info['display'] ?? '';
|
||||||
$time = ($date_info['has_time'] ?? false) ? substr($date, 11) : 'ganztägig';
|
$time = ($date_info['has_time'] ?? false) ? substr($date, 11) : 'ganztägig';
|
||||||
$day = substr($date, 0, 2);
|
$day = substr($date, 0, 2);
|
||||||
$month = substr($date, 3, 2);
|
$month = substr($date, 3, 2);
|
||||||
$iso_date = $date_info['iso'] ?? '';
|
$iso_date = $date_info['iso'] ?? '';
|
||||||
|
|
||||||
// Sichere Array-Zugriffe
|
// Sichere Array-Zugriffe
|
||||||
$month_name = $de_months[$month] ?? 'Unbek';
|
$month_name = $de_months[$month] ?? 'Unbek';
|
||||||
$event_summary = htmlspecialchars($summary, ENT_QUOTES, 'UTF-8');
|
$event_summary = htmlspecialchars($summary, ENT_QUOTES, 'UTF-8');
|
||||||
@@ -69,57 +80,64 @@ $de_months = [
|
|||||||
$safe_time = htmlspecialchars($time, ENT_QUOTES, 'UTF-8');
|
$safe_time = htmlspecialchars($time, ENT_QUOTES, 'UTF-8');
|
||||||
?>
|
?>
|
||||||
|
|
||||||
<div class="termine-card flex-none w-full md:w-1/2 bg-gradient-to-br from-blue-50 to-blue-100 rounded-2xl transform hover:scale-102 transition-all duration-300 ease-in-out border border-blue-200">
|
<div
|
||||||
<!-- Inhalt der ersten Karte bleibt unverändert -->
|
class="termine-card flex-none w-full md:w-1/2 bg-gradient-to-br from-blue-50 to-blue-100 rounded-2xl transform hover:scale-102 transition-all duration-300 ease-in-out border border-blue-200">
|
||||||
<div class="p-6 flex flex-col h-full">
|
<!-- Inhalt der ersten Karte bleibt unverändert -->
|
||||||
<div class="flex items-top mb-5">
|
<div class="p-6 flex flex-col h-full">
|
||||||
<div class="relative flex-shrink-0 bg-white rounded-lg shadow-md overflow-hidden w-16 h-16 flex flex-col border border-blue-200">
|
<div class="flex items-top mb-5">
|
||||||
<!-- Kopfzeile des Kalenders mit Monat -->
|
<div
|
||||||
<div class="bg-blue-600 text-white text-xs font-semibold py-1 text-center uppercase">
|
class="relative flex-shrink-0 bg-white rounded-lg shadow-md overflow-hidden w-16 h-16 flex flex-col border border-blue-200">
|
||||||
<span data-month><?= $month_name ?></span>
|
<!-- Kopfzeile des Kalenders mit Monat -->
|
||||||
</div>
|
<div class="bg-blue-600 text-white text-xs font-semibold py-1 text-center uppercase">
|
||||||
|
<span data-month><?= $month_name ?></span>
|
||||||
|
</div>
|
||||||
|
|
||||||
<!-- Datumsanzeige -->
|
<!-- Datumsanzeige -->
|
||||||
<div class="flex-grow flex items-center justify-center">
|
<div class="flex-grow flex items-center justify-center">
|
||||||
<div class="text-3xl font-bold text-sf_grau-800" data-day><?= $safe_day ?></div>
|
<div class="text-3xl font-bold text-sf_grau-800" data-day><?= $safe_day ?></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Dekorative Elemente - kleine Punkte für Kalendertage -->
|
<!-- Dekorative Elemente - kleine Punkte für Kalendertage -->
|
||||||
<div class="absolute bottom-1 left-0 right-0 flex justify-center space-x-0.5 px-1">
|
<div class="absolute bottom-1 left-0 right-0 flex justify-center space-x-0.5 px-1">
|
||||||
<div class="w-1 h-1 rounded-full bg-sf_blau-200"></div>
|
<div class="w-1 h-1 rounded-full bg-sf_blau-200"></div>
|
||||||
<div class="w-1 h-1 rounded-full bg-sf_blau-300"></div>
|
<div class="w-1 h-1 rounded-full bg-sf_blau-300"></div>
|
||||||
<div class="w-1 h-1 rounded-full bg-sf_blau-400"></div>
|
<div class="w-1 h-1 rounded-full bg-sf_blau-400"></div>
|
||||||
<div class="w-1 h-1 rounded-full bg-sf_blau-500"></div>
|
<div class="w-1 h-1 rounded-full bg-sf_blau-500"></div>
|
||||||
<div class="w-1 h-1 rounded-full bg-sf_blau-400"></div>
|
<div class="w-1 h-1 rounded-full bg-sf_blau-400"></div>
|
||||||
<div class="w-1 h-1 rounded-full bg-sf_blau-300"></div>
|
<div class="w-1 h-1 rounded-full bg-sf_blau-300"></div>
|
||||||
<div class="w-1 h-1 rounded-full bg-sf_blau-200"></div>
|
<div class="w-1 h-1 rounded-full bg-sf_blau-200"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="ml-5 flex-grow">
|
||||||
|
<p class="text-xl font-medium text-sf_grau-900"><?= $event_summary ?></p>
|
||||||
|
<p class="text-sf_blau-700 text-lg font-medium mt-1">
|
||||||
|
<?php if ($date_info['has_time'] ?? false): ?>
|
||||||
|
ab <span class="local-time"
|
||||||
|
data-iso-date="<?= $safe_iso_date ?>"><?= $safe_time ?></span> Uhr
|
||||||
|
<?php else: ?>
|
||||||
|
ganztägig
|
||||||
|
<?php endif; ?>
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
<div class="ml-5 flex-grow">
|
|
||||||
<p class="text-xl font-medium text-sf_grau-900"><?= $event_summary ?></p>
|
|
||||||
<p class="text-sf_blau-700 text-lg font-medium mt-1">
|
|
||||||
<?php if ($date_info['has_time'] ?? false): ?>
|
|
||||||
ab <span class="local-time" data-iso-date="<?= $safe_iso_date ?>"><?= $safe_time ?></span> Uhr
|
|
||||||
<?php else: ?>
|
|
||||||
ganztägig
|
|
||||||
<?php endif; ?>
|
|
||||||
</p>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
<?php endforeach; ?>
|
<?php endforeach; ?>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<button id="scroll-right" class="flex-shrink-0 bg-white p-3 rounded-full shadow-lg hover:bg-gray-100 focus:outline-none focus:ring-2 focus:ring-blue-500 z-10 hidden md:block ml-4">
|
<button id="scroll-right"
|
||||||
<svg class="w-6 h-6 text-gray-700" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7"></path></svg>
|
class="flex-shrink-0 bg-white p-3 rounded-full shadow-lg hover:bg-gray-100 focus:outline-none focus:ring-2 focus:ring-blue-500 z-10 hidden md:block ml-4">
|
||||||
|
<svg class="w-6 h-6 text-gray-700" fill="none" stroke="currentColor" viewBox="0 0 24 24"
|
||||||
|
xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7"></path>
|
||||||
|
</svg>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
document.addEventListener('DOMContentLoaded', function() {
|
document.addEventListener('DOMContentLoaded', function () {
|
||||||
const termineWrapper = document.getElementById('termine-wrapper');
|
const termineWrapper = document.getElementById('termine-wrapper');
|
||||||
const termineContainer = document.getElementById('termine-container');
|
const termineContainer = document.getElementById('termine-container');
|
||||||
const scrollLeftBtn = document.getElementById('scroll-left');
|
const scrollLeftBtn = document.getElementById('scroll-left');
|
||||||
@@ -143,7 +161,7 @@ $de_months = [
|
|||||||
scrollLeftBtn.classList.remove('opacity-50', 'cursor-not-allowed');
|
scrollLeftBtn.classList.remove('opacity-50', 'cursor-not-allowed');
|
||||||
scrollLeftBtn.classList.add('hover:bg-gray-100');
|
scrollLeftBtn.classList.add('hover:bg-gray-100');
|
||||||
}
|
}
|
||||||
|
|
||||||
// Rechter Pfeil deaktivieren, wenn es keine weiteren Termine gibt
|
// Rechter Pfeil deaktivieren, wenn es keine weiteren Termine gibt
|
||||||
if (currentPosition >= maxPosition) {
|
if (currentPosition >= maxPosition) {
|
||||||
scrollRightBtn.disabled = true;
|
scrollRightBtn.disabled = true;
|
||||||
@@ -200,23 +218,23 @@ $de_months = [
|
|||||||
// Erstelle ein Date-Objekt aus der ISO-Date
|
// Erstelle ein Date-Objekt aus der ISO-Date
|
||||||
// JavaScript erkennt automatisch UTC-Zeiten (mit Z oder +00:00)
|
// JavaScript erkennt automatisch UTC-Zeiten (mit Z oder +00:00)
|
||||||
const date = new Date(isoDate);
|
const date = new Date(isoDate);
|
||||||
|
|
||||||
// Prüfe ob das Datum gültig ist
|
// Prüfe ob das Datum gültig ist
|
||||||
if (isNaN(date.getTime())) {
|
if (isNaN(date.getTime())) {
|
||||||
console.warn('Ungültiges Datum:', isoDate);
|
console.warn('Ungültiges Datum:', isoDate);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Formatiere die Zeit in der lokalen Zeitzone des Browsers
|
// Formatiere die Zeit in der lokalen Zeitzone des Browsers
|
||||||
const localTime = date.toLocaleTimeString('de-DE', {
|
const localTime = date.toLocaleTimeString('de-DE', {
|
||||||
hour: '2-digit',
|
hour: '2-digit',
|
||||||
minute: '2-digit',
|
minute: '2-digit',
|
||||||
hour12: false
|
hour12: false
|
||||||
});
|
});
|
||||||
|
|
||||||
// Aktualisiere den Text
|
// Aktualisiere den Text
|
||||||
element.textContent = localTime;
|
element.textContent = localTime;
|
||||||
|
|
||||||
// Debug-Information (kann später entfernt werden)
|
// Debug-Information (kann später entfernt werden)
|
||||||
console.log('Konvertiert:', isoDate, '->', localTime, 'in Zeitzone:', Intl.DateTimeFormat().resolvedOptions().timeZone);
|
console.log('Konvertiert:', isoDate, '->', localTime, 'in Zeitzone:', Intl.DateTimeFormat().resolvedOptions().timeZone);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@@ -250,32 +268,41 @@ $de_months = [
|
|||||||
<style>
|
<style>
|
||||||
/* Versteckt die Scrollbar vollständig, behält aber die Scrollfunktionalität */
|
/* Versteckt die Scrollbar vollständig, behält aber die Scrollfunktionalität */
|
||||||
#termine-container {
|
#termine-container {
|
||||||
-ms-overflow-style: none; /* IE and Edge */
|
-ms-overflow-style: none;
|
||||||
scrollbar-width: none; /* Firefox */
|
/* IE and Edge */
|
||||||
|
scrollbar-width: none;
|
||||||
|
/* Firefox */
|
||||||
overflow-x: visible;
|
overflow-x: visible;
|
||||||
}
|
}
|
||||||
|
|
||||||
#termine-container::-webkit-scrollbar {
|
#termine-container::-webkit-scrollbar {
|
||||||
display: none; /* Chrome, Safari, Opera */
|
display: none;
|
||||||
|
/* Chrome, Safari, Opera */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Gleiche Kartenbreiten sicherstellen */
|
/* Gleiche Kartenbreiten sicherstellen */
|
||||||
@media (min-width: 1280px) {
|
@media (min-width: 1280px) {
|
||||||
.termine-card {
|
.termine-card {
|
||||||
width: 100%; /* 100% minus 2 Gaps (2 * 24px) geteilt durch 3 */
|
width: 100%;
|
||||||
|
/* 100% minus 2 Gaps (2 * 24px) geteilt durch 3 */
|
||||||
}
|
}
|
||||||
|
|
||||||
#termine-container {
|
#termine-container {
|
||||||
space-x-0; /* Kein Abstand zwischen Karten nötig */
|
space-x-0;
|
||||||
|
/* Kein Abstand zwischen Karten nötig */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Auf mobilen Geräten eine Karte anzeigen */
|
/* Auf mobilen Geräten eine Karte anzeigen */
|
||||||
@media (max-width: 1280px) {
|
@media (max-width: 1280px) {
|
||||||
.termine-card {
|
.termine-card {
|
||||||
width: 100%; /* Volle Breite */
|
width: 100%;
|
||||||
|
/* Volle Breite */
|
||||||
}
|
}
|
||||||
|
|
||||||
#termine-container {
|
#termine-container {
|
||||||
space-x-0; /* Kein Abstand zwischen Karten nötig */
|
space-x-0;
|
||||||
|
/* Kein Abstand zwischen Karten nötig */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -283,9 +310,11 @@ $de_months = [
|
|||||||
.termine-card h3 {
|
.termine-card h3 {
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
/* white-space: nowrap; */ /* Diese Zeile entfernen oder kommentieren */
|
/* white-space: nowrap; */
|
||||||
|
/* Diese Zeile entfernen oder kommentieren */
|
||||||
display: -webkit-box;
|
display: -webkit-box;
|
||||||
-webkit-line-clamp: 2; /* Maximal 2 Zeilen anzeigen */
|
-webkit-line-clamp: 2;
|
||||||
|
/* Maximal 2 Zeilen anzeigen */
|
||||||
-webkit-box-orient: vertical;
|
-webkit-box-orient: vertical;
|
||||||
line-height: 1.3;
|
line-height: 1.3;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,14 +2,22 @@
|
|||||||
|
|
||||||
$events = collection('termine');
|
$events = collection('termine');
|
||||||
|
|
||||||
|
if ($events === null): ?>
|
||||||
|
<section class="py-24 bg-sf_grau-50">
|
||||||
|
<div class="mx-auto max-w-7xl px-4 sm:px-6 lg:px-8">
|
||||||
|
<div class="text-red-600 bg-white p-6 rounded-lg shadow">Die Termine können gerade nicht geladen werden.</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
<?php return; endif;
|
||||||
|
|
||||||
// Nur Events mit DTSTART berücksichtigen
|
// Nur Events mit DTSTART berücksichtigen
|
||||||
$events = array_filter($events, function ($event) {
|
$events = array_filter($events, function ($event) {
|
||||||
return isset($event['DTSTART']) && !empty($event['DTSTART']);
|
return isset($event['DTSTART']) && !empty($event['DTSTART']);
|
||||||
});
|
});
|
||||||
|
|
||||||
// Nach Datum sortieren
|
// Nach Datum sortieren
|
||||||
usort($events, function ($a, $b) {
|
usort($events, function ($a, $b) {
|
||||||
return strcmp($a['DTSTART'], $b['DTSTART']);
|
return strcmp($a['DTSTART'], $b['DTSTART']);
|
||||||
});
|
});
|
||||||
|
|
||||||
// Aktuelles Datum - PHP 8.3 kompatibel
|
// Aktuelles Datum - PHP 8.3 kompatibel
|
||||||
@@ -17,44 +25,44 @@ $today = (new DateTime('now'))->format('Ymd');
|
|||||||
|
|
||||||
// Nur zukünftige Termine anzeigen
|
// Nur zukünftige Termine anzeigen
|
||||||
$future_events = array_filter($events, function ($event) use ($today) {
|
$future_events = array_filter($events, function ($event) use ($today) {
|
||||||
return isset($event['DTSTART']) && $event['DTSTART'] >= $today;
|
return isset($event['DTSTART']) && $event['DTSTART'] >= $today;
|
||||||
});
|
});
|
||||||
|
|
||||||
// --- Deutsche Monatsnamen ---
|
// --- Deutsche Monatsnamen ---
|
||||||
$de_months = [
|
$de_months = [
|
||||||
'01' => 'Januar',
|
'01' => 'Januar',
|
||||||
'02' => 'Februar',
|
'02' => 'Februar',
|
||||||
'03' => 'März',
|
'03' => 'März',
|
||||||
'04' => 'April',
|
'04' => 'April',
|
||||||
'05' => 'Mai',
|
'05' => 'Mai',
|
||||||
'06' => 'Juni',
|
'06' => 'Juni',
|
||||||
'07' => 'Juli',
|
'07' => 'Juli',
|
||||||
'08' => 'August',
|
'08' => 'August',
|
||||||
'09' => 'September',
|
'09' => 'September',
|
||||||
'10' => 'Oktober',
|
'10' => 'Oktober',
|
||||||
'11' => 'November',
|
'11' => 'November',
|
||||||
'12' => 'Dezember',
|
'12' => 'Dezember',
|
||||||
];
|
];
|
||||||
|
|
||||||
// --- Gruppierung aller Termine nach Jahr und Monat für die Sidebar ---
|
// --- Gruppierung aller Termine nach Jahr und Monat für die Sidebar ---
|
||||||
function group_events_by_year_month($events)
|
function group_events_by_year_month($events)
|
||||||
{
|
{
|
||||||
$grouped = [];
|
$grouped = [];
|
||||||
foreach ($events as $event) {
|
foreach ($events as $event) {
|
||||||
if (!isset($event['DTSTART'])) {
|
if (!isset($event['DTSTART'])) {
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
$date = $event['DTSTART'];
|
||||||
|
$year = substr($date, 0, 4);
|
||||||
|
$month = substr($date, 4, 2);
|
||||||
|
$grouped[$year][$month][] = $event;
|
||||||
|
}
|
||||||
|
krsort($grouped); // Jahre absteigend
|
||||||
|
foreach ($grouped as &$months) {
|
||||||
|
krsort($months); // Monate absteigend
|
||||||
}
|
}
|
||||||
$date = $event['DTSTART'];
|
|
||||||
$year = substr($date, 0, 4);
|
|
||||||
$month = substr($date, 4, 2);
|
|
||||||
$grouped[$year][$month][] = $event;
|
|
||||||
}
|
|
||||||
krsort($grouped); // Jahre absteigend
|
|
||||||
foreach ($grouped as &$months) {
|
|
||||||
krsort($months); // Monate absteigend
|
|
||||||
}
|
|
||||||
|
|
||||||
return $grouped;
|
return $grouped;
|
||||||
}
|
}
|
||||||
|
|
||||||
$all_events_grouped = group_events_by_year_month($events);
|
$all_events_grouped = group_events_by_year_month($events);
|
||||||
@@ -64,19 +72,19 @@ $filter_jahr = filter_input(INPUT_GET, 'jahr', FILTER_SANITIZE_FULL_SPECIAL_CHAR
|
|||||||
$filter_monat = filter_input(INPUT_GET, 'monat', FILTER_SANITIZE_FULL_SPECIAL_CHARS) ?? null;
|
$filter_monat = filter_input(INPUT_GET, 'monat', FILTER_SANITIZE_FULL_SPECIAL_CHARS) ?? null;
|
||||||
|
|
||||||
if ($filter_jahr && $filter_monat) {
|
if ($filter_jahr && $filter_monat) {
|
||||||
$filtered_events = array_filter($events, function ($event) use ($filter_jahr, $filter_monat) {
|
$filtered_events = array_filter($events, function ($event) use ($filter_jahr, $filter_monat) {
|
||||||
$date = $event['DTSTART'] ?? '';
|
$date = $event['DTSTART'] ?? '';
|
||||||
|
|
||||||
return substr($date, 0, 4) === $filter_jahr && substr($date, 4, 2) === $filter_monat;
|
return substr($date, 0, 4) === $filter_jahr && substr($date, 4, 2) === $filter_monat;
|
||||||
});
|
});
|
||||||
} elseif ($filter_jahr) {
|
} elseif ($filter_jahr) {
|
||||||
$filtered_events = array_filter($events, function ($event) use ($filter_jahr) {
|
$filtered_events = array_filter($events, function ($event) use ($filter_jahr) {
|
||||||
$date = $event['DTSTART'] ?? '';
|
$date = $event['DTSTART'] ?? '';
|
||||||
|
|
||||||
return substr($date, 0, 4) === $filter_jahr;
|
return substr($date, 0, 4) === $filter_jahr;
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
$filtered_events = $future_events;
|
$filtered_events = $future_events;
|
||||||
}
|
}
|
||||||
?>
|
?>
|
||||||
|
|
||||||
@@ -90,33 +98,34 @@ if ($filter_jahr && $filter_monat) {
|
|||||||
<?php foreach ($all_events_grouped as $year => $months): ?>
|
<?php foreach ($all_events_grouped as $year => $months): ?>
|
||||||
<li class="mb-2">
|
<li class="mb-2">
|
||||||
<div class="flex items-center">
|
<div class="flex items-center">
|
||||||
<?php
|
<?php
|
||||||
$safe_year = htmlspecialchars($year, ENT_QUOTES, 'UTF-8');
|
$safe_year = htmlspecialchars($year, ENT_QUOTES, 'UTF-8');
|
||||||
$is_year_selected = ($filter_jahr === $year && !$filter_monat);
|
$is_year_selected = ($filter_jahr === $year && !$filter_monat);
|
||||||
?>
|
?>
|
||||||
<a href="?jahr=<?= $safe_year ?>"
|
<a href="?jahr=<?= $safe_year ?>"
|
||||||
class="font-bold text-sf_blau-600 focus:outline-none flex items-center group<?= $is_year_selected ? ' underline selected' : '' ?>"
|
class="font-bold text-sf_blau-600 focus:outline-none flex items-center group<?= $is_year_selected ? ' underline selected' : '' ?>"
|
||||||
onclick="event.stopPropagation(); openYear('<?= $safe_year ?>')">
|
onclick="event.stopPropagation(); openYear('<?= $safe_year ?>')">
|
||||||
<span><?= $safe_year ?></span>
|
<span><?= $safe_year ?></span>
|
||||||
</a>
|
</a>
|
||||||
<button type="button" class="ml-1 focus:outline-none" onclick="toggleYear('<?= $safe_year ?>')">
|
<button type="button" class="ml-1 focus:outline-none"
|
||||||
<svg class="w-4 h-4 transition-transform" id="arrow-<?= $safe_year ?>" fill="none" stroke="currentColor" stroke-width="2"
|
onclick="toggleYear('<?= $safe_year ?>')">
|
||||||
viewBox="0 0 24 24">
|
<svg class="w-4 h-4 transition-transform" id="arrow-<?= $safe_year ?>" fill="none"
|
||||||
<path stroke-linecap="round" stroke-linejoin="round" d="M9 5l7 7-7 7"/>
|
stroke="currentColor" stroke-width="2" viewBox="0 0 24 24">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" d="M9 5l7 7-7 7" />
|
||||||
</svg>
|
</svg>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<ul class="ml-4 mt-1 hidden" id="months-<?= $safe_year ?>">
|
<ul class="ml-4 mt-1 hidden" id="months-<?= $safe_year ?>">
|
||||||
<?php foreach ($months as $month => $evts): ?>
|
<?php foreach ($months as $month => $evts): ?>
|
||||||
<li>
|
<li>
|
||||||
<?php
|
<?php
|
||||||
$safe_month = htmlspecialchars($month, ENT_QUOTES, 'UTF-8');
|
$safe_month = htmlspecialchars($month, ENT_QUOTES, 'UTF-8');
|
||||||
$month_name = $de_months[$month] ?? 'Unbekannt';
|
$month_name = $de_months[$month] ?? 'Unbekannt';
|
||||||
$is_month_selected = ($filter_jahr === $year && $filter_monat === $month);
|
$is_month_selected = ($filter_jahr === $year && $filter_monat === $month);
|
||||||
$event_count = count($evts);
|
$event_count = count($evts);
|
||||||
?>
|
?>
|
||||||
<a href="?jahr=<?= $safe_year ?>&monat=<?= $safe_month ?>"
|
<a href="?jahr=<?= $safe_year ?>&monat=<?= $safe_month ?>"
|
||||||
class="text-sf_blau-500 hover:underline<?= $is_month_selected ? ' font-bold underline selected' : '' ?>">
|
class="text-sf_blau-500 hover:underline<?= $is_month_selected ? ' font-bold underline selected' : '' ?>">
|
||||||
<?= htmlspecialchars($month_name, ENT_QUOTES, 'UTF-8') ?> (<?= $event_count ?>)
|
<?= htmlspecialchars($month_name, ENT_QUOTES, 'UTF-8') ?> (<?= $event_count ?>)
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
@@ -157,50 +166,50 @@ if ($filter_jahr && $filter_monat) {
|
|||||||
<div class="overflow-x-auto">
|
<div class="overflow-x-auto">
|
||||||
<table class="min-w-full border border-gray-200 bg-white rounded-lg shadow">
|
<table class="min-w-full border border-gray-200 bg-white rounded-lg shadow">
|
||||||
<thead>
|
<thead>
|
||||||
<tr class="bg-gray-100">
|
<tr class="bg-gray-100">
|
||||||
<th class="py-2 px-4 border-b text-left">Datum</th>
|
<th class="py-2 px-4 border-b text-left">Datum</th>
|
||||||
<th class="py-2 px-4 border-b text-left">Uhrzeit</th>
|
<th class="py-2 px-4 border-b text-left">Uhrzeit</th>
|
||||||
<th class="py-2 px-4 border-b text-left">Titel</th>
|
<th class="py-2 px-4 border-b text-left">Titel</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
<?php foreach ($filtered_events as $event): ?>
|
<?php foreach ($filtered_events as $event): ?>
|
||||||
<?php
|
<?php
|
||||||
$start = $event['DTSTART'] ?? '';
|
$start = $event['DTSTART'] ?? '';
|
||||||
$end = $event['DTEND'] ?? '';
|
$end = $event['DTEND'] ?? '';
|
||||||
$summary = $event['SUMMARY'] ?? '';
|
$summary = $event['SUMMARY'] ?? '';
|
||||||
$location = $event['LOCATION'] ?? '';
|
$location = $event['LOCATION'] ?? '';
|
||||||
$desc = $event['DESCRIPTION'] ?? '';
|
$desc = $event['DESCRIPTION'] ?? '';
|
||||||
$timezone = $event['DTSTART_TZID'] ?? null;
|
$timezone = $event['DTSTART_TZID'] ?? null;
|
||||||
|
|
||||||
// Sichere Funktionsaufrufe mit Null-Checks
|
// Sichere Funktionsaufrufe mit Null-Checks
|
||||||
$date_info = function_exists('format_ics_date_with_timezone')
|
$date_info = function_exists('format_ics_date_with_timezone')
|
||||||
? format_ics_date_with_timezone($start, $timezone)
|
? format_ics_date_with_timezone($start, $timezone)
|
||||||
: ['display' => '', 'has_time' => false, 'iso' => ''];
|
: ['display' => '', 'has_time' => false, 'iso' => ''];
|
||||||
|
|
||||||
$date = $date_info['display'] ?? '';
|
$date = $date_info['display'] ?? '';
|
||||||
$time = ($date_info['has_time'] ?? false) ? substr($date, 11) : 'ganztägig';
|
$time = ($date_info['has_time'] ?? false) ? substr($date, 11) : 'ganztägig';
|
||||||
$date = substr($date, 0, 10);
|
$date = substr($date, 0, 10);
|
||||||
$iso_date = $date_info['iso'] ?? '';
|
$iso_date = $date_info['iso'] ?? '';
|
||||||
|
|
||||||
// Sichere HTML-Ausgabe
|
// Sichere HTML-Ausgabe
|
||||||
$safe_date = htmlspecialchars($date, ENT_QUOTES, 'UTF-8');
|
$safe_date = htmlspecialchars($date, ENT_QUOTES, 'UTF-8');
|
||||||
$safe_time = htmlspecialchars($time, ENT_QUOTES, 'UTF-8');
|
$safe_time = htmlspecialchars($time, ENT_QUOTES, 'UTF-8');
|
||||||
$safe_iso_date = htmlspecialchars($iso_date, ENT_QUOTES, 'UTF-8');
|
$safe_iso_date = htmlspecialchars($iso_date, ENT_QUOTES, 'UTF-8');
|
||||||
$safe_summary = htmlspecialchars($summary, ENT_QUOTES, 'UTF-8');
|
$safe_summary = htmlspecialchars($summary, ENT_QUOTES, 'UTF-8');
|
||||||
?>
|
?>
|
||||||
<tr class="hover:bg-gray-50">
|
<tr class="hover:bg-gray-50">
|
||||||
<td class="py-2 px-4 border-b whitespace-nowrap"><?= $safe_date ?></td>
|
<td class="py-2 px-4 border-b whitespace-nowrap"><?= $safe_date ?></td>
|
||||||
<td class="py-2 px-4 border-b whitespace-nowrap">
|
<td class="py-2 px-4 border-b whitespace-nowrap">
|
||||||
<?php if ($date_info['has_time'] ?? false): ?>
|
<?php if ($date_info['has_time'] ?? false): ?>
|
||||||
<span class="local-time" data-iso-date="<?= $safe_iso_date ?>"><?= $safe_time ?></span>
|
<span class="local-time" data-iso-date="<?= $safe_iso_date ?>"><?= $safe_time ?></span>
|
||||||
<?php else: ?>
|
<?php else: ?>
|
||||||
ganztägig
|
ganztägig
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
</td>
|
</td>
|
||||||
<td class="py-2 px-4 border-b"><?= $safe_summary ?></td>
|
<td class="py-2 px-4 border-b"><?= $safe_summary ?></td>
|
||||||
</tr>
|
</tr>
|
||||||
<?php endforeach; ?>
|
<?php endforeach; ?>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
@@ -214,7 +223,7 @@ if ($filter_jahr && $filter_monat) {
|
|||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
// Zeitzonenkonvertierung für lokale Zeiten
|
// Zeitzonenkonvertierung für lokale Zeiten
|
||||||
function convertTimesToLocal() {
|
function convertTimesToLocal() {
|
||||||
@@ -226,23 +235,23 @@ if ($filter_jahr && $filter_monat) {
|
|||||||
// Erstelle ein Date-Objekt aus der ISO-Date
|
// Erstelle ein Date-Objekt aus der ISO-Date
|
||||||
// JavaScript erkennt automatisch UTC-Zeiten (mit Z oder +00:00)
|
// JavaScript erkennt automatisch UTC-Zeiten (mit Z oder +00:00)
|
||||||
const date = new Date(isoDate);
|
const date = new Date(isoDate);
|
||||||
|
|
||||||
// Prüfe ob das Datum gültig ist
|
// Prüfe ob das Datum gültig ist
|
||||||
if (isNaN(date.getTime())) {
|
if (isNaN(date.getTime())) {
|
||||||
console.warn('Ungültiges Datum:', isoDate);
|
console.warn('Ungültiges Datum:', isoDate);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Formatiere die Zeit in der lokalen Zeitzone des Browsers
|
// Formatiere die Zeit in der lokalen Zeitzone des Browsers
|
||||||
const localTime = date.toLocaleTimeString('de-DE', {
|
const localTime = date.toLocaleTimeString('de-DE', {
|
||||||
hour: '2-digit',
|
hour: '2-digit',
|
||||||
minute: '2-digit',
|
minute: '2-digit',
|
||||||
hour12: false
|
hour12: false
|
||||||
});
|
});
|
||||||
|
|
||||||
// Aktualisiere den Text
|
// Aktualisiere den Text
|
||||||
element.textContent = localTime;
|
element.textContent = localTime;
|
||||||
|
|
||||||
// Debug-Information (kann später entfernt werden)
|
// Debug-Information (kann später entfernt werden)
|
||||||
console.log('Konvertiert:', isoDate, '->', localTime, 'in Zeitzone:', Intl.DateTimeFormat().resolvedOptions().timeZone);
|
console.log('Konvertiert:', isoDate, '->', localTime, 'in Zeitzone:', Intl.DateTimeFormat().resolvedOptions().timeZone);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@@ -253,7 +262,7 @@ if ($filter_jahr && $filter_monat) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Zeitzonenkonvertierung beim Laden der Seite
|
// Zeitzonenkonvertierung beim Laden der Seite
|
||||||
document.addEventListener('DOMContentLoaded', function() {
|
document.addEventListener('DOMContentLoaded', function () {
|
||||||
convertTimesToLocal();
|
convertTimesToLocal();
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -1,16 +1,16 @@
|
|||||||
<?php snippet('layout', slots: true) ?>
|
<?php snippet('layout', slots: true) ?>
|
||||||
|
|
||||||
<?php
|
<?php
|
||||||
// Filterfunktionalität implementieren
|
// Filterfunktionalität implementieren
|
||||||
$posts = $page->children()->sortBy('date', 'desc');
|
$posts = $page->children()->sortBy('date', 'desc')->paginate(5);
|
||||||
|
|
||||||
// Nach Kategorie (Tag) filtern
|
// Nach Kategorie (Tag) filtern
|
||||||
if($tag = param('tag')) {
|
if ($tag = param('tag')) {
|
||||||
$posts = $posts->filterBy('tags', $tag, ',');
|
$posts = $posts->filterBy('tags', $tag, ',');
|
||||||
}
|
}
|
||||||
?>
|
?>
|
||||||
|
|
||||||
<?php foreach($posts as $post): ?>
|
<?php foreach ($posts as $post): ?>
|
||||||
<article class="relative flex flex-col gap-8 lg:flex-row py-12">
|
<article class="relative flex flex-col gap-8 lg:flex-row py-12">
|
||||||
<div class="relative aspect-video sm:aspect-2/1 lg:aspect-square lg:w-64 lg:shrink-0">
|
<div class="relative aspect-video sm:aspect-2/1 lg:aspect-square lg:w-64 lg:shrink-0">
|
||||||
<img src="<?= $post->image()->url() ?>" alt="" class="absolute inset-0 size-full rounded-xl object-cover" />
|
<img src="<?= $post->image()->url() ?>" alt="" class="absolute inset-0 size-full rounded-xl object-cover" />
|
||||||
@@ -22,8 +22,9 @@
|
|||||||
<time class="text-gray-500"><?= $post->date()->toDate("d.m.Y") ?></time>
|
<time class="text-gray-500"><?= $post->date()->toDate("d.m.Y") ?></time>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<?php foreach($post->tags()->split() as $tag): ?>
|
<?php foreach ($post->tags()->split() as $tag): ?>
|
||||||
<a href="<?= $page->url(['params' => ['tag' => $tag]]) ?>" class="relative z-10 rounded-full bg-gray-50 px-3 py-1.5 font-medium text-gray-600 hover:bg-gray-100"><?= $tag ?></a>
|
<a href="<?= $page->url(['params' => ['tag' => $tag]]) ?>"
|
||||||
|
class="relative z-10 rounded-full bg-gray-50 px-3 py-1.5 font-medium text-gray-600 hover:bg-gray-100"><?= $tag ?></a>
|
||||||
<?php endforeach; ?>
|
<?php endforeach; ?>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -37,33 +38,62 @@
|
|||||||
<p><?= $post->summary() ?></p>
|
<p><?= $post->summary() ?></p>
|
||||||
</div>
|
</div>
|
||||||
<?php if ($user = $post->author()->toUser()): ?>
|
<?php if ($user = $post->author()->toUser()): ?>
|
||||||
<div class="mt-6 flex border-t border-gray-900/5 pt-6">
|
<div class="mt-6 flex border-t border-gray-900/5 pt-6">
|
||||||
<div class="relative flex items-center gap-x-4">
|
<div class="relative flex items-center gap-x-4">
|
||||||
<?php if ($user->avatar()): ?>
|
<?php if ($user->avatar()): ?>
|
||||||
<img src="<?= $user->avatar()->url() ?>" alt="" class="size-10 rounded-full bg-gray-50" />
|
<img src="<?= $user->avatar()->url() ?>" alt="" class="size-10 rounded-full bg-gray-50" />
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
<div class="text-sm/6">
|
<div class="text-sm/6">
|
||||||
<p>
|
<p>
|
||||||
<span class="absolute inset-0"></span>
|
<span class="absolute inset-0"></span>
|
||||||
<div class="text-xl">
|
<div class="text-xl">
|
||||||
<?= $user->username() ?>
|
<?= $user->username() ?>
|
||||||
</div>
|
</div>
|
||||||
</p>
|
</p>
|
||||||
<p class="text-sm"><?= $user->role()->title() ?></p>
|
<p class="text-sm"><?= $user->role()->title() ?></p>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
<?php endif ?>
|
<?php endif ?>
|
||||||
</div>
|
</div>
|
||||||
</article>
|
</article>
|
||||||
<?php endforeach ?>
|
<?php endforeach ?>
|
||||||
|
<?php $pagination = $posts->pagination(); ?>
|
||||||
<?php if(param('tag')): ?>
|
<?php if ($pagination->hasPages()): ?>
|
||||||
|
<nav class="flex justify-between items-center my-12 border-t border-gray-100 pt-8">
|
||||||
|
<?php if ($pagination->hasPrevPage()): ?>
|
||||||
|
<a href="<?= $pagination->prevPageUrl() ?>"
|
||||||
|
class="flex items-center gap-2 rounded-full bg-gray-50 px-4 py-2 text-sm font-medium text-gray-600 hover:bg-gray-100 transition-colors">
|
||||||
|
← Neuere Beiträge
|
||||||
|
</a>
|
||||||
|
<?php else: ?>
|
||||||
|
<span class="flex items-center gap-2 rounded-full px-4 py-2 text-sm font-medium text-gray-300 cursor-not-allowed">
|
||||||
|
← Neuere Beiträge
|
||||||
|
</span>
|
||||||
|
<?php endif ?>
|
||||||
|
|
||||||
|
<span class="text-xs font-medium text-gray-400">
|
||||||
|
Seite <?= $pagination->page() ?> von <?= $pagination->pages() ?>
|
||||||
|
</span>
|
||||||
|
|
||||||
|
<?php if ($pagination->hasNextPage()): ?>
|
||||||
|
<a href="<?= $pagination->nextPageUrl() ?>"
|
||||||
|
class="flex items-center gap-2 rounded-full bg-gray-50 px-4 py-2 text-sm font-medium text-gray-600 hover:bg-gray-100 transition-colors">
|
||||||
|
Ältere Beiträge →
|
||||||
|
</a>
|
||||||
|
<?php else: ?>
|
||||||
|
<span class="flex items-center gap-2 rounded-full px-4 py-2 text-sm font-medium text-gray-300 cursor-not-allowed">
|
||||||
|
Ältere Beiträge →
|
||||||
|
</span>
|
||||||
|
<?php endif ?>
|
||||||
|
</nav>
|
||||||
|
<?php endif ?>
|
||||||
|
|
||||||
|
|
||||||
|
<?php if (param('tag')): ?>
|
||||||
<div class="my-8">
|
<div class="my-8">
|
||||||
<a href="<?= $page->url() ?>" class="bg-gray-100 hover:bg-gray-200 text-gray-800 font-semibold py-2 px-4 rounded">
|
<a href="<?= $page->url() ?>" class="bg-gray-100 hover:bg-gray-200 text-gray-800 font-semibold py-2 px-4 rounded">
|
||||||
Alle Beiträge anzeigen
|
Alle Beiträge anzeigen
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<?php endif ?>
|
<?php endif ?><?php endsnippet() ?>
|
||||||
|
|
||||||
<?php endsnippet() ?>
|
|
||||||
@@ -1,5 +1,29 @@
|
|||||||
<?php snippet('layout', slots: true) ?>
|
<?php
|
||||||
|
// Wenn dies die Startseite ist, verwende die Home-Vorlage
|
||||||
<h1>Hallo Welt!</h1>
|
if ($page->isHomePage()) {
|
||||||
|
snippet('layout', slots: true);
|
||||||
<?php endsnippet() ?>
|
?>
|
||||||
|
<h1>Herzlich Willkommen!</h1>
|
||||||
|
|
||||||
|
<?= $page->text()->kirbytext() ?>
|
||||||
|
|
||||||
|
<?php snippet('home-news', [
|
||||||
|
'news' => page('news')->children()->limit(3)->sortBy('date', 'desc'),
|
||||||
|
]); ?>
|
||||||
|
|
||||||
|
<?php snippet('home-termine'); ?>
|
||||||
|
|
||||||
|
<?php snippet('puzzle'); ?>
|
||||||
|
<?php
|
||||||
|
endsnippet();
|
||||||
|
} else {
|
||||||
|
// Für andere Seiten
|
||||||
|
snippet('layout', slots: true);
|
||||||
|
?>
|
||||||
|
<h1><?= $page->title()->esc() ?></h1>
|
||||||
|
|
||||||
|
<?= $page->text()->kirbytext() ?>
|
||||||
|
<?php
|
||||||
|
endsnippet();
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
|||||||