Compare commits

..
3 Commits
18 changed files with 369 additions and 8 deletions

No files matched your search

+7 -1
View File
@@ -1,5 +1,11 @@
# AGENTS.md # AGENTS.md
## Guidlines
Ich bin Softwareentwickler, Full-Stack Webentwickler und Netzwerkadministrator. Ich möchte bei allen Software und Netzwerk-Design-Entscheidungen und beim Erstellen von Code eingebunden werden.
Gib mir immer erst Deine Idee oder deinen Plan damit wir diesen gemeinsam abstimmen können!
Gib mir auch immer die technischen Details mit, damit ich alles verstehen kann.
## Ziel ## Ziel
Diese Aufgabe betrifft die Implementierung einer Terminbuchungs-Funktion für die Website des Perspektivwerks und der Produktionsschule. Ziel ist eine nutzerfreundliche Buchungsoberfläche, die den genannten Terminarten entspricht, mobil nutzbar ist, sicher umgesetzt wird und später in einen Google-Kalender integriert werden kann. Diese Aufgabe betrifft die Implementierung einer Terminbuchungs-Funktion für die Website des Perspektivwerks und der Produktionsschule. Ziel ist eine nutzerfreundliche Buchungsoberfläche, die den genannten Terminarten entspricht, mobil nutzbar ist, sicher umgesetzt wird und später in einen Google-Kalender integriert werden kann.
@@ -75,7 +81,7 @@ Für die weitere Umsetzung bedeutet das:
- Keine geheimen Zugangsdaten, Tokens, Keys oder Secrets im Repository speichern. - Keine geheimen Zugangsdaten, Tokens, Keys oder Secrets im Repository speichern.
- Eingaben immer validieren und bereinigen; XSS- und Injection-Angriffe vermeiden. - Eingaben immer validieren und bereinigen; XSS- und Injection-Angriffe vermeiden.
- Wenn Sicherheitsrelevanter Code geschrieben wurde, soll gefragt werden ob eine gesonderete tiefe Sicherheitsanalyse dafür durchgeführt werden soll. - Wenn Sicherheitsrelevanter Code geschrieben wurde, soll gefragt werden ob eine gesonderete tiefe Sicherheitsanalyse dafür durchgeführt werden soll.
- Wenn Formulare oder API-Calls später eingesetzt werden, nur mit abgesicherten, validierten Requests arbeiten. - Wenn Formulare oder API-Calls später eingesetzt werden, nur mit abgesicherten, validierten Requests arbeiten.
- Bei späterem Backend- und API-Setup: sichere Authentifizierung, autorisierte Zugriffe und minimal notwendige Berechtigungen verwenden. - Bei späterem Backend- und API-Setup: sichere Authentifizierung, autorisierte Zugriffe und minimal notwendige Berechtigungen verwenden.
- Keine sensiblen Daten im Client- oder Mockup-Code sichtbar machen. - Keine sensiblen Daten im Client- oder Mockup-Code sichtbar machen.
+8 -1
View File
@@ -1,6 +1,13 @@
/vendor/ /vendor/
/var/ /var/
/public/assets/js/ /public/assets
/public/bundles
/public/share
/public/system
/public/vendor
/system
/bin/console
/node_modules/ /node_modules/
/.env /.env
/.env.local
/.idea/ /.idea/
+11 -2
View File
@@ -10,10 +10,16 @@ Voraussetzungen: Docker Desktop (Compose v2) und optional Node.js 20+ für die T
docker compose up --build docker compose up --build
``` ```
Danach: Beim ersten Start eines frischen Clones erzeugt Contao die benötigten Laufzeitverzeichnisse und Asset-Symlinks. Danach einmalig ausführen:
```powershell
docker compose exec app vendor/bin/contao-setup --no-interaction --env=dev
docker compose exec app chown -R www-data:www-data var public
docker compose exec app vendor/bin/contao-console contao:migrate --no-interaction
```
- Website/CMS: <http://localhost:8080> - Website/CMS: <http://localhost:8080>
- Contao-Installation: <http://localhost:8080/contao/install> - Contao-Login: <http://localhost:8080/contao/login>
- Datenbankinspektor: <http://localhost:8081> (Server `db`, Benutzer `perspektivwerk`, Passwort `perspektivwerk`, Datenbank `perspektivwerk`) - Datenbankinspektor: <http://localhost:8081> (Server `db`, Benutzer `perspektivwerk`, Passwort `perspektivwerk`, Datenbank `perspektivwerk`)
Für die Frontend-Logik: Für die Frontend-Logik:
@@ -23,6 +29,9 @@ npm install
npm run build npm run build
``` ```
**Dann die Seite öffnen:**
http://localhost:8080/perspektivwerk/
## Abgrenzung zur Originalseite ## Abgrenzung zur Originalseite
Die genaue Contao-, PHP- und Template-Version der öffentlichen Seite ist nicht verlässlich aus dem ausgelieferten HTML ableitbar. Das Setup bildet daher die wahrscheinlichste Komponentenfamilie nach; es ist kein Dump der Produktivinstallation. IONOS/Hosting, Matomo-Konfiguration, Inhalte, Templates und Erweiterungen müssen bei Bedarf separat ergänzt werden. Die genaue Contao-, PHP- und Template-Version der öffentlichen Seite ist nicht verlässlich aus dem ausgelieferten HTML ableitbar. Das Setup bildet daher die wahrscheinlichste Komponentenfamilie nach; es ist kein Dump der Produktivinstallation. IONOS/Hosting, Matomo-Konfiguration, Inhalte, Templates und Erweiterungen müssen bei Bedarf separat ergänzt werden.
+33
View File
@@ -0,0 +1,33 @@
#!/usr/bin/env php
<?php
declare(strict_types=1);
/*
* This file is part of Contao.
*
* (c) Leo Feyer
*
* @license LGPL-3.0-or-later
*/
use Contao\ManagerBundle\Console\ContaoApplication;
use Contao\ManagerBundle\HttpKernel\ContaoKernel;
use Symfony\Component\Console\Input\ArgvInput;
set_time_limit(0);
@ini_set('zlib.output_compression', '0');
@ini_set('display_errors', '0');
// System maintenance mode comes first as it has to work even if the vendor directory does not exist
if ('contao:cron' === ($_SERVER['argv'][1] ?? null) && file_exists(__DIR__.'/../var/maintenance.html')) {
exit;
}
require __DIR__.'/../vendor/autoload.php';
$input = new ArgvInput();
$kernel = ContaoKernel::fromInput(\dirname(__DIR__), $input);
$application = new ContaoApplication($kernel);
$application->run($input);
+2
View File
@@ -5,6 +5,8 @@
"require": { "require": {
"contao/managed-edition": "^5.3" "contao/managed-edition": "^5.3"
}, },
"minimum-stability": "dev",
"prefer-stable": true,
"scripts": { "scripts": {
"post-install-cmd": [ "post-install-cmd": [
"Contao\\ManagerPlugin\\Bundle\\Config\\ScriptHandler::initializeApplication" "Contao\\ManagerPlugin\\Bundle\\Config\\ScriptHandler::initializeApplication"
+2 -2
View File
@@ -2,13 +2,13 @@ services:
app: app:
build: build:
context: . context: .
dockerfile: docker/php-apache/Dockerfile dockerfile: php-apache/Dockerfile
ports: ports:
- "8080:80" - "8080:80"
environment: environment:
APP_ENV: dev APP_ENV: dev
CONTAO_ENVIRONMENT: dev CONTAO_ENVIRONMENT: dev
DATABASE_URL: mysql://perspektivwerk:perspektivwerk@db:3306/perspektivwerk?serverVersion=mariadb-10.11 DATABASE_URL: mysql://perspektivwerk:perspektivwerk@db:3306/perspektivwerk?serverVersion=mariadb-10.11.0
volumes: volumes:
- ./:/var/www/html - ./:/var/www/html
- contao_vendor:/var/www/html/vendor - contao_vendor:/var/www/html/vendor
+95
View File
@@ -0,0 +1,95 @@
{
"name": "perspektivwerk-booking-frontend",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "perspektivwerk-booking-frontend",
"dependencies": {
"bootstrap": "^5.3.3",
"jquery": "^3.7.1",
"slick-carousel": "^1.8.1"
},
"devDependencies": {
"@types/jquery": "^3.5.32",
"typescript": "^5.7.2"
}
},
"node_modules/@popperjs/core": {
"version": "2.11.8",
"resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz",
"integrity": "sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==",
"license": "MIT",
"peer": true,
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/popperjs"
}
},
"node_modules/@types/jquery": {
"version": "3.5.34",
"resolved": "https://registry.npmjs.org/@types/jquery/-/jquery-3.5.34.tgz",
"integrity": "sha512-3m3939S3erqmTLJANS/uy0B6V7BorKx7RorcGZVjZ62dF5PAGbKEDZK1CuLtKombJkFA2T1jl8LAIIs7IV6gBQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"@types/sizzle": "*"
}
},
"node_modules/@types/sizzle": {
"version": "2.3.10",
"resolved": "https://registry.npmjs.org/@types/sizzle/-/sizzle-2.3.10.tgz",
"integrity": "sha512-TC0dmN0K8YcWEAEfiPi5gJP14eJe30TTGjkvek3iM/1NdHHsdCA/Td6GvNndMOo/iSnIsZ4HuuhrYPDAmbxzww==",
"dev": true,
"license": "MIT"
},
"node_modules/bootstrap": {
"version": "5.3.8",
"resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-5.3.8.tgz",
"integrity": "sha512-HP1SZDqaLDPwsNiqRqi5NcP0SSXciX2s9E+RyqJIIqGo+vJeN5AJVM98CXmW/Wux0nQ5L7jeWUdplCEf0Ee+tg==",
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/twbs"
},
{
"type": "opencollective",
"url": "https://opencollective.com/bootstrap"
}
],
"license": "MIT",
"peerDependencies": {
"@popperjs/core": "^2.11.8"
}
},
"node_modules/jquery": {
"version": "3.7.1",
"resolved": "https://registry.npmjs.org/jquery/-/jquery-3.7.1.tgz",
"integrity": "sha512-m4avr8yL8kmFN8psrbFFFmB/If14iN5o9nw/NgnnM+kybDJpRsAynV2BsfpTYrTRysYUdADVD7CkUUizgkpLfg==",
"license": "MIT"
},
"node_modules/slick-carousel": {
"version": "1.8.1",
"resolved": "https://registry.npmjs.org/slick-carousel/-/slick-carousel-1.8.1.tgz",
"integrity": "sha512-XB9Ftrf2EEKfzoQXt3Nitrt/IPbT+f1fgqBdoxO3W/+JYvtEOW6EgxnWfr9GH6nmULv7Y2tPmEX3koxThVmebA==",
"license": "MIT",
"peerDependencies": {
"jquery": ">=1.8.0"
}
},
"node_modules/typescript": {
"version": "5.9.3",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz",
"integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==",
"dev": true,
"license": "Apache-2.0",
"bin": {
"tsc": "bin/tsc",
"tsserver": "bin/tsserver"
},
"engines": {
"node": ">=14.17"
}
}
}
}
+1 -1
View File
@@ -9,7 +9,7 @@ RUN apt-get update \
&& rm -rf /var/lib/apt/lists/* && rm -rf /var/lib/apt/lists/*
COPY --from=composer:2 /usr/bin/composer /usr/bin/composer COPY --from=composer:2 /usr/bin/composer /usr/bin/composer
COPY docker/php-apache/vhost.conf /etc/apache2/sites-available/000-default.conf COPY php-apache/vhost.conf /etc/apache2/sites-available/000-default.conf
WORKDIR /var/www/html WORKDIR /var/www/html
+64
View File
@@ -0,0 +1,64 @@
<IfModule mod_rewrite.c>
RewriteEngine On
<IfModule mod_headers.c>
# Assets in /assets and /bundles either contain a hash in their filename
# or are called with a ?version suffix, therefore cache them for 1 year.
RewriteRule ^(assets|bundles)/ - [ENV=CONTAO_ASSETS:true]
Header set Cache-Control "max-age=31536000" env=CONTAO_ASSETS
# Allow CORS on the Contao TinyMCE skin.
RewriteRule ^assets/tinymce4/js/skins/contao/fonts/ - [ENV=CONTAO_TINYMCE_SKIN:true]
Header set Access-Control-Allow-Origin "*" env=CONTAO_TINYMCE_SKIN
</IfModule>
# Determine the RewriteBase automatically and set it as environment variable.
# If you are using Apache aliases to do mass virtual hosting or installed the
# project in a subdirectory, the base path will be prepended to allow proper
# resolution of the index.php file and to redirect to the correct URI. It will
# work in environments without path prefix as well, providing a safe, one-size
# fits all solution. But as you do not need it in this case, you can comment
# the following 2 lines to eliminate the overhead.
RewriteCond %{REQUEST_URI}::$1 ^(/.+)/(.*)::\2$
RewriteRule ^(.*) - [E=BASE:%1]
# Sets the HTTP_AUTHORIZATION header removed by Apache
RewriteCond %{HTTP:Authorization} .
RewriteRule ^ - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
# Static mockup used during local booking UI development.
RewriteRule ^perspektivwerk/?$ perspektivwerk/index.html [L]
RewriteRule ^(?:index\.html)?$ perspektivwerk/index.html [L]
# Redirect to URI without front controller to prevent duplicate content
# (with and without `/index.php`). Only do this redirect on the initial
# rewrite by Apache and not on subsequent cycles. Otherwise, we would get an
# endless redirect loop (request -> rewrite to front controller ->
# redirect -> request -> ...).
# So in case you get a "too many redirects" error or you always get redirected
# to the start page because your Apache does not expose the REDIRECT_STATUS
# environment variable, you have 2 choices:
# - disable this feature by commenting the following 2 lines or
# - use Apache >= 2.3.9 and replace all L flags by END flags and remove the
# following RewriteCond (best solution)
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteRule ^index\.php(?:/(.*)|$) %{ENV:BASE}/$1 [R=301,L]
# If the requested filename exists, simply serve it.
# We only want to let Apache serve files and not directories.
RewriteCond %{REQUEST_FILENAME} -f
RewriteRule ^ - [L]
# Rewrite all other queries to the front controller.
RewriteRule ^ %{ENV:BASE}/index.php [L]
</IfModule>
<IfModule !mod_rewrite.c>
<IfModule mod_alias.c>
# When mod_rewrite is not available, we instruct a temporary redirect of
# the start page to the front controller explicitly so that the website
# and the generated links can still be used.
RedirectMatch 302 ^/$ /index.php/
# RedirectTemp cannot be used instead
</IfModule>
</IfModule>
+47
View File
@@ -0,0 +1,47 @@
<?php
declare(strict_types=1);
/*
* This file is part of Contao.
*
* (c) Leo Feyer
*
* @license LGPL-3.0-or-later
*/
use Contao\ManagerBundle\HttpKernel\ContaoKernel;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\TerminableInterface;
// Suppress error messages (see #1422)
@ini_set('display_errors', '0');
// Disable the phar stream wrapper for security reasons (see #105)
if (in_array('phar', stream_get_wrappers(), true)) {
stream_wrapper_unregister('phar');
}
// System maintenance mode comes first as it has to work even if the vendor directory does not exist
if (file_exists(__DIR__.'/../var/maintenance.html')) {
$contents = file_get_contents(__DIR__.'/../var/maintenance.html');
http_response_code(503);
header('Content-Type: text/html; charset=UTF-8');
header('Content-Length: '.strlen((string) $contents));
header('Cache-Control: no-store');
die($contents);
}
$loader = require __DIR__.'/../vendor/autoload.php';
$request = Request::createFromGlobals();
$kernel = ContaoKernel::fromRequest(dirname(__DIR__), $request);
$response = $kernel->handle($request);
$response->send();
if ($kernel instanceof TerminableInterface) {
$kernel->terminate($request, $response);
}
@@ -0,0 +1,26 @@
<!doctype html>
<html lang="de">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="description" content="PerspektivWerk – Brücke zwischen Diagnostik, Begleitung und betrieblicher Praxis.">
<title>PerspektivWerk | SUFW Dresden</title>
<link rel="stylesheet" href="styles.css">
</head>
<body>
<a class="skip-link" href="#main">Navigation überspringen</a>
<header class="site-header">
<div class="header-top page-width"><a href="/" class="brand"><img src="media/logo-sufw.png" alt="Bildung & Beschäftigung SUFW"></a><div class="quick-links"><span class="round-icon">●</span><span class="round-icon">●</span><span class="round-icon">◎</span><label class="search"><span class="visually-hidden">Suche</span><input type="search" placeholder="Suche"><b>⌕</b></label><strong>A+</strong><strong>A−</strong><a href="#aktuelles">Aktuelles</a><a href="#karriere">Karriere</a><a href="#kontakt">Kontakt</a><a href="#spenden">Spenden</a></div></div>
<nav class="main-nav page-width" aria-label="Hauptnavigation"><a href="#leistungen">Leistungen</a><a href="#kurse">Kurse/Seminare</a><a href="#sozialkaufhaus">Sozialkaufhaus<br>Möbeldienst</a><a href="#veranstaltungen">Veranstaltungen</a><a class="active" href="#projekte">Unsere Projekte</a><a href="#ueaz">ÜAZ</a><a href="#ueber-uns">Über Uns</a></nav>
</header>
<main id="main">
<div class="green-rule"></div>
<div class="page-width breadcrumb"><a href="/">SUFW</a><span>→</span><a href="#projekte">Unsere Projekte</a><span>→</span><a href="#projekte">Unterstützung bei Erwerbslosigkeit</a><span>→</span><span>PerspektivWerk</span></div>
<section class="intro page-width"><h1>PerspektivWerk – Brücke zwischen Diagnostik, Begleitung und betrieblicher Praxis</h1><img class="project-logo" src="media/logo-perspektivwerk.jpg" alt="PerspektivWerk"><div class="intro-copy"><p>Unser Fachpersonal arbeitet mit Ihnen gemeinsam daran, <strong>Ihre aktuelle Lebenssituation zu verstehen.</strong> Ziel ist es, aus den Informationen individuelle und zu Ihnen <strong>passende Wege ins Arbeitsleben</strong> sichtbar zu machen.</p><p>Dazu gehört es, herauszufinden, welche <strong>Herausforderungen Sie im Alltag</strong> bestreiten müssen und wo es Unterstützungsbedarf gibt. Vor allem aber auch, wo Ihre Fähigkeiten, Interessen und Entwicklungsmöglichkeiten liegen. Dabei arbeiten wir eng mit den beratenden Fachkräften der Agentur für Arbeit und des Jobcenters zusammen.</p></div></section>
<section class="team-section"><div class="team-copy"><img src="media/wir-sind-fuer-sie-da.svg" alt="Wir sind für Sie da"><p>Unser Team, bestehend aus sozialpädagogischen, pädagogischen und psychologischen Mitarbeiterinnen und Mitarbeitern, <strong>unterstützt Ihren Prozess der beruflichen Orientierung.</strong> Wir arbeiten eng mit den Bearbeiterinnen und Beratern der Agentur für Arbeit, dem Jobcenter und weiteren Beratungsstellen zusammen.</p><p>Die Teilnahme am <strong>PerspektivWerk ist kostenlos.</strong> Sie bestimmen, an welchen Angeboten Sie teilnehmen.</p></div><div class="team-image"><img src="media/perspektivwerk-psych.jpg" alt="Beratungsgespräch im PerspektivWerk"></div></section>
<section class="content page-width" id="projekte"><div class="content-grid"><article><h2>Wer kann zu uns kommen?</h2><p>Menschen zwischen 15 und 65 Jahren, die sich beruflich neu orientieren möchten, beim Einstieg Unterstützung suchen oder ihre Möglichkeiten gemeinsam klären wollen.</p></article><article><h2>1. Orientierung &amp; Ersteinschätzung</h2><p>Sozialpädagogische und psychologische Module helfen dabei, persönliche Situation, Motivation, Belastbarkeit und Stärken einzuschätzen.</p></article><article><h2>2. Praktische Erprobung &amp; Belastungstest</h2><p>Arbeitsproben und praktische Erprobungen machen fachliche, soziale und arbeitsbezogene Kompetenzen sichtbar.</p></article><article><h2>3. Auswertung &amp; Perspektiventwicklung</h2><p>Wir führen die Ergebnisse zusammen und entwickeln konkrete, realistische nächste Schritte.</p></article></div></section>
<section class="contact page-width" id="kontakt"><h2>Sie haben Fragen zu dieser Maßnahme?</h2><p>Haben Sie Interesse an unserem Angebot, melden Sie sich bei uns. Wir beraten Sie gern vorab zu den weiteren Schritten.</p><p><strong>Kontakt:</strong> <a href="tel:+4917660328929">(0176) 60328929</a> · <a href="mailto:perspektivwerk@sufw.de">perspektivwerk@sufw.de</a> · Dresdner Straße 16, 01326 Dresden</p></section>
</main>
<footer><div class="page-width">Sächsisches Umschulungs- und Fortbildungswerk Dresden e. V.</div></footer>
</body>
</html>
Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 178 KiB

@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" id="Ebene_1" x="0px" y="0px" viewBox="0 0 173 96.8" style="enable-background:new 0 0 173 96.8;" xml:space="preserve" width="400" height="224">
<style type="text/css">
.st0{fill:#FFFFFF;}
.st1{fill:#159A34;}
</style>
<polygon class="st0" points="0,95.2 0.1,60.4 97.9,49.3 97.6,84.1 "/>
<polygon class="st0" points="0.1,54.4 0.1,19.8 173,0 172.7,34.7 "/>
<g>
<path class="st1" d="M152.5,13.1l2.2-0.2c1.4-0.2,2.1,0.7,2.1,2.5c0,0.8-0.2,1.5-0.6,2c-0.4,0.5-0.9,0.8-1.7,0.9l-2.1,0.2 L152.5,13.1z M156.9,27.9l4-0.5l0-0.2l-3.1-7.2c1.8-1.2,2.7-3,2.7-5.5c0-1.8-0.5-3.1-1.5-4c-1-0.9-2.4-1.2-4.3-1l-5.9,0.7 l-0.2,18.5l3.7-0.4l0.1-6.8l1.8-0.2L156.9,27.9z M140.9,9.6c0.3,0.3,0.7,0.4,1.3,0.3c0.5-0.1,0.9-0.3,1.3-0.6 c0.3-0.4,0.5-0.7,0.5-1.2c0-0.5-0.2-0.8-0.5-1.1c-0.3-0.3-0.7-0.4-1.2-0.3c-0.5,0.1-0.9,0.3-1.2,0.6c-0.3,0.3-0.5,0.7-0.5,1.2 C140.4,9,140.5,9.4,140.9,9.6 M134.8,10.3c0.3,0.3,0.7,0.4,1.2,0.3c0.5-0.1,0.9-0.3,1.2-0.6c0.3-0.3,0.5-0.7,0.5-1.2 c0-0.5-0.2-0.8-0.5-1.1c-0.3-0.3-0.7-0.4-1.2-0.3s-0.9,0.3-1.2,0.6s-0.5,0.8-0.5,1.2C134.3,9.7,134.4,10.1,134.8,10.3 M141.4,11.2 L141.3,24c0,1-0.2,1.8-0.5,2.2c-0.3,0.5-0.9,0.8-1.8,0.9c-0.9,0.1-1.5-0.1-1.8-0.5c-0.3-0.4-0.5-1.1-0.5-2.2l0.1-12.7l-3.7,0.4 L133,24.9c0,2,0.5,3.4,1.5,4.3c1,0.9,2.5,1.3,4.5,1c1.9-0.2,3.4-0.9,4.4-2c1-1.1,1.6-2.7,1.6-4.6l0.1-12.8L141.4,11.2z M129.5,20.4 l-5.7,0.7l0-4.7l6.4-0.7l0-3.1l-10.1,1.2L120,32.1l3.7-0.4l0.1-7.5l5.7-0.7L129.5,20.4z M103.9,18.6c1.1-0.1,1.9,0.2,2.4,0.8 c0.5,0.6,0.7,1.8,0.7,3.5l0,3.2c0,1.6-0.3,2.8-0.8,3.5c-0.5,0.7-1.4,1.1-2.6,1.3l-1.1,0.1l0.1-12.3L103.9,18.6z M103.5,34 c2.2-0.3,4-1.1,5.2-2.7c1.3-1.5,1.9-3.5,1.9-5.9l0-3c0-2.4-0.6-4.2-1.9-5.4c-1.3-1.2-2.9-1.7-5.1-1.5l-4.8,0.5l-0.2,18.5L103.5,34z M95,16.5l-3.7,0.4L91.3,29L86,17.5l-3.7,0.4l-0.2,18.5l3.7-0.4l0.1-12.1l5.3,11.5l3.7-0.4L95,16.5z M78.3,18.4l-3.7,0.4l-0.2,18.5 l3.7-0.4L78.3,18.4z M65.4,35.6c-0.9,0.1-1.6-0.1-2-0.5c-0.4-0.4-0.6-1.2-0.6-2.3l-3.7,0.4c0,1.2,0.3,2.3,0.8,3.1 c0.5,0.9,1.3,1.5,2.3,1.8c1,0.4,2,0.5,3.2,0.4c1.7-0.2,3.1-0.8,4.1-1.8c1-1,1.5-2.3,1.5-3.9c0-1.5-0.4-2.6-1.2-3.5s-2.1-1.5-3.9-2 c-1-0.3-1.7-0.7-2.1-1c-0.4-0.4-0.6-0.8-0.6-1.3c0-0.7,0.2-1.2,0.6-1.6c0.4-0.4,0.9-0.7,1.5-0.7c0.7-0.1,1.2,0.1,1.6,0.5 c0.4,0.4,0.5,1,0.5,1.9l3.7-0.4c0-1.1-0.2-2.1-0.7-2.9c-0.5-0.8-1.1-1.4-2-1.8c-0.9-0.4-1.9-0.5-3-0.4c-1.7,0.2-3.1,0.8-4.2,1.9 c-1.1,1.1-1.7,2.4-1.7,3.9c0,1.3,0.4,2.4,1.2,3.2c0.8,0.9,2.1,1.5,3.9,2c1,0.3,1.7,0.6,2.1,1c0.4,0.3,0.6,0.9,0.6,1.6 C67.3,34.7,66.6,35.4,65.4,35.6 M42.4,25.6l2.2-0.2c1.4-0.2,2.1,0.7,2.1,2.5c0,0.8-0.2,1.5-0.6,2c-0.4,0.5-0.9,0.8-1.7,0.9 l-2.1,0.2L42.4,25.6z M46.8,40.4l4-0.5l0-0.2l-3.1-7.2c1.8-1.2,2.7-3,2.7-5.5c0-1.8-0.5-3.1-1.5-4c-1-0.9-2.4-1.2-4.3-1l-5.9,0.7 l-0.2,18.5l3.7-0.4l0.1-6.8l1.8-0.2L46.8,40.4z M34.7,23.4L31,23.8l-0.2,18.5l3.7-0.4L34.7,23.4z M20.5,25l-3.1,0.4l-2.2,11.8 l-1.6-11.4l-3.7,0.4L13,44.3l3.7-0.4l2.2-11.1l2,10.6l3.7-0.4L28,24.1l-3.6,0.4l-1.8,11.8L20.5,25z"/>
<path class="st1" d="M85,76.6c0.4,0.3,0.8,0.5,1.4,0.4c0.6-0.1,1-0.3,1.4-0.7c0.4-0.4,0.5-0.9,0.5-1.5c0-0.6-0.2-1-0.5-1.4 C87.4,73.1,87,73,86.4,73c-0.6,0.1-1,0.3-1.4,0.7c-0.4,0.4-0.5,0.9-0.6,1.5C84.4,75.8,84.6,76.2,85,76.6 M88.4,58l-3.8,0.4L85,71.2 l2.9-0.3L88.4,58z M74.9,64.6l1.6,6.4l-3.4,0.4L74.9,64.6z M78.3,77.7l3.9-0.4l-5.6-17.8l-3.4,0.4l-5.9,19.1l3.9-0.4l1-3.9l5-0.6 L78.3,77.7z M58.7,64.5c1.1-0.1,1.9,0.2,2.4,0.8c0.5,0.6,0.7,1.8,0.7,3.5l0,3.2c0,1.6-0.3,2.8-0.8,3.5c-0.5,0.7-1.4,1.1-2.6,1.3 L57.2,77l0.1-12.3L58.7,64.5z M58.2,79.9c2.2-0.3,4-1.1,5.2-2.7c1.3-1.5,1.9-3.5,1.9-5.9l0-3c0-2.4-0.6-4.2-1.9-5.4 c-1.3-1.2-2.9-1.7-5.1-1.5L53.7,62l-0.2,18.5L58.2,79.9z M43.6,70.6l-5.7,0.7l0-4.4l6.8-0.8l0-3.1l-10.4,1.2l-0.2,18.5l10.5-1.2 l0-3.1l-6.8,0.8l0-4.9l5.7-0.7L43.6,70.6z M30.3,64.7l-3.7,0.4l-0.2,18.5l3.7-0.4L30.3,64.7z M17.4,81.8c-0.9,0.1-1.6-0.1-2-0.5 c-0.4-0.4-0.6-1.2-0.6-2.3l-3.7,0.4c0,1.2,0.3,2.3,0.8,3.1c0.5,0.9,1.3,1.5,2.3,1.8c1,0.4,2,0.5,3.2,0.4c1.7-0.2,3.1-0.8,4.1-1.8 c1-1,1.5-2.3,1.5-3.9c0-1.5-0.4-2.6-1.2-3.5c-0.8-0.9-2.1-1.5-3.9-2c-1-0.3-1.7-0.7-2.1-1c-0.4-0.4-0.6-0.8-0.6-1.3 c0-0.7,0.2-1.2,0.6-1.6c0.4-0.4,0.9-0.7,1.5-0.7c0.7-0.1,1.2,0.1,1.6,0.5c0.4,0.4,0.5,1,0.5,1.9l3.7-0.4c0-1.1-0.2-2.1-0.7-2.9 c-0.5-0.8-1.1-1.4-2-1.8c-0.9-0.4-1.9-0.5-3-0.4c-1.7,0.2-3.1,0.8-4.2,1.9c-1.1,1.1-1.7,2.4-1.7,3.9c0,1.3,0.4,2.4,1.2,3.2 c0.8,0.9,2.1,1.5,3.9,2c1,0.3,1.7,0.6,2.1,1c0.4,0.3,0.6,0.9,0.6,1.6C19.3,80.9,18.6,81.7,17.4,81.8"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 4.4 KiB

@@ -0,0 +1 @@
:root{--sufw-green:#159a34;--ink:#1d1d1b;--body:#5a5a5a;--line:#d7d7d7;--pale:#efefef}*{box-sizing:border-box}html{scroll-behavior:smooth}body{margin:0;background:#fff;color:var(--body);font:16px/1.5 Arial,"Helvetica Neue",sans-serif}.page-width{width:min(1240px,calc(100% - 52px));margin:auto}.skip-link{position:absolute;left:-10000px}.skip-link:focus{left:1rem;top:1rem;z-index:10;padding:.5rem;background:#fff}.site-header{background:#fff}.header-top{min-height:66px;display:flex;align-items:center;justify-content:space-between}.brand img{display:block;width:196px;height:auto}.quick-links{display:flex;align-items:center;gap:14px;font-size:14px}.quick-links a{color:var(--ink);text-decoration:none}.quick-links strong{color:var(--sufw-green);font-size:18px}.round-icon{display:grid;place-items:center;width:29px;height:29px;border-radius:50%;background:var(--sufw-green);color:#fff;font-size:12px}.search{height:34px;width:215px;border:1px solid #cbd0d6;display:flex;align-items:center;padding-left:8px}.search input{border:0;outline:0;width:100%;font:inherit}.search b{font-size:23px;color:#777;padding:0 6px}.main-nav{height:62px;display:flex;justify-content:flex-end;align-items:center}.main-nav a{padding:2px 18px;border-right:1px solid var(--line);color:var(--ink);font-size:18px;line-height:1.22;text-decoration:none}.main-nav a:last-child{border:0}.main-nav .active{font-weight:700}.green-rule{height:10px;background:var(--sufw-green)}.breadcrumb{padding:18px 0 34px;display:flex;gap:5px;flex-wrap:wrap;font-size:14px}.breadcrumb a{color:var(--sufw-green)}.intro{text-align:center;padding-bottom:58px}.intro h1{margin:0 auto 34px;max-width:850px;color:var(--sufw-green);font-size:20px;line-height:1.3}.project-logo{width:240px;display:block;margin:0 auto 25px}.intro-copy{max-width:900px;margin:auto;color:#272727;font-size:18px;line-height:1.48}.intro-copy p{margin:0 0 18px}.team-section{display:grid;grid-template-columns:44% 56%;align-items:stretch}.team-copy{padding:50px max(8vw,calc((100vw - 1100px)/2));padding-right:7vw;background:var(--sufw-green);color:#fff;font-size:18px;line-height:1.5}.team-copy img{display:block;width:min(280px,100%);margin-bottom:25px}.team-image img{display:block;width:100%;height:100%;min-height:490px;object-fit:cover}.content{padding:70px 0}.content-grid{display:grid;grid-template-columns:1fr 1fr;gap:46px 80px}.content h2,.booking h2,.contact h2{color:var(--sufw-green);font-size:22px;margin:0 0 13px}.content h2::before{content:"●";font-size:23px;margin-right:14px}.content p{margin:0}.booking{padding:35px 0 85px}.booking-heading{border-top:7px solid var(--sufw-green);padding-top:25px;display:flex;justify-content:space-between;align-items:end;gap:20px}.booking-heading p{margin:0}.booking-tabs{display:flex;border-bottom:1px solid var(--line)}.booking-tabs button{font:inherit;color:var(--body);background:#fff;border:0;border-bottom:4px solid transparent;padding:11px 16px;cursor:pointer}.booking-tabs .is-active{border-color:var(--sufw-green);color:var(--ink);font-weight:bold}.booking-list{display:grid;gap:10px;margin-top:24px}.booking-card{display:flex;justify-content:space-between;align-items:center;gap:20px;border:1px solid var(--line);border-left:6px solid var(--sufw-green);padding:15px 20px;background:#fff}.booking-card h3{margin:0;color:var(--ink);font-size:17px}.booking-card p{margin:3px 0 0}.button{display:inline-block;background:var(--sufw-green);color:#fff;text-decoration:none;padding:9px 13px;font-weight:bold;font-size:14px;white-space:nowrap}.contact{border-top:1px solid var(--line);padding:50px 0 70px}.contact a{color:var(--sufw-green)}footer{background:var(--sufw-green);padding:25px 0;color:#fff}@media(max-width:900px){.quick-links>a,.quick-links strong,.round-icon{display:none}.main-nav{justify-content:flex-start;overflow:auto}.main-nav a{font-size:15px;padding:2px 12px;white-space:nowrap}.team-section{grid-template-columns:1fr}.team-copy{padding:42px 28px}.team-image img{min-height:auto}.content-grid{gap:35px}.booking-heading{align-items:start;flex-direction:column}}@media(max-width:560px){.page-width{width:min(100% - 28px,1240px)}.header-top{min-height:72px}.brand img{width:155px}.search{width:130px}.main-nav{height:50px}.breadcrumb{padding:15px 0 24px}.intro h1{font-size:18px}.intro-copy{font-size:16px}.content-grid{grid-template-columns:1fr}.booking-card{display:block}.booking-card .button{margin-top:12px}.booking-tabs{width:100%}.booking-tabs button{padding:10px 9px;font-size:14px}}
+58
View File
@@ -0,0 +1,58 @@
<?php
declare(strict_types=1);
/*
* This file is part of Contao.
*
* (c) Leo Feyer
*
* @license LGPL-3.0-or-later
*/
use Contao\ManagerBundle\HttpKernel\ContaoKernel;
use FOS\HttpCache\TagHeaderFormatter\TagHeaderFormatter;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\TerminableInterface;
// Suppress error messages (see #1422)
@ini_set('display_errors', '0');
// Disable the phar stream wrapper for security reasons (see #105)
if (in_array('phar', stream_get_wrappers(), true)) {
stream_wrapper_unregister('phar');
}
// System maintenance mode comes first as it has to work even if the vendor directory does not exist
if (file_exists(__DIR__.'/../var/maintenance.html')) {
$contents = file_get_contents(__DIR__.'/../var/maintenance.html');
http_response_code(503);
header('Content-Type: text/html; charset=UTF-8');
header('Content-Length: '.strlen((string) $contents));
header('Cache-Control: no-store');
die($contents);
}
$loader = require __DIR__.'/../vendor/autoload.php';
$request = Request::createFromGlobals();
$request->attributes->set('_preview', true);
$kernel = ContaoKernel::fromRequest(dirname(__DIR__), $request);
$response = $kernel->handle($request);
// Prevent preview URLs from being indexed
$response->headers->set('X-Robots-Tag', 'noindex');
// Force no-cache on all responses in the preview front controller
$response->headers->set('Cache-Control', 'no-store');
// Strip all tag headers from the response
$response->headers->remove(TagHeaderFormatter::DEFAULT_HEADER_NAME);
$response->send();
if ($kernel instanceof TerminableInterface) {
$kernel->terminate($request, $response);
}
+1 -1
View File
@@ -5,7 +5,7 @@
"moduleResolution": "Bundler", "moduleResolution": "Bundler",
"strict": true, "strict": true,
"noEmitOnError": true, "noEmitOnError": true,
"outDir": "public/assets/js" "outDir": "public/perspektivwerk/js"
}, },
"include": ["src/**/*.ts"] "include": ["src/**/*.ts"]
} }